public static IEnumerable <StatementInfoWithFund> Statements(CMSDataContext db, int?id, int[] includedFundIds = null)
        {
            if (!id.HasValue)
            {
                throw new ArgumentException("Missing id");
            }

            var person        = db.LoadPersonById(id.Value);
            var contributions = (from c in db.Contributions2(new DateTime(1900, 1, 1), new DateTime(3000, 12, 31), 0, false, null, true, null)
                                 where (c.PeopleId == person.PeopleId || (c.PeopleId == person.SpouseId && (person.ContributionOptionsId ?? StatementOptionCode.Joint) == StatementOptionCode.Joint))
                                 select c).ToList();
            var currentUser = db.CurrentUserPerson;

            if (currentUser.PeopleId != person.PeopleId)
            {
                var authorizedFunds         = db.ContributionFunds.ScopedByRoleMembership(db);
                var authorizedContributions = from c in contributions
                                              join f in authorizedFunds on c.FundId equals f.FundId
                                              select c;
                contributions = authorizedContributions.ToList();
            }
            if (includedFundIds != null)
            {
                contributions = contributions.Where(c => includedFundIds.Contains(c.FundId)).ToList();
            }

            var shouldGroupByFunds = db.Setting("EnableContributionFundsOnStatementDisplay");

            IEnumerable <StatementInfoWithFund> result;

            if (shouldGroupByFunds)
            {
                result = (from c in contributions
                          group c by new { c.DateX.Value.Year, c.FundName, c.FundId } into g
                          orderby g.Key.Year descending, g.Key.FundName ascending
                          select new StatementInfoWithFund()
                {
                    Count = g.Count(),
                    Amount = g.Sum(cc => cc.Amount ?? 0),
                    StartDate = new DateTime(g.Key.Year, 1, 1),
                    EndDate = new DateTime(g.Key.Year, 12, 31),
                    FundName = g.Key.FundName,
                    FundId = g.Key.FundId,
                    FundGroupName = string.Empty
                }).ToList();

                var displayNameHelper = new CustomFundSetDisplayHelper(db);
                displayNameHelper.ProcessList(result);

                // hack: grouping done in memory since these fundids are stored as XML and not easily accessed in SQL
                // task: FundGrouping table to avoid using XML for this data in the future with UI to make management easier?
                result = (from c in result
                          group c by new { c.StartDate.Year, c.FundGroupName } into g
                          orderby g.Key.Year descending, g.Key.FundGroupName ascending
                          select new StatementInfoWithFund()
                {
                    Count = g.Sum(cc => cc.Count),
                    Amount = g.Sum(cc => cc.Amount),
                    StartDate = new DateTime(g.Key.Year, 1, 1),
                    EndDate = new DateTime(g.Key.Year, 12, 31),
                    FundName = "",
                    FundId = 0,
                    FundGroupName = g.Key.FundGroupName
                }).ToList();
            }
            else
            {
                result = (from c in contributions
                          group c by new { c.DateX.Value.Year } into g
                          orderby g.Key.Year descending
                          select new StatementInfoWithFund()
                {
                    Count = g.Count(),
                    Amount = g.Sum(cc => cc.Amount ?? 0),
                    StartDate = new DateTime(g.Key.Year, 1, 1),
                    EndDate = new DateTime(g.Key.Year, 12, 31),
                    FundName = string.Empty,
                    FundId = 0
                }).ToList();
            }

            return(result);
        }