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); }