public void CreateDonationAndDistributionRecordWithPledge()
        {
            const decimal donationAmt = 676767;
            var feeAmt = 5656;
            var donorId = 1234567;
            var programId = "3";
            var pledgeId = 123;
            var setupDate = DateTime.Now;
            var chargeId = "ch_crds1234567";
            var processorId = "cus_8675309";
            var pymtType = "cc";
            var expectedDonationId = 321321;
            var expectedDonationDistributionId = 231231;
            var checkScannerBatchName = "check scanner batch";
            const string viewKey = "DonorByContactId";
            const string sortString = "";
            var searchString = ",\"" + donorId + "\"";
            var donationPageId = Convert.ToInt32(ConfigurationManager.AppSettings["Donations"]);
            var donationDistPageId = Convert.ToInt32(ConfigurationManager.AppSettings["Distributions"]);
            
            var defaultContact = new MyContact()
            {
                Contact_ID = 1234556,
                Email_Address = "*****@*****.**"
            };

            _ministryPlatformService.Setup(mocked => mocked.CreateRecord(
              donationPageId, It.IsAny<Dictionary<string, object>>(),
              It.IsAny<string>(), true)).Returns(expectedDonationId);

            _ministryPlatformService.Setup(mocked => mocked.CreateRecord(
                donationDistPageId, It.IsAny<Dictionary<string, object>>(),
                It.IsAny<string>(), true)).Returns(expectedDonationDistributionId);
            _contactService.Setup(mocked => mocked.GetContactById(Convert.ToInt32(ConfigurationManager.AppSettings["DefaultGivingContactEmailId"]))).Returns(defaultContact);
            _communicationService.Setup(mocked => mocked.SendMessage(It.IsAny<Communication>()));

            var expectedDonationValues = new Dictionary<string, object>
            {
                {"Donor_ID", donorId},
                {"Donation_Amount", donationAmt},
                {"Processor_Fee_Amount", feeAmt /Constants.StripeDecimalConversionValue},
                {"Payment_Type_ID", 4}, //hardcoded as credit card until ACH stories are worked
                {"Donation_Date", setupDate},
                {"Transaction_code", chargeId},
                {"Registered_Donor", true},
                {"Anonymous", false},
                {"Processor_ID", processorId},
                {"Donation_Status_Date", setupDate},
                {"Donation_Status_ID", 1},
                {"Recurring_Gift_ID", null},
                {"Is_Recurring_Gift", false},
                {"Donor_Account_ID", null},
                {"Check_Scanner_Batch", checkScannerBatchName}
            };

            var expectedDistributionValues = new Dictionary<string, object>
            {
                {"Donation_ID", expectedDonationId},
                {"Amount", donationAmt},
                {"Program_ID", programId},
                {"Pledge_ID", pledgeId}
               
            };

            var programServiceResponse = new Program
            {
                CommunicationTemplateId = 1234,
                ProgramId = 3,
                Name = "Crossroads"
            };

            _programService.Setup(mocked => mocked.GetProgramById(It.IsAny<int>())).Returns(programServiceResponse);

            var dictList = new List<Dictionary<string, object>>();
            dictList.Add(new Dictionary<string, object>()
            {
                {"Donor_ID", donorId},
                {"Processor_ID", "tx_123"},
                {"Email","*****@*****.**"},
                {"Contact_ID","1234"},
                {"Statement_Type", "Individual"},
                {"Statement_Type_ID", 1},
                {"Statement_Frequency", "Quarterly"},
                {"Statement_Method", "None"},
                {"Household_ID", 1}
            });


            _ministryPlatformService.Setup(mocked => mocked.GetPageViewRecords(viewKey, It.IsAny<string>(), searchString, sortString, 0)).Returns(dictList);

            var getTemplateResponse = new MessageTemplate()
            {
                Body = "Test Body Content",
                Subject = "Test Email Subject Line"
            };
            _communicationService.Setup(mocked => mocked.GetTemplate(It.IsAny<int>())).Returns(getTemplateResponse);

            var donationAndDistribution = new DonationAndDistributionRecord
            {
                DonationAmt = donationAmt,
                FeeAmt = feeAmt,
                DonorId = donorId,
                ProgramId = programId,
                ChargeId = chargeId,
                PymtType = pymtType,
                ProcessorId = processorId,
                SetupDate = setupDate,
                RegisteredDonor = true,
                CheckScannerBatchName = checkScannerBatchName,
                PledgeId = pledgeId
            };

            var response = _fixture.CreateDonationAndDistributionRecord(donationAndDistribution);

            // Explicitly verify each expectation...
            _communicationService.Verify(mocked => mocked.SendMessage(It.IsAny<Communication>()));
            _programService.Verify(mocked => mocked.GetProgramById(3));
            _ministryPlatformService.Verify(mocked => mocked.CreateRecord(donationPageId, expectedDonationValues, It.IsAny<string>(), true));
            _ministryPlatformService.Verify(mocked => mocked.CreateRecord(donationDistPageId, expectedDistributionValues, It.IsAny<string>(), true));

            // _ministryPlatformService.VerifyAll();
            _programService.VerifyAll();
            _communicationService.VerifyAll();
            Assert.IsNotNull(response);
            Assert.AreEqual(response, expectedDonationId);
        }
        public int CreateDonationAndDistributionRecord(DonationAndDistributionRecord donationAndDistribution)
        {
            var pymtId = PaymentType.GetPaymentType(donationAndDistribution.PymtType).id;
            var fee = donationAndDistribution.FeeAmt.HasValue ? donationAndDistribution.FeeAmt / Constants.StripeDecimalConversionValue : null;

            var apiToken = ApiLogin();

            var donationValues = new Dictionary<string, object>
            {
                {"Donor_ID", donationAndDistribution.DonorId},
                {"Donation_Amount", donationAndDistribution.DonationAmt},
                {"Processor_Fee_Amount", fee},
                {"Payment_Type_ID", pymtId},
                {"Donation_Date", donationAndDistribution.SetupDate},
                {"Transaction_code", donationAndDistribution.ChargeId},
                {"Registered_Donor", donationAndDistribution.RegisteredDonor},
                {"Anonymous", donationAndDistribution.Anonymous},
                {"Processor_ID", donationAndDistribution.ProcessorId },
                {"Donation_Status_Date", donationAndDistribution.SetupDate},
                {"Donation_Status_ID", donationAndDistribution.DonationStatus ?? 1}, //hardcoded to pending if no status specified
                {"Recurring_Gift_ID", donationAndDistribution.RecurringGiftId},
                {"Is_Recurring_Gift", donationAndDistribution.RecurringGift},
                {"Donor_Account_ID", donationAndDistribution.DonorAcctId},
            };
            if (!string.IsNullOrWhiteSpace(donationAndDistribution.CheckScannerBatchName))
            {
                donationValues["Check_Scanner_Batch"] = donationAndDistribution.CheckScannerBatchName;
            }

            if (!string.IsNullOrWhiteSpace(donationAndDistribution.CheckNumber))
            {
                donationValues["Item_Number"] = donationAndDistribution.CheckNumber;
            }

            int donationId;

            try
            {
                donationId = _ministryPlatformService.CreateRecord(_donationPageId, donationValues, apiToken, true);
            }
            catch (Exception e)
            {
                throw new ApplicationException(string.Format("CreateDonationRecord failed.  Donor Id: {0}", donationAndDistribution.DonorId), e);
            }

            if (string.IsNullOrWhiteSpace(donationAndDistribution.ProgramId))
            {
                return (donationId);
            }
            
            var distributionValues = new Dictionary<string, object>
            {
                {"Donation_ID", donationId},
                {"Amount", donationAndDistribution.DonationAmt},
                {"Program_ID", donationAndDistribution.ProgramId}                
            };
            if (donationAndDistribution.PledgeId != null)
            {
                distributionValues.Add("Pledge_ID", donationAndDistribution.PledgeId);
            }

            try
            {
                _ministryPlatformService.CreateRecord(_donationDistributionPageId, distributionValues, apiToken, true);
            }
            catch (Exception e)
            {
                throw new ApplicationException(
                    string.Format("CreateDonationDistributionRecord failed.  Donation Id: {0}", donationId), e);
            }

            try
            {
                SetupConfirmationEmail(Convert.ToInt32(donationAndDistribution.ProgramId), donationAndDistribution.DonorId, donationAndDistribution.DonationAmt, donationAndDistribution.SetupDate, donationAndDistribution.PymtType);
            }
            catch (Exception)
            {
                _logger.Error(string.Format("Failed when processing the template for Donation Id: {0}", donationId));
            }

            return donationId;
        }
        public CheckScannerBatch CreateDonationsForBatch(CheckScannerBatch batchDetails)
        {
            var checks = _checkScannerDao.GetChecksForBatch(batchDetails.Name);
            foreach (var check in checks)
            {
                if (check.Exported)
                {
                    var previousError = string.IsNullOrWhiteSpace(check.Error) ? string.Empty : string.Format("Previous Error: {0}", check.Error);
                    var msg = string.Format("Not exporting check {0} on batch {1}, it was already exported. {2}", check.Id, batchDetails.Name, previousError);
                    _logger.Info(msg);
                    check.Error = msg;
                    batchDetails.ErrorChecks.Add(check);
                    continue;
                }

                try
                {
                    var contactDonor = CreateDonor(check);
                    //Always use the customer ID and source ID from the Donor Account, if it exists
                    StripeCharge charge;
                    charge = contactDonor.HasAccount ? _paymentService.ChargeCustomer(contactDonor.ProcessorId, contactDonor.Account.ProcessorAccountId, check.Amount, contactDonor.DonorId) : _paymentService.ChargeCustomer(contactDonor.ProcessorId, check.Amount, contactDonor.DonorId);
                   
                    var fee = charge.BalanceTransaction != null ? charge.BalanceTransaction.Fee : null;

                    // Mark the check as exported now, so we don't double-charge a community member.
                    // If the CreateDonationAndDistributionRecord fails, we'll still consider it exported, but
                    // it will be in error, and will have to be manually resolved.
                    check.Exported = true;
                    var account = _mpDonorService.DecryptCheckValue(check.AccountNumber);
                    var routing = _mpDonorService.DecryptCheckValue(check.RoutingNumber);
                    var encryptedKey = _mpDonorService.CreateHashedAccountAndRoutingNumber(account, routing);
                                     
                    var donorAccountId =_mpDonorService.UpdateDonorAccount(encryptedKey, charge.Source.id, contactDonor.ProcessorId);
                 
                    var programId = batchDetails.ProgramId == null ? null : batchDetails.ProgramId + "";

                    var donationAndDistribution = new DonationAndDistributionRecord
                    {
                        DonationAmt = check.Amount,
                        FeeAmt = fee,
                        DonorId = contactDonor.DonorId,
                        ProgramId = programId,
                        ChargeId = charge.Id,
                        PymtType = "check",
                        ProcessorId = contactDonor.ProcessorId,
                        SetupDate = check.CheckDate ?? (check.ScanDate ?? DateTime.Now),
                        RegisteredDonor = contactDonor.RegisteredUser,
                        DonorAcctId = donorAccountId,
                        CheckScannerBatchName = batchDetails.Name,
                        CheckNumber = (check.CheckNumber ?? string.Empty).TrimStart(' ', '0').Right(MinistryPlatformCheckNumberMaxLength)
                    };

                    var donationId = _mpDonorService.CreateDonationAndDistributionRecord(donationAndDistribution);

                    check.DonationId = donationId;

                    _checkScannerDao.UpdateCheckStatus(check.Id, true);

                    batchDetails.Checks.Add(check);
                }
                catch (Exception e)
                {
                    check.Error = e.ToString();
                    check.AccountNumber = _mpDonorService.DecryptCheckValue(check.AccountNumber);
                    check.RoutingNumber = _mpDonorService.DecryptCheckValue(check.RoutingNumber);
                    batchDetails.ErrorChecks.Add(check);
                    _checkScannerDao.UpdateCheckStatus(check.Id, check.Exported, check.Error);
                }
            }

            batchDetails.Status = BatchStatus.Exported;
            _checkScannerDao.UpdateBatchStatus(batchDetails.Name, batchDetails.Status);

            return (batchDetails);
        }