Exemplo n.º 1
0
        // Bank Run Process Notes:

        /*
         * 1. User clicks the generate list on the bank run. This uses the query to get the records from SQL DB.
         * 2. With these records we attempt to create Bank Run Schedule records in SQL DB.
         * 3. Those records are synced back to Dynamics via the data sync process.
         * 4. Those records are used for the Report generation (taken from SQL DB).
         * 5. After the report is generated the user confirms the list changing the bank run status to List Confirmed.
         *		- This generates the child transactions (links them to the bank run) and updates all the payment schedules.
         */
        public static void GetPaymentSchedulesForBankRun(BankRun bankRunEntity, PaymentContext dataContext, ILogger logger)
        {
            logger.LogInformation("----------Entering GetPaymentSchedulesForBankRun()----------");
            try
            {
                var paymentSchedules = dataContext.PaymentSchedule.Where(ps => (ps.Deleted == null || ps.Deleted == false) &&
                                                                         ps.StatusCode == StatusCode.Active && // Active
                                                                         ps.PaymentMethodId != null && // Has a payment method
                                                                         ps.PaymentTypeCode == PaymentTypeCode.BankAccount &&
                                                                         (ps.NextPaymentDate.Value.Date <= bankRunEntity.EndDate.Value.Date && ps.NextPaymentDate.Value.Date >= bankRunEntity.StartDate.Value.Date) // If it is within the start-end range
                                                                         ).ToList();

                //Local debugging: var paymentSchedules = DataContext.PaymentSchedule.Where(ps => ps.PaymentScheduleId == new Guid("3e5fec3c-f96d-ea11-a811-000d3a0c8a65"));

                logger.LogInformation("Payment Schedules to associate = " + paymentSchedules.Count());
                logger.LogInformation("Bank Run Start Date = " + bankRunEntity.StartDate.Value.Date);
                logger.LogInformation("Bank Run End Date = " + bankRunEntity.EndDate.Value.Date);

                // Now that we have the payment schedules, attach them to this bank run:
                foreach (PaymentSchedule ps in paymentSchedules)
                {
                    logger.LogInformation("Adding Payment Schedule: " + ps.Name + " (" + ps.PaymentScheduleId + ")");

                    // Create the bank run schedule in SQL DB:
                    try
                    {
                        bool duplicate = false;
                        if (dataContext.BankRunSchedule.Count() > 0)
                        {
                            // We make sure to not add a duplicate for the same bank run:
                            if (dataContext.BankRunSchedule.Where(brs => brs.PaymentScheduleId == ps.PaymentScheduleId && brs.BankRunId == bankRunEntity.BankRunId && (brs.Deleted == null || brs.Deleted == false)).Count() > 0)
                            {
                                // Duplicate, ignore.
                                duplicate = true;
                            }
                        }

                        if (!duplicate)
                        {
                            BankRunSchedule newBRS = new BankRunSchedule();
                            newBRS.BankRunId         = bankRunEntity.BankRunId;
                            newBRS.PaymentScheduleId = ps.PaymentScheduleId;
                            newBRS.CreatedOn         = DateTime.UtcNow;
                            newBRS.StateCode         = 0;                     // Active state
                            newBRS.StatusCode        = StatusCode.Active;     // Active status reason code (default status reason)
                            dataContext.BankRunSchedule.Add(newBRS);
                        }
                    }
                    catch (Exception e)
                    {
                        // It may already exist, so ignore and move on.
                        logger.LogError("Issue with adding new bank run schedule record for payment schedule " + ps.Name + " (" + ps.PaymentScheduleId + "): " + e.Message);
                    }
                }

                try
                {
                    if (bankRunEntity.BankRunStatus == 844060000 || bankRunEntity.BankRunStatus == 844060004)
                    {
                        logger.LogInformation("Setting Bank Run Status to 'Gift List Retrieved'.");
                        bankRunEntity.BankRunStatus = 844060003;               // Gift List Retrieved
                        bankRunEntity.SyncDate      = null;                    // Sync this change back to Dynamics.
                    }

                    logger.LogInformation("Saving new Bank Run Schedules to DB.");
                    dataContext.SaveChanges();
                    logger.LogInformation("Save Complete.");
                }
                catch (Exception e)
                {
                    // It may already exist, so ignore and move on.
                    logger.LogError("Issue saving Bank Run Schedules: " + e.Message);
                    if (e.InnerException != null)
                    {
                        logger.LogError("Inner exception: " + e.InnerException.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error has occured in GetPaymentSchedulesForBankRun(): " + ex.Message);
                if (ex.InnerException != null)
                {
                    Console.WriteLine("Inner exception: " + ex.InnerException.ToString());
                }
                throw;
            }
            Console.WriteLine("----------Exiting GetPaymentSchedulesForBankRun()----------");
        }
 public AbaFileReport(BankRun bankRun, PaymentProcessor paymentProcessor, PaymentMethod paymentMethod, PaymentContext dataContext, ILogger logger) : base(bankRun, paymentProcessor, paymentMethod, dataContext, logger)
 {
     Debits        = new List <PaymentSchedule>();
     Credits       = new List <PaymentSchedule>();
     fileExtension = "aba";
 }
        private static Transaction GenerateChildTransactionForPaymentSchedule(PaymentSchedule parentPaymentSchedule, BankRun paymentSchedulesAssociatedRun)
        {
            Transaction newChildTransaction = new Transaction();

            // Get all the same fields and copy them to the new child record:
            newChildTransaction = parentPaymentSchedule.CopyCommonFieldsTo(newChildTransaction);

            // Some fields are named different or have different states for the child vs parent, so we fix those here:
            newChildTransaction.TransactionId = Guid.NewGuid();
            newChildTransaction.StatusCode    = StatusCode.Completed;          // Completed
            newChildTransaction.TransactionPaymentScheduleId = parentPaymentSchedule.PaymentScheduleId;
            newChildTransaction.BookDate                   = DateTime.UtcNow;
            newChildTransaction.CreatedOn                  = DateTime.UtcNow;
            newChildTransaction.Amount                     = parentPaymentSchedule.RecurringAmount; // Total Header
            newChildTransaction.AmountMembership           = parentPaymentSchedule.AmountMembership;
            newChildTransaction.AmountNonReceiptable       = parentPaymentSchedule.AmountNonReceiptable;
            newChildTransaction.AmountReceipted            = parentPaymentSchedule.AmountReceipted;
            newChildTransaction.TransactionPaymentMethodId = parentPaymentSchedule.PaymentMethodId;
            newChildTransaction.DepositDate                = paymentSchedulesAssociatedRun.DateToBeProcessed;
            newChildTransaction.TransactionResult          = "Bank Run ID: " + paymentSchedulesAssociatedRun.BankRunId.ToString();
            newChildTransaction.DesignationId              = parentPaymentSchedule.DesignationId;
            newChildTransaction.AppealId                   = parentPaymentSchedule.AppealId;
            newChildTransaction.TransactionCurrencyId      = parentPaymentSchedule.TransactionCurrencyId;
            newChildTransaction.MembershipInstanceId       = parentPaymentSchedule.MembershipId;
            newChildTransaction.MembershipId               = parentPaymentSchedule.MembershipCategoryId;
            newChildTransaction.SyncDate                   = null;
            newChildTransaction.ReceivedDate               = paymentSchedulesAssociatedRun.DateToBeProcessed;

            return(newChildTransaction);
        }
        public static void GenerateBankRunRecurringDonations(BankRun bankRunEntity, PaymentContext dataContext, ILogger logger)
        {
            logger.LogInformation("----------Entering GenerateBankRunRecurringDonations()----------");

            // Get all of the payment schedules from the bank runs:
            List <BankRunSchedule> bankRunSchedules = dataContext.BankRunSchedule.Where(brs =>
                                                                                        brs.BankRunId == bankRunEntity.BankRunId &&
                                                                                        brs.StatusCode == StatusCode.Active &&
                                                                                        (brs.Deleted == null || brs.Deleted == false)).ToList(); // Active and not deleted.

            if (bankRunSchedules.Count() < 1)
            {
                logger.LogInformation("No Bank Run Schedules found for this bank run (" + bankRunEntity.BankRunId + "). Exiting webjob.");
                return;
            }

            logger.LogInformation("Bank Run Schedules meeting the criteria for this bank run (" + bankRunEntity.BankRunId + "): " + bankRunSchedules.Count());

            int         numberOfFailedPaymentSchedules = 0;
            int         currentPaymentScheduleNumber   = 0;   // Used for visual counting, not for code operations.
            List <Guid> paymentSchedulesProcessed      = new List <Guid>();

            foreach (BankRunSchedule brs in bankRunSchedules)
            {
                try
                {
                    bool            generateTransaction           = false;
                    PaymentSchedule paymentSchedule               = dataContext.PaymentSchedule.Where(ps => ps.PaymentScheduleId == brs.PaymentScheduleId).FirstOrDefault();
                    BankRun         paymentSchedulesAssociatedRun = dataContext.BankRun.Where(br => br.BankRunId == brs.BankRunId).FirstOrDefault();
                    currentPaymentScheduleNumber++;

                    // Make sure we don't process anything twice (just in case):
                    if (!paymentSchedulesProcessed.Contains(paymentSchedule.PaymentScheduleId))
                    {
                        generateTransaction = true;
                    }
                    else
                    {
                        logger.LogInformation("Skipping potential duplicate: " + paymentSchedule.PaymentScheduleId);
                    }

                    if (generateTransaction)
                    {
                        logger.LogInformation("--PS-" + currentPaymentScheduleNumber.ToString() + "--");
                        logger.LogInformation("Processing Payment Schedule = " + paymentSchedule.Name + "  (" + paymentSchedule.PaymentScheduleId.ToString() + ")");
                        logger.LogInformation("Previous Next Donation Date = " + paymentSchedule.NextPaymentDate.ToString());
                        // Set the last donation date:
                        paymentSchedule.LastPaymentDate = paymentSchedulesAssociatedRun.DateToBeProcessed;
                        // If so, we process it (create the child transaction, update next donation date) and move on to the next one:
                        paymentSchedule.NextPaymentDate = paymentSchedule.GetNextDonationDate();
                        logger.LogInformation("New Next Donation Date = " + paymentSchedule.NextPaymentDate.ToString());
                        paymentSchedule.SyncDate = null;
                        Transaction newChildTransaction = GenerateChildTransactionForPaymentSchedule(paymentSchedule, paymentSchedulesAssociatedRun);
                        // Add to DB changes:
                        logger.LogInformation("Created new transaction (" + newChildTransaction.TransactionId.ToString() + ") adding to transaction list.");
                        dataContext.Transaction.Add(newChildTransaction);
                        // Update the bank run schedule to status to "Completed":
                        brs.StatusCode = StatusCode.Completed;
                        brs.SyncDate   = null;
                        // Update the bank run:
                        paymentSchedulesAssociatedRun.BankRunStatus = 844060001;                         // Processed
                        paymentSchedulesAssociatedRun.SyncDate      = null;
                        paymentSchedulesProcessed.Add(paymentSchedule.PaymentScheduleId);
                        logger.LogInformation("----");
                    }
                }
                catch (Exception e)
                {
                    numberOfFailedPaymentSchedules++;
                    logger.LogError("Error with processing payment schedule (" + brs.PaymentScheduleId + "): " + e.Message);
                    if (e.InnerException != null)
                    {
                        logger.LogError("Inner exception: " + e.InnerException.ToString());
                    }
                }
            }

            logger.LogInformation("Processed all payment schedules (" + currentPaymentScheduleNumber + " total, " + numberOfFailedPaymentSchedules.ToString() + " failed payment schedules).");
            logger.LogInformation("Saving all payment schedules and new transactions to the DB.");

            dataContext.SaveChanges();
            logger.LogInformation("Save Complete.");

            logger.LogInformation("----------Exiting GenerateBankRunRecurringDonations()----------");
        }
Exemplo n.º 5
0
        public async Task BankRunAppSelector(string selectedProcess, Guid?bankRunGUID, Guid?entityId, string entityName)
        {
            logger.LogInformation("----------Entering BankRunAppSelector()----------");


            try
            {
                #region Bank Run Generate List
                // ----------Bank Run Generate List----------
                if (selectedProcess.Equals("List"))
                {
                    BankRun bankRunEntity = BankRunFileReport.GetBankRunEntityFromId(bankRunGUID, this.context);

                    if (bankRunEntity == null)
                    {
                        logger.LogInformation("Exiting web job.");
                        return;
                    }

                    // Assign the payment schedules to the bank run:
                    BankRunGenerateList.GetPaymentSchedulesForBankRun(bankRunEntity, context, this.logger);
                    // Now do the same for one off transactions (TODO in future sprint).

                    try
                    {
                        // Update the Bankrun Status to "Report Available" (844060004):
                        BankRun bankRunToUpdate = new BankRun();
                        bankRunToUpdate.BankRunId     = bankRunEntity.BankRunId;
                        bankRunToUpdate.BankRunStatus = 844060004;
                        logger.LogInformation("Updating BankRun Status.");
                        await this.xrmService.UpdateAsync(bankRunToUpdate);

                        logger.LogInformation("Updated BankRun Status to \"Report Available\" successfully.");
                    }
                    catch (Exception ex)
                    {
                        logger.LogError("Could not Update Bank Run Status. Exception:" + ex.Message);
                    }
                }
                #endregion
                #region Bank Run Generate File
                // ----------Bank Run Generate File----------
                else if (selectedProcess.Equals("File"))
                {
                    BankRun bankRunEntity = BankRunFileReport.GetBankRunEntityFromId(bankRunGUID, this.context);
                    //Configuration configEntity = Common.GetConfigurationEntityFromId(configGuid, this.DataContext);
                    PaymentProcessor paymentProcessorEntity = BankRunFileReport.GetPaymentProcessorEntityFromBankRun(bankRunEntity, this.context, this.logger);
                    PaymentMethod    paymentMethodEntity    = BankRunFileReport.GetPaymentMethodEntityFromBankRun(bankRunEntity, this.context, this.logger);

                    int?bankRunFileFormat = paymentProcessorEntity.BankRunFileFormat;
                    logger.LogInformation("Requested Bank Run File Format:" + bankRunFileFormat);

                    BankRunFileReport bankRunFileReport;
                    switch (bankRunFileFormat)
                    {
                    case (int)BankRunFileFormat.ABA:
                        bankRunFileReport = new AbaFileReport(bankRunEntity, paymentProcessorEntity, paymentMethodEntity, this.context, this.logger);
                        break;

                    case (int)BankRunFileFormat.BMO:
                        bankRunFileReport = new BMOFileReport(bankRunEntity, paymentProcessorEntity, paymentMethodEntity, this.context, this.logger);
                        break;

                    case (int)BankRunFileFormat.ScotiaBank:
                        bankRunFileReport = new ScotiaBankFileReport(bankRunEntity, paymentProcessorEntity, paymentMethodEntity, this.context, this.logger);
                        break;

                    case null:
                        throw new Exception("No Bank Run File Format set on the Payment Processor with ID:" + paymentProcessorEntity.PaymentProcessorId);

                    default:
                        throw new Exception("Can't find Bank Run File Format for provided value:" + bankRunFileFormat);
                    }

                    await bankRunFileReport.GenerateFileReport();

                    await bankRunFileReport.SaveReport();
                }
                #endregion
                #region Bank Run Generate Recurring Donation Records
                else if (selectedProcess.Equals("GenerateTransactions"))
                {
                    BankRun bankRunEntity = BankRunFileReport.GetBankRunEntityFromId(bankRunGUID, this.context);
                    BankRunRecurringDonations.GenerateBankRunRecurringDonations(bankRunEntity, this.context, this.logger);
                }
                #endregion

                #region Event Receipting
                else if (selectedProcess.Equals("EventReceipting") && entityId.HasValue)
                {
                    List <EventPackage> eventPackages = new List <EventPackage>();
                    switch (entityName)
                    {
                    case EventReceipting.EventTicket:
                        EventTicket eventTicket = EventReceipting.GetEventTicketFromId(entityId.Value, this.context);
                        EventReceipting.UpdateTicketsFromEventTicket(eventTicket, this.context);
                        eventPackages = EventReceipting.GetEventPackagesFromEventTicket(eventTicket, this.context);
                        break;

                    case EventReceipting.EventProduct:
                        EventProduct eventProduct = EventReceipting.GetEventProductFromId(entityId.Value, this.context);
                        EventReceipting.UpdateProductsFromEventProduct(eventProduct, this.context);
                        eventPackages = EventReceipting.GetEventPackagesFromEventProduct(eventProduct, this.context);
                        break;

                    case EventReceipting.EventSponsorship:
                        EventSponsorship eventSponsorship = EventReceipting.GetEventSponsorshipFromId(entityId.Value, this.context);
                        EventReceipting.UpdateSponsorshipsFromEventSponsorship(eventSponsorship, this.context);
                        eventPackages = EventReceipting.GetEventPackagesFromEventSponsorship(eventSponsorship, this.context);
                        break;

                    default:
                        throw new Exception("Unknown Entity for Event Receipting: " + entityName + ". Exiting.");
                    }

                    EventReceipting.UpdateEventPackages(eventPackages, this.context);
                }

                #endregion
            }
            catch (Exception e)
            {
                logger.LogError("Error in BankRunAppSelector(): " + e.Message);
                if (e.InnerException != null)
                {
                    logger.LogError("Inner exception: " + e.InnerException.ToString());
                }
            }

            logger.LogInformation("----------Exiting BankRunAppSelector()----------");
            logger.LogInformation("----------Exiting Web Job----------");
        }
 public ScotiaBankFileReport(BankRun bankRun, PaymentProcessor paymentProcessor, PaymentMethod paymentMethod, PaymentContext dataContext, ILogger logger) : base(bankRun, paymentProcessor, paymentMethod, dataContext, logger)
 {
     Debits  = new List <PaymentSchedule>();
     Credits = new List <PaymentSchedule>();
 }