public void TestEditRecurringGiftOnlyChangePayment()
        {
            const string authUserToken = "auth";
            var today = DateTime.Today;

            var editGift = new RecurringGiftDto
            {
                RecurringGiftId = 345,
                StripeTokenId = "tok_123",
                PlanAmount = 500M,
                Program = "3",
                PlanInterval = PlanInterval.Weekly,
                StartDate = today
            };

            var donor = new ContactDonor
            {
                DonorId = 456,
                ProcessorId = "cus_123"
            };

            var existingGift = new CreateDonationDistDto
            {
                Amount = 50000,
                ProgramId = "3",
                Frequency = 1,
                StartDate = today,
                DonorAccountId = 234,
                SubscriptionId = "sub_123",
                DayOfWeek = (int)today.DayOfWeek,
                RecurringGiftId = 345,
                DonorId = 789,
                StripeCustomerId = "cus_456",
                StripeAccountId = "card_456"
            };

            var stripeSource = new SourceData
            {
                id = "bank_1234",
                bank_last4 = "5678"
            };


            const int newDonorAccountId = 987;

            _mpDonorService.Setup(mocked => mocked.GetRecurringGiftById(authUserToken, editGift.RecurringGiftId)).Returns(existingGift);
            _paymentService.Setup(mocked => mocked.UpdateCustomerSource(existingGift.StripeCustomerId, editGift.StripeTokenId)).Returns(stripeSource);
            _mpDonorService.Setup(mocked => mocked.CreateDonorAccount(null, "0", stripeSource.bank_last4, null, existingGift.DonorId, stripeSource.id, existingGift.StripeCustomerId)).Returns(newDonorAccountId);
            _mpDonorService.Setup(mocked => mocked.UpdateRecurringGiftDonorAccount(authUserToken, existingGift.RecurringGiftId.Value, newDonorAccountId));

            var result = _fixture.EditRecurringGift(authUserToken, editGift, donor);
            _mpDonorService.VerifyAll();
            _paymentService.VerifyAll();

            Assert.IsNotNull(result);
        }
        public void TestEditRecurringGiftChangePaymentAndStartDate()
        {
            const string authUserToken = "auth";
            var today = DateTime.Today;
            const int congregationId = 1;

            var editGift = new RecurringGiftDto
            {
                RecurringGiftId = 345,
                StripeTokenId = "tok_123",
                PlanAmount = 800M,
                Program = "3",
                PlanInterval = PlanInterval.Weekly,
                StartDate = today
            };

            var donor = new ContactDonor
            {
                DonorId = 456,
                ProcessorId = "cus_123",
                Email = "*****@*****.**"
            };

            var existingGift = new CreateDonationDistDto
            {
                Amount = 50000,
                ProgramId = "3",
                Frequency = 1,
                StartDate = today.AddDays(-7),
                DonorAccountId = 234,
                SubscriptionId = "sub_123",
                DayOfWeek = (int)today.AddDays(-7).DayOfWeek,
                RecurringGiftId = 345,
                DonorId = 789,
                StripeCustomerId = "cus_456",
                StripeAccountId = "card_456"
            };

            var stripeSource = new SourceData
            {
                brand = "Visa",
                last4 = "1234",
                id = "card_123"
            };

            const int newDonorAccountId = 987;

            var oldSubscription = new StripeSubscription
            {
                Id = "sub_123",
                Plan = new StripePlan
                {
                    Id = "plan_123"
                }
            };

            var newPlan = new StripePlan
            {
                Id = "plan_456"
            };

            var newSubscription = new StripeSubscription
            {
                Id = "sub_456"
            };

            const int newRecurringGiftId = 765;

            var newRecurringGift = new CreateDonationDistDto
            {
                Amount = 80000,
                ProgramId = "3",
                Frequency = 1,
                StartDate = today,
                DonorAccountId = 234,
                SubscriptionId = "sub_456",
                DayOfWeek = (int)today.DayOfWeek,
                RecurringGiftId = newRecurringGiftId,
                DonorId = 789
            };

            var contact = new MyContact()
            {
                Congregation_ID = congregationId
            };

            _mpDonorService.Setup(mocked => mocked.GetRecurringGiftById(authUserToken, editGift.RecurringGiftId)).Returns(existingGift);
            _paymentService.Setup(mocked => mocked.UpdateCustomerSource(existingGift.StripeCustomerId, editGift.StripeTokenId)).Returns(stripeSource);
            _mpDonorService.Setup(mocked => mocked.CreateDonorAccount(stripeSource.brand, "0", stripeSource.last4, null, existingGift.DonorId, stripeSource.id, existingGift.StripeCustomerId)).Returns(newDonorAccountId);
            _paymentService.Setup(mocked => mocked.CancelSubscription(existingGift.StripeCustomerId, existingGift.SubscriptionId)).Returns(oldSubscription);
            _paymentService.Setup(mocked => mocked.CreateSubscription(newPlan.Id, existingGift.StripeCustomerId, newRecurringGift.StartDate.Value)).Returns(newSubscription);
            _paymentService.Setup(mocked => mocked.CancelPlan(oldSubscription.Plan.Id)).Returns(oldSubscription.Plan);
            _paymentService.Setup(mocked => mocked.CreatePlan(editGift, donor)).Returns(newPlan);
            _mpDonorService.Setup(mocked => mocked.CancelRecurringGift(authUserToken, existingGift.RecurringGiftId.Value));
            _mpContactService.Setup(mocked => mocked.GetContactById(donor.ContactId)).Returns(contact);
            _mpDonorService.Setup(
                mocked =>
                    mocked.CreateRecurringGiftRecord(authUserToken,
                                                     donor.DonorId,
                                                     newDonorAccountId,
                                                     EnumMemberSerializationUtils.ToEnumString(editGift.PlanInterval),
                                                     editGift.PlanAmount,
                                                     editGift.StartDate,
                                                     editGift.Program,
                                                     newSubscription.Id, contact.Congregation_ID.Value)).Returns(newRecurringGiftId);
            _mpDonorService.Setup(mocked => mocked.GetRecurringGiftById(authUserToken, newRecurringGiftId)).Returns(newRecurringGift);

            var result = _fixture.EditRecurringGift(authUserToken, editGift, donor);
            _mpDonorService.VerifyAll();
            _paymentService.VerifyAll();

            Assert.IsNotNull(result);
            Assert.AreEqual(newRecurringGift.RecurringGiftId, result.RecurringGiftId);
            Assert.AreEqual(newRecurringGift.StartDate, result.StartDate);
            Assert.AreEqual(newRecurringGift.Amount, result.PlanAmount);
            Assert.AreEqual(PlanInterval.Weekly, result.PlanInterval);
            Assert.AreEqual(newRecurringGift.ProgramId, result.Program);
            Assert.AreEqual(newRecurringGift.DonorId, result.DonorID);
            Assert.AreEqual(donor.Email, result.EmailAddress);
            Assert.AreEqual(newSubscription.Id, result.SubscriptionID);
        }
        public void TestCreateRecurringGift()
        {
            var recurringGiftDto = new RecurringGiftDto
            {
                StripeTokenId = "tok_123",
                PlanAmount = 123.45M,
                PlanInterval = PlanInterval.Weekly,
                Program = "987",
                StartDate = DateTime.Parse("1973-10-15")
            };

            var contactDonor = new ContactDonor
            {
                DonorId = 678,
                ProcessorId = "cus_123",
                ContactId = 909090
            };

            var defaultSource = new SourceData
            {
                id = "card_123",
                brand = "Visa",
                last4 = "5150"
            };

            var stripeCustomer = new StripeCustomer
            {
                brand = "visa",
                last4 = "9876",
                id = "cus_123",
                default_source = "card_123",
                sources = new Sources
                {
                    data = new List<SourceData>
                    {
                        new SourceData
                        {
                            id = "bank_123",
                            bank_last4 = "5678"
                        },
                        defaultSource
                    }
                }
            };

            var stripePlan = new StripePlan
            {
                Id = "plan_123"
            };

            const int donorAccountId = 999;

            var stripeSubscription = new StripeSubscription
            {
                Id = "sub_123"
            };

            var contact = new MyContact()
            {
                Congregation_ID = 1
            };
            const int recurringGiftId = 888;

            var recurringGift = new CreateDonationDistDto
            {
                ProgramName = "Crossroads",
                Amount = 123.45M,
                Recurrence = "12th of the month",
                DonorAccountId = 90
            };

            _paymentService.Setup(mocked => mocked.CreateCustomer(recurringGiftDto.StripeTokenId, "678, Recurring Gift Subscription")).Returns(stripeCustomer);
            _paymentService.Setup(mocked => mocked.CreatePlan(recurringGiftDto, contactDonor)).Returns(stripePlan);
            _mpDonorService.Setup(
                mocked =>
                    mocked.CreateDonorAccount(defaultSource.brand,
                                              It.IsAny<string>(),
                                              defaultSource.last4,
                                              null,
                                              contactDonor.DonorId,
                                              defaultSource.id,
                                              stripeCustomer.id)).Returns(donorAccountId);
            _paymentService.Setup(mocked => mocked.CreateSubscription(stripePlan.Id, stripeCustomer.id, recurringGiftDto.StartDate)).Returns(stripeSubscription);
            _mpContactService.Setup(mocked => mocked.GetContactById(contactDonor.ContactId)).Returns(contact);
            _mpDonorService.Setup(
                mocked =>
                    mocked.CreateRecurringGiftRecord("auth", contactDonor.DonorId,
                                                     donorAccountId,
                                                     EnumMemberSerializationUtils.ToEnumString(recurringGiftDto.PlanInterval),
                                                     recurringGiftDto.PlanAmount,
                                                     recurringGiftDto.StartDate,
                                                     recurringGiftDto.Program,
                                                     stripeSubscription.Id, contact.Congregation_ID.Value)).Returns(recurringGiftId);

            _mpDonorService.Setup(mocked => mocked.GetRecurringGiftById("auth", recurringGiftId)).Returns(recurringGift);
            _mpDonorService.Setup(mocked => mocked.GetDonorAccountPymtType(recurringGift.DonorAccountId.Value)).Returns(1);
            _mpDonorService.Setup(
                mocked =>
                    mocked.SendEmail(RecurringGiftSetupEmailTemplateId, recurringGift.DonorId, (int)(123.45M/100), "Check", It.IsAny<DateTime>(), "Crossroads", string.Empty, "12th of the month"));

            var response = _fixture.CreateRecurringGift("auth", recurringGiftDto, contactDonor);
            _paymentService.VerifyAll();
            _mpDonorService.VerifyAll();
            Assert.AreEqual(recurringGiftId, response);
        }
        public void TestCreateRecurringGiftWholeLottaFailures()
        {
            var recurringGiftDto = new RecurringGiftDto
            {
                StripeTokenId = "tok_123",
                PlanAmount = 123.45M,
                PlanInterval = PlanInterval.Weekly,
                Program = "987",
                StartDate = DateTime.Parse("1973-10-15")
            };

            var contactDonor = new ContactDonor
            {
                DonorId = 678,
                ProcessorId = "cus_123",
                ContactId = 909090
            };

            var defaultSource = new SourceData
            {
                id = "card_123",
                brand = "Visa",
                last4 = "5150"
            };

            var stripeCustomer = new StripeCustomer
            {
                brand = "visa",
                last4 = "9876",
                id = "cus_123",
                default_source = "card_123",
                sources = new Sources
                {
                    data = new List<SourceData>
                    {
                        new SourceData
                        {
                            id = "bank_123",
                            bank_last4 = "5678"
                        },
                        defaultSource
                    }
                }
            };

            var stripePlan = new StripePlan
            {
                Id = "plan_123"
            };

            const int donorAccountId = 999;

            var stripeSubscription = new StripeSubscription
            {
                Id = "sub_123"
            };

            var contact = new MyContact()
            {
                Congregation_ID = 1
            };

            _paymentService.Setup(mocked => mocked.CreateCustomer(recurringGiftDto.StripeTokenId, "678, Recurring Gift Subscription")).Returns(stripeCustomer);
            _paymentService.Setup(mocked => mocked.CreatePlan(recurringGiftDto, contactDonor)).Returns(stripePlan);
            _mpDonorService.Setup(
                mocked =>
                    mocked.CreateDonorAccount(defaultSource.brand,
                                              It.IsAny<string>(),
                                              defaultSource.last4,
                                              null,
                                              contactDonor.DonorId,
                                              defaultSource.id,
                                              stripeCustomer.id)).Returns(donorAccountId);
            _paymentService.Setup(mocked => mocked.CreateSubscription(stripePlan.Id, stripeCustomer.id, recurringGiftDto.StartDate)).Returns(stripeSubscription);
            _mpContactService.Setup(mocked => mocked.GetContactById(contactDonor.ContactId)).Returns(contact);
            var exception = new ApplicationException("Do it to it Lars");
            _mpDonorService.Setup(
                mocked =>
                    mocked.CreateRecurringGiftRecord("auth",
                                                     contactDonor.DonorId,
                                                     donorAccountId,
                                                     EnumMemberSerializationUtils.ToEnumString(recurringGiftDto.PlanInterval),
                                                     recurringGiftDto.PlanAmount,
                                                     recurringGiftDto.StartDate,
                                                     recurringGiftDto.Program,
                                                     stripeSubscription.Id,
                                                     contact.Congregation_ID.Value)).Throws(exception);

            _paymentService.Setup(mocked => mocked.CancelSubscription(stripeCustomer.id, stripeSubscription.Id)).Throws(new Exception());
            _paymentService.Setup(mocked => mocked.CancelPlan(stripePlan.Id)).Throws(new Exception());
            _paymentService.Setup(mocked => mocked.DeleteCustomer(stripeCustomer.id)).Throws(new Exception());
            _mpDonorService.Setup(mocked => mocked.DeleteDonorAccount("auth", donorAccountId)).Throws(new Exception());

            try
            {
                _fixture.CreateRecurringGift("auth", recurringGiftDto, contactDonor);
                Assert.Fail("Expected exception was not thrown");
            }
            catch (ApplicationException e)
            {
                Assert.AreSame(exception, e);
            }
            _paymentService.VerifyAll();
            _mpDonorService.VerifyAll();
            _mpContactService.VerifyAll();
        }
        public void TestGetSuccessGetDonorAuthenticated()
        {
            var contactDonor = new ContactDonor
            {
                ContactId = 1,
                DonorId = 394256,
                ProcessorId = ProcessorId
            };

            var defaultSource = new SourceData
            {
                last4 = "1234",
                brand = "Visa",
                address_zip = "45454"
            };
            
            _donorService.Setup(mocked => mocked.GetContactDonorForAuthenticatedUser(It.IsAny<string>())).Returns(contactDonor);
            _paymentService.Setup(mocked => mocked.GetDefaultSource(It.IsAny<string>())).Returns(defaultSource);
            IHttpActionResult result = _fixture.Get();
            Assert.IsNotNull(result);
            Assert.IsInstanceOf(typeof(OkNegotiatedContentResult<DonorDTO>), result);
            var okResult = (OkNegotiatedContentResult<DonorDTO>)result;
            Assert.AreEqual(DonorId, okResult.Content.Id);
            Assert.AreEqual(ProcessorId, okResult.Content.ProcessorId);
            Assert.AreEqual(Brand, okResult.Content.DefaultSource.credit_card.brand);
            Assert.AreEqual(Last4, okResult.Content.DefaultSource.credit_card.last4);
            Assert.AreEqual(AddressZip, okResult.Content.DefaultSource.credit_card.address_zip);
        }
        public void TestUpdateDonorRegisteredDonor()
        {
            var dto = new UpdateDonorDTO
            {
                DonorId = "123",
                EmailAddress = "*****@*****.**",
                StripeTokenId = "456"
            };

            var contactDonor = new ContactDonor
            {
                DonorId = 123,
                ContactId = 789,
                Email = "*****@*****.**",
                ProcessorId = "102030",
                RegisteredUser = true,
            };

            var sourceData = new SourceData
            {
                brand = "Visa",
                last4 = "5432",
                address_zip = "90210",
                exp_month = "12",
                exp_year = "19"
            };

            _donorService.Setup(mocked => mocked.GetContactDonorForAuthenticatedUser(It.IsAny<string>())).Returns(contactDonor);
            _paymentService.Setup(mocked => mocked.UpdateCustomerSource(contactDonor.ProcessorId, dto.StripeTokenId))
                .Returns(sourceData);

            var result = _fixture.UpdateDonor(dto);
            _donorService.VerifyAll();
            _paymentService.VerifyAll();

            Assert.NotNull(result);
            Assert.IsInstanceOf<OkNegotiatedContentResult<DonorDTO>>(result);
            var donorDto = ((OkNegotiatedContentResult<DonorDTO>)result).Content;
            Assert.AreEqual(contactDonor.DonorId, donorDto.Id);
            Assert.AreEqual(contactDonor.ProcessorId, donorDto.ProcessorId);
            Assert.AreEqual(contactDonor.RegisteredUser, donorDto.RegisteredUser);
            Assert.IsNotNull(donorDto.DefaultSource.bank_account);
            Assert.IsNotNull(donorDto.DefaultSource.credit_card);
            Assert.AreEqual(sourceData.brand, donorDto.DefaultSource.credit_card.brand);
            Assert.AreEqual(sourceData.last4, donorDto.DefaultSource.credit_card.last4);
            Assert.AreEqual(sourceData.address_zip, donorDto.DefaultSource.credit_card.address_zip);
            Assert.AreEqual(sourceData.exp_month + sourceData.exp_year, donorDto.DefaultSource.credit_card.exp_date);
        }
        public void TestUpdateDonorGuestDonor()
        {
            _fixture.Request.Headers.Authorization = null;
            var dto = new UpdateDonorDTO
            {
                DonorId = "123",
                EmailAddress = "*****@*****.**",
                StripeTokenId = "456"
            };

            var contactDonor = new ContactDonor
            {
                DonorId = 123,
                ContactId = 789,
                Email = "*****@*****.**",
                ProcessorId = "102030",
                RegisteredUser = false,
            };

            var sourceData = new SourceData
            {
                bank_last4 = "5555",
                routing_number = "987654321"
            };

            _donorService.Setup(mocked => mocked.GetContactDonorForEmail("*****@*****.**")).Returns(contactDonor);
            _paymentService.Setup(mocked => mocked.UpdateCustomerSource(contactDonor.ProcessorId, dto.StripeTokenId))
                .Returns(sourceData);

            var result = _fixture.UpdateDonor(dto);
            _donorService.VerifyAll();
            _paymentService.VerifyAll();

            Assert.NotNull(result);
            Assert.IsInstanceOf<OkNegotiatedContentResult<DonorDTO>>(result);
            var donorDto = ((OkNegotiatedContentResult<DonorDTO>) result).Content;
            Assert.AreEqual(contactDonor.DonorId, donorDto.Id);
            Assert.AreEqual(contactDonor.ProcessorId, donorDto.ProcessorId);
            Assert.AreEqual(contactDonor.RegisteredUser, donorDto.RegisteredUser);

            Assert.IsNotNull(donorDto.DefaultSource.credit_card);
            Assert.IsNotNull(donorDto.DefaultSource.bank_account);
            Assert.AreEqual(sourceData.bank_last4, donorDto.DefaultSource.bank_account.last4);
            Assert.AreEqual(sourceData.routing_number, donorDto.DefaultSource.bank_account.routing);
        }
        private static SourceData MapDefaultSource(List<SourceData>sources, string defaultSourceId)
        {
            var defaultSource = new SourceData();

            foreach (var source in sources.Where(source => source.id == defaultSourceId))
            {
                defaultSource.@object = source.@object;
                if (source.@object == "bank_account")
                {
                    defaultSource.routing_number = source.routing_number;
                    defaultSource.bank_last4 = source.last4;
                }
                else
                {
                    defaultSource.brand = source.brand;
                    defaultSource.last4 = source.last4;
                    defaultSource.address_zip = source.address_zip;
                    defaultSource.exp_month = source.exp_month.PadLeft(2, '0');
                    defaultSource.exp_year = source.exp_year.Substring(2, 2);
                }
                defaultSource.id = defaultSourceId;
            }

            return defaultSource;
        }
        public void TestGetSource()
        {
            var expectedSource = new SourceData
            {
                id = "ba_456"
            };

            var customer = new StripeCustomer
            {
                sources = new Sources
                {
                    data = new List<SourceData>
                    {
                        new SourceData
                        {
                            id = "card_123"
                        },
                        expectedSource,
                        new SourceData
                        {
                            id = "card_789"
                        }
                    }
                }
            };

            var response = new Mock<IRestResponse<StripeCustomer>>();

            response.SetupGet(mocked => mocked.ResponseStatus).Returns(ResponseStatus.Completed).Verifiable();
            response.SetupGet(mocked => mocked.StatusCode).Returns(HttpStatusCode.OK).Verifiable();
            response.SetupGet(mocked => mocked.Data).Returns(customer).Verifiable();

            _restClient.Setup(mocked => mocked.Execute<StripeCustomer>(It.IsAny<IRestRequest>())).Returns(response.Object);

            var result = _fixture.GetSource("cus_123", "ba_456");

            _restClient.Verify(mocked => mocked.Execute<StripeCustomer>(
                It.Is<RestRequest>(o =>
                    o.Method == Method.GET
                    && o.Resource.Equals("/customers/cus_123")
            )));

            _restClient.VerifyAll();
            response.VerifyAll();

            Assert.IsNotNull(result);
            Assert.AreSame(expectedSource, result);
        }