/// <summary>
        ///     Examines the ledger book's most recent reconciliation looking for transactions waiting to be matched to
        ///     transactions imported in the current month.
        ///     If any transactions are found, the statement is then examined to see if the transactions appear, if they do not a
        ///     new <see cref="ValidationWarningException" />
        ///     is thrown; otherwise the method returns.
        /// </summary>
        public void ValidateAgainstOrphanedAutoMatchingTransactions(LedgerBook ledgerBook, StatementModel statement)
        {
            if (ledgerBook == null)
            {
                throw new ArgumentNullException(nameof(ledgerBook));
            }

            if (statement == null)
            {
                throw new ArgumentNullException(nameof(statement));
            }

            var lastLine = ledgerBook.Reconciliations.FirstOrDefault();

            if (lastLine == null)
            {
                return;
            }

            List <LedgerTransaction> unmatchedTxns = lastLine.Entries
                                                     .SelectMany(e => e.Transactions)
                                                     .Where(
                t =>
                !string.IsNullOrWhiteSpace(t.AutoMatchingReference) &&
                !t.AutoMatchingReference.StartsWith(ReconciliationBuilder.MatchedPrefix,
                                                    StringComparison.Ordinal))
                                                     .ToList();

            if (unmatchedTxns.None())
            {
                return;
            }

            List <Transaction> statementSubSet = statement.AllTransactions.Where(t => t.Date >= lastLine.Date).ToList();

            foreach (var ledgerTransaction in unmatchedTxns)
            {
                IEnumerable <Transaction> statementTxns = ReconciliationBuilder.TransactionsToAutoMatch(statementSubSet,
                                                                                                        ledgerTransaction.AutoMatchingReference);
                if (statementTxns.None())
                {
                    this.logger.LogWarning(
                        l =>
                        l.Format(
                            "There appears to be some transactions from last month that should be auto-matched to a statement transactions, but no matching statement transactions were found. {0}",
                            ledgerTransaction));
                    throw new ValidationWarningException(
                              string.Format(
                                  CultureInfo.CurrentCulture,
                                  "There appears to be some transactions from last month that should be auto-matched to a statement transactions, but no matching statement transactions were found.\nHave you forgotten to do a transfer?\nTransaction ID:{0} Ref:{1} Amount:{2:C}",
                                  ledgerTransaction.Id,
                                  ledgerTransaction.AutoMatchingReference,
                                  ledgerTransaction.Amount))
                          {
                              Source = "1"
                          };
                }
            }
        }
        private void PreReconciliationValidation(LedgerBook ledgerBook, DateTime reconciliationDate, StatementModel statement)
        {
            var messages = new StringBuilder();

            if (!ledgerBook.Validate(messages))
            {
                throw new InvalidOperationException("Ledger book is currently in an invalid state. Cannot add new entries.\n" + messages);
            }

            if (statement == null)
            {
                return;
            }

            var startDate = ReconciliationBuilder.CalculateDateForReconcile(ledgerBook, reconciliationDate);

            ValidateDates(ledgerBook, startDate, reconciliationDate, statement);

            ValidateAgainstUncategorisedTransactions(startDate, reconciliationDate, statement);

            ValidateAgainstOrphanedAutoMatchingTransactions(ledgerBook, statement);

            ValidateAgainstMissingTransactions(reconciliationDate, statement);
        }