public override void ExecuteResult(ControllerContext context)
        {
            var Response = context.HttpContext.Response;

            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition", "filename=foo.pdf");
            var c = new ContributionStatements
            {
                FamilyId = FamilyId,
                FromDate = FromDate,
                PeopleId = PeopleId,
                SpouseId = SpouseId,
                ToDate   = ToDate,
                typ      = typ
            };
            IEnumerable <ContributorInfo> q = null;

            switch (typ)
            {
            case 1:
                SpouseId = DbUtil.Db.People.Single(p => p.PeopleId == PeopleId).SpouseId.ToInt();
                q        = APIContribution.contributors(DbUtil.Db, FromDate, ToDate, PeopleId, SpouseId, 0, noaddressok, useMinAmt);
                break;

            case 2:
                FamilyId = DbUtil.Db.People.Single(p => p.PeopleId == PeopleId).FamilyId;
                q        = APIContribution.contributors(DbUtil.Db, FromDate, ToDate, 0, 0, FamilyId, noaddressok, useMinAmt);
                break;

            case 3:
                q = APIContribution.contributors(DbUtil.Db, FromDate, ToDate, 0, 0, 0, noaddressok, useMinAmt);
                break;
            }
            c.Run(Response.OutputStream, DbUtil.Db, q);
        }
Example #2
0
        private void writeContributions(ContributorInfo c)
        {
            string hdrContributions = "   Date        Fund Name          Amount       Date        Fund Name          Amount\n\n";

            rWrite(hdrContributions);
            var q2      = APIContribution.contributions(Db, c, fd, td);
            var contrib = new List <string>();

            foreach (var ci in q2)
            {
                contrib.Add("{0:MM/dd/yyyy}     {1,-16}{2,11:N2}"
                            .Fmt(ci.ContributionDate, ci.Fund, ci.ContributionAmount));
            }

            var n         = contrib.Count;
            var nrows     = n / 32 * 16;
            var remainder = n % 32;

            if (remainder < 16)
            {
                nrows += remainder;
            }
            else
            {
                nrows += 16;
            }

            int row, c1;

            for (row = 0, c1 = 0; row < nrows; row++, c1++)
            {
                if (row % 16 == 0)
                {
                    c1 = row * 2;
                }
                var line = contrib[c1];
                var c2   = c1 + 16;
                if (c2 < n)
                {
                    line += "  " + contrib[c2];
                }

                if (row > 0 && row % 16 == 0)
                {
                    pageStatement += 1;
                    writeHeader(c);
                    rWrite(hdrContributions);
                    rWrite("\n");
                }
                rWrite(line + "\n");
            }
            if (nrows > 0)
            {
                rWrite("\n");
            }
        }
Example #3
0
        public void DoWork()
        {
            Db                = new CMSDataContext(Util.GetConnectionString(Host));
            Db.Host           = Host;
            Db.CommandTimeout = 1200;

            var noaddressok   = Db.Setting("RequireAddressOnStatement", "true") == "false";
            var qc            = APIContribution.contributors(Db, fd, td, 0, 0, 0, noaddressok, useMinAmt: true, startswith: StartsWith);
            var runningtotals = Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();

            runningtotals.Count = qc.Count();
            Db.SubmitChanges();
            if (PDF)
            {
                var c = new ContributionStatements
                {
                    FromDate = fd,
                    ToDate   = td,
                    typ      = 3
                };
                using (var stream = new FileStream(OutputFile, FileMode.Create))
                    c.Run(stream, Db, qc);
                LastSet = c.LastSet();
                var sets = c.Sets();
                foreach (var set in sets)
                {
                    using (var stream = new FileStream(Output(OutputFile, set), FileMode.Create))
                        c.Run(stream, Db, qc, set);
                }
                runningtotals           = Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();
                runningtotals.LastSet   = LastSet;
                runningtotals.Sets      = string.Join(",", sets);
                runningtotals.Completed = DateTime.Now;
                Db.SubmitChanges();
            }
            else
            {
                textStream = new StreamWriter(OutputFile);
                foreach (var c in qc)
                {
                    pageStatement = 1;
                    writeHeader(c);
                    writeContributions(c);
                    string hdrGift = "   Date        Fund Name          Description of Gift-in-Kind Given as of {0:d}\n\n".Fmt(td);
                    rWrite(hdrGift);
                    writeSummary(c);
                    runningtotals.Processed += 1;
                    Db.SubmitChanges();
                }
                textStream.Close();
                runningtotals           = Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();
                runningtotals.Completed = DateTime.Now;
                Db.SubmitChanges();
            }
        }
Example #4
0
        public ActionResult ContributionStatements(DateTime?fromDate, DateTime?endDate, string startswith, string sort, int?tagid, bool excludeelectronic, string customstatement = null, bool exportcontributors = false)
        {
            if (!fromDate.HasValue || !endDate.HasValue)
            {
                return(Content("<h3>Must have a Startdate and Enddate</h3>"));
            }
            var runningtotals = new ContributionsRun
            {
                Started   = DateTime.Now,
                Count     = 0,
                Processed = 0
            };
            var cs = Models.Report.ContributionStatements.GetStatementSpecification(customstatement);

            if (!startswith.HasValue())
            {
                startswith = null;
            }
            if (exportcontributors)
            {
                var        db          = DbUtil.Db;
                var        noaddressok = !db.Setting("RequireAddressOnStatement", true);
                const bool useMinAmt   = true;
                if (tagid == 0)
                {
                    tagid = null;
                }
                var qc = APIContribution.Contributors(db, fromDate.Value, endDate.Value, 0, 0, 0, cs.Funds, noaddressok, useMinAmt, startswith, sort, tagid: tagid, excludeelectronic: excludeelectronic);
                return(ExcelExportModel.ToDataTable(qc.ToList()).ToExcel("Contributors.xlsx"));
            }
            DbUtil.Db.ContributionsRuns.InsertOnSubmit(runningtotals);
            DbUtil.Db.SubmitChanges();
            var cul  = DbUtil.Db.Setting("Culture", "en-US");
            var host = Util.Host;

            var output = Output();

            if (tagid == 0)
            {
                tagid = null;
            }

            HostingEnvironment.QueueBackgroundWorkItem(ct =>
            {
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(cul);
                Thread.CurrentThread.CurrentCulture   = CultureInfo.CreateSpecificCulture(cul);
                var m = new ContributionStatementsExtract(host, fromDate.Value, endDate.Value, output, startswith, sort, tagid, excludeelectronic);
                m.DoWork(cs);
            });
            return(Redirect("/Statements/Progress"));
        }
Example #5
0
        private void writeSummary(ContributorInfo c)
        {
            string  hdr1Pledge = "            Pledge History                Current Year Summary ({0:MM/dd/yyyy})\n".Fmt(td);
            string  hdr2Pledge = " Fund Name         Pledge        Given      Fund Name           Amount This Year\n\n";
            var     recPledges = new List <string>();
            decimal Total      = 0;

            rWrite(hdr1Pledge + hdr2Pledge);
            foreach (var p in APIContribution.pledges(Db, c, td))
            {
                if (p.Fund != null)
                {
                    recPledges.Add("{0,-16}{1,12:N2}  {2,12:N2} ".Fmt(p.Fund, p.PledgeAmount, p.ContributionAmount));
                }
            }

            foreach (var ci in APIContribution.quarterlySummary(Db, c, fd, td))
            {
                Total += ci.ContributionAmount.Value;
                if (recPledges != null && recPledges.Count > 0 && countRec < recPledges.Count)
                {
                    recPledges[countRec] += "{0,-20}{1,14:N2} ".Fmt(ci.Fund, ci.ContributionAmount);
                }
                else
                {
                    recPledges.Add("{0,43}{1,-20}{2,14:N2} ".Fmt("", ci.Fund, ci.ContributionAmount));
                }
                countRec++;
            }

            countRec = 0;
            foreach (var s in recPledges)
            {
                countRec++;
                if (countRec > 6 && (countRec % 6) == 1)
                {
                    pageStatement++;
                    writeHeader(c);
                    rWrite(hdr1Pledge + hdr2Pledge);
                }
                rWrite(s + "\n");
            }
            if (countRec != 0)
            {
                rWrite("\n");
            }
            rWrite(totalLine + Total.ToString("C").PadLeft(25) + "\n");
            countRec = 0;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            var response = context.HttpContext.Response;

            response.ContentType = "application/pdf";
            var filename = $"Statement-{ToDate:d}".SlugifyString("-", false);

            response.AddHeader("content-disposition", $"filename={filename}.pdf");
            var cs = ContributionStatementsExtract.GetStatementSpecification(CurrentDatabase, statementType ?? "all");

            var c = new ContributionStatements
            {
                FamilyId = FamilyId,
                FromDate = FromDate,
                PeopleId = PeopleId,
                SpouseId = SpouseId,
                ToDate   = ToDate,
                typ      = typ,
                //TODO: once we switch to entirely html-based statement templates we won't need to check for these options
                NumberOfColumns = showCheckNo || showNotes ? 1 : 2,
                ShowCheckNo     = showCheckNo,
                ShowNotes       = showNotes
            };

            IEnumerable <ContributorInfo> q = null;

            switch (typ)
            {
            case 1:
                q = APIContribution.Contributors(CurrentDatabase, FromDate, ToDate, PeopleId, SpouseId, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                break;

            case 2:
                FamilyId = CurrentDatabase.People.Single(p => p.PeopleId == PeopleId).FamilyId;
                q        = APIContribution.Contributors(CurrentDatabase, FromDate, ToDate, 0, 0, FamilyId, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                break;

            case 3:
                q = APIContribution.Contributors(CurrentDatabase, FromDate, ToDate, 0, 0, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                break;
            }
            c.Run(response.OutputStream, CurrentDatabase, q, cs);
        }
        public void Run(Stream stream, CMSDataContext Db, IEnumerable <ContributorInfo> q, int set = 0)
        {
            pageEvents.set = set;
            IEnumerable <ContributorInfo> contributors = q;
            var toDate = ToDate.Date.AddHours(24).AddSeconds(-1);

            PdfContentByte dc;
            var            font     = FontFactory.GetFont(FontFactory.HELVETICA, 11);
            var            boldfont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11);

            var doc = new Document(PageSize.LETTER);

            doc.SetMargins(36f, 30f, 24f, 36f);
            var w = PdfWriter.GetInstance(doc, stream);

            w.PageEvent = pageEvents;
            doc.Open();
            dc = w.DirectContent;

            int prevfid       = 0;
            var runningtotals = Db.ContributionsRuns.OrderByDescending(mm => mm.Id).FirstOrDefault();

            runningtotals.Processed = 0;
            Db.SubmitChanges();
            var count = 0;

            foreach (var ci in contributors)
            {
                if (set > 0 && pageEvents.FamilySet[ci.PeopleId] != set)
                {
                    continue;
                }

                var contributions = APIContribution.contributions(Db, ci, FromDate, toDate).ToList();
                var pledges       = APIContribution.pledges(Db, ci, toDate).ToList();
                var giftsinkind   = APIContribution.GiftsInKind(Db, ci, FromDate, toDate).ToList();
                var nontaxitems   = Db.Setting("DisplayNonTaxOnStatement", "false").ToBool()
                    ? APIContribution.NonTaxItems(Db, ci, FromDate, toDate).ToList()
                    : new List <ContributionInfo>();

                if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) == 0)
                {
                    runningtotals.Processed += 1;
                    runningtotals.CurrSet    = set;
                    Db.SubmitChanges();
                    if (set == 0)
                    {
                        pageEvents.FamilySet[ci.PeopleId] = 0;
                    }
                    continue;
                }

                doc.NewPage();
                if (prevfid != ci.FamilyId)
                {
                    prevfid = ci.FamilyId;
                    pageEvents.EndPageSet();
                }
                if (set == 0)
                {
                    pageEvents.FamilySet[ci.PeopleId] = 0;
                }
                count++;

                var css = @"
<style>
h1 { font-size: 24px; font-weight:normal; margin-bottom:0; }
h2 { font-size: 11px; font-weight:normal; margin-top: 0; }
p { font-size: 11px; }
</style>
";
                //----Church Name

                var t1 = new PdfPTable(1);
                t1.TotalWidth         = 72f * 5f;
                t1.DefaultCell.Border = Rectangle.NO_BORDER;
                string html1 = Db.ContentHtml("StatementHeader", Resource1.ContributionStatementHeader);
                string html2 = Db.ContentHtml("StatementNotice", Resource1.ContributionStatementNotice);

                var mh = new MyHandler();
                using (var sr = new StringReader(css + html1))
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh, sr);

                var cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }
                //cell.FixedHeight = 72f * 1.25f;
                t1.AddCell(cell);
                t1.AddCell("\n");

                var t1a = new PdfPTable(1);
                t1a.TotalWidth         = 72f * 5f;
                t1a.DefaultCell.Border = Rectangle.NO_BORDER;

                var ae = new PdfPTable(1);
                ae.DefaultCell.Border = Rectangle.NO_BORDER;
                ae.WidthPercentage    = 100;

                var a = new PdfPTable(1);
                a.DefaultCell.Indent = 25f;
                a.DefaultCell.Border = Rectangle.NO_BORDER;
                a.AddCell(new Phrase(ci.Name, font));
                foreach (var line in ci.MailingAddress.SplitLines())
                {
                    a.AddCell(new Phrase(line, font));
                }
                cell = new PdfPCell(a)
                {
                    Border = Rectangle.NO_BORDER
                };
                //cell.FixedHeight = 72f * 1.0625f;
                ae.AddCell(cell);

                cell = new PdfPCell(t1a.DefaultCell);
                cell.AddElement(ae);
                t1a.AddCell(ae);

                //-----Notice

                var t2 = new PdfPTable(1);
                t2.TotalWidth         = 72f * 3f;
                t2.DefaultCell.Border = Rectangle.NO_BORDER;
                t2.AddCell(new Phrase($"\nPrint Date: {DateTime.Now:d}   (id:{ci.PeopleId} {ci.CampusId})", font));
                t2.AddCell("");
                var mh2 = new MyHandler();
                using (var sr = new StringReader(css + html2))
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh2, sr);
                cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh2.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }
                t2.AddCell(cell);

                // POSITIONING OF ADDRESSES
                //----Header

                var yp = doc.BottomMargin +
                         Db.Setting("StatementRetAddrPos", "10.125").ToFloat() * 72f;
                t1.WriteSelectedRows(0, -1,
                                     doc.LeftMargin - 0.1875f * 72f, yp, dc);

                yp = doc.BottomMargin +
                     Db.Setting("StatementAddrPos", "8.3375").ToFloat() * 72f;
                t1a.WriteSelectedRows(0, -1, doc.LeftMargin, yp, dc);

                yp = doc.BottomMargin + 10.125f * 72f;
                t2.WriteSelectedRows(0, -1, doc.LeftMargin + 72f * 4.4f, yp, dc);

                //----Contributions

                doc.Add(new Paragraph(" "));
                doc.Add(new Paragraph(" ")
                {
                    SpacingBefore = 72f * 2.125f
                });

                doc.Add(new Phrase($"\n  Period: {FromDate:d} - {toDate:d}", boldfont));

                var pos = w.GetVerticalPosition(true);

                var   ct       = new ColumnText(dc);
                float gutter   = 20f;
                float colwidth = (doc.Right - doc.Left - gutter) / 2;

                var t = new PdfPTable(new[] { 10f, 24f, 10f });
                t.WidthPercentage    = 100;
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 3;
                cell.Phrase  = new Phrase("Contributions\n", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Date", boldfont));
                t.AddCell(new Phrase("Description", boldfont));
                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase("Amount", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.NO_BORDER;

                var total = 0m;
                foreach (var c in contributions)
                {
                    t.AddCell(new Phrase(c.ContributionDate.ToShortDateString(), font));
                    t.AddCell(new Phrase(c.Fund, font));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(c.ContributionAmount.ToString("N2"), font);
                    t.AddCell(cell);
                    total += (c.ContributionAmount);
                }
                t.DefaultCell.Border = Rectangle.TOP_BORDER;
                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 2;
                cell.Phrase  = new Phrase("Total Contributions for period", boldfont);
                t.AddCell(cell);
                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase(total.ToString("N2"), font);
                t.AddCell(cell);

                ct.AddElement(t);

                //------Pledges

                if (pledges.Count > 0)
                {
                    t = new PdfPTable(new float[] { 16f, 12f, 12f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 3;
                    cell.Phrase  = new Phrase("\n\nPledges\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Fund", boldfont));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Pledge", boldfont);
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Given", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    foreach (var c in pledges)
                    {
                        t.AddCell(new Phrase(c.Fund, font));
                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.PledgeAmount.ToString2("N2"), font);
                        t.AddCell(cell);
                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font);
                        t.AddCell(cell);
                    }
                    ct.AddElement(t);
                }

                //------Gifts In Kind

                if (giftsinkind.Count > 0)
                {
                    t = new PdfPTable(new float[] { 12f, 18f, 20f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 3;
                    cell.Phrase  = new Phrase("\n\nGifts in Kind\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    cell        = new PdfPCell(t.DefaultCell);
                    cell.Phrase = new Phrase("Fund", boldfont);
                    t.AddCell(cell);
                    cell        = new PdfPCell(t.DefaultCell);
                    cell.Phrase = new Phrase("Description", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    foreach (var c in giftsinkind)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToShortDateString(), font));
                        cell        = new PdfPCell(t.DefaultCell);
                        cell.Phrase = new Phrase(c.Fund, font);
                        t.AddCell(cell);
                        cell        = new PdfPCell(t.DefaultCell);
                        cell.Phrase = new Phrase(c.Description, font);
                        t.AddCell(cell);
                    }
                    ct.AddElement(t);
                }

                //-----Summary

                t = new PdfPTable(new float[] { 29f, 9f });
                t.WidthPercentage    = 100;
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 2;
                cell.Phrase  = new Phrase("\n\nPeriod Summary\n", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Fund", boldfont));
                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase("Amount", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.NO_BORDER;
                foreach (var c in APIContribution.quarterlySummary(Db, ci, FromDate, toDate))
                {
                    t.AddCell(new Phrase(c.Fund, font));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(c.ContributionAmount.ToString("N2"), font);
                    t.AddCell(cell);
                }
                t.DefaultCell.Border = Rectangle.TOP_BORDER;
                t.AddCell(new Phrase("Total contributions for period", boldfont));
                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase(total.ToString("N2"), font);
                t.AddCell(cell);
                ct.AddElement(t);

                //------NonTax

                if (nontaxitems.Count > 0)
                {
                    t = new PdfPTable(new float[] { 10f, 24f, 10f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 3;
                    cell.Phrase  = new Phrase("\n\nNon Tax-Deductible Items\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    t.AddCell(new Phrase("Description", boldfont));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Amount", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    var ntotal = 0m;
                    foreach (var c in nontaxitems)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToShortDateString(), font));
                        t.AddCell(new Phrase(c.Fund, font));
                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.ContributionAmount.ToString("N2"), font);
                        t.AddCell(cell);
                        ntotal += (c.ContributionAmount);
                    }
                    t.DefaultCell.Border = Rectangle.TOP_BORDER;
                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 2;
                    cell.Phrase  = new Phrase("Total Non Tax-Deductible Items for period", boldfont);
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(ntotal.ToString("N2"), font);
                    t.AddCell(cell);

                    ct.AddElement(t);
                }

                var col    = 0;
                var status = 0;
                while (ColumnText.HasMoreText(status))
                {
                    if (col == 0)
                    {
                        ct.SetSimpleColumn(doc.Left, doc.Bottom, doc.Left + colwidth, pos);
                    }
                    else if (col == 1)
                    {
                        ct.SetSimpleColumn(doc.Right - colwidth, doc.Bottom, doc.Right, pos);
                    }
                    status = ct.Go();
                    ++col;
                    if (col > 1)
                    {
                        col = 0;
                        pos = doc.Top;
                        doc.NewPage();
                    }
                }

                runningtotals.Processed += 1;
                runningtotals.CurrSet    = set;
                Db.SubmitChanges();
            }

            if (count == 0)
            {
                doc.NewPage();
                doc.Add(new Paragraph("no data"));
                var a = new Anchor("see this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html")
                {
                    Reference = "http://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting"
                };
                doc.Add(a);
            }
            doc.Close();

            if (set == LastSet())
            {
                runningtotals.Completed = DateTime.Now;
            }
            Db.SubmitChanges();
        }
Example #8
0
        private void HtmlToPdfMethod(Stream stream, CMSDataContext db, IEnumerable <ContributorInfo> q, StatementSpecification cs, int set)
        {
            IConverter       converter     = GetConverter();
            string           nameOfChurch  = db.Setting("NameOfChurch", "Name of Church");
            string           startAddress  = db.Setting("StartAddress", "Start Address");
            string           churchPhone   = db.Setting("ChurchPhone", "(000) 000-0000");
            string           html          = cs.Template ?? db.Content("StatementTemplate", Resource1.ContributionStatementTemplate, ContentTypeCode.TypeText).Body;
            string           bodyHtml      = cs.TemplateBody ?? db.Content("StatementTemplateBody", Resource1.ContributionStatementTemplateBody, ContentTypeCode.TypeText).Body;
            string           header        = cs.Header ?? db.Content("StatementHeader", string.Format(Resource1.ContributionStatementHeader, nameOfChurch, startAddress, churchPhone), ContentTypeCode.TypeHtml).Body;
            string           notice        = cs.Notice ?? db.Content("StatementNotice", string.Format(Resource1.ContributionStatementNotice, nameOfChurch), ContentTypeCode.TypeHtml).Body;
            string           footer        = cs.Footer ?? db.Content("StatementTemplateFooter", "", ContentTypeCode.TypeText).Body;
            ContributionsRun runningtotals = db.ContributionsRuns.Where(mm => mm.UUId == UUId).SingleOrDefault();
            StatementOptions options;

            if (!GetStatementOptions(bodyHtml, out options))
            {
                GetStatementOptions(html, out options);
            }

            var toDate = ToDate.Date.AddHours(24).AddSeconds(-1);

            var document = new HtmlToPdfDocument
            {
                GlobalSettings =
                {
                    DocumentTitle  = (cs.Description ?? "Contribution Statement {date}").Replace("{date}", $"{toDate:d}"),
                    Margins        = options.Margins.Settings,
                    PaperSize      = options.PaperSize,
                    ProduceOutline = false,
                }
            };

            var familiesInSet = pageEvents.FamilySet.Where(k => k.Value == set).Select(k => k.Key);
            var contributors  = q.Where(c => set == 0 || familiesInSet.Contains(c.FamilyId));
            var count         = contributors.Count();

            if (count == 0)
            {
                document.Objects.Add(new ObjectSettings {
                    HtmlText = @"<p>no data</p>
                    <a href=""https://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting"">
                    See this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html
                    </a>"
                });
                var bytes = converter.Convert(document);
                stream.Write(bytes, 0, bytes.Length);
                return;
            }

            if (runningtotals != null)
            {
                runningtotals.Processed = 0;
            }
            db.SubmitChanges();

            Document combinedPDF     = new Document();
            var      combinedPDFName = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.pdf");

            using (FileStream combinedStream = new FileStream(combinedPDFName, FileMode.Create))
            {
                using (PdfCopy writer = new PdfCopy(combinedPDF, combinedStream))
                {
                    combinedPDF.Open();

                    var lastFamilyId = 0;
                    foreach (var contributor in contributors)
                    {
                        if (runningtotals != null)
                        {
                            runningtotals.Processed += 1;
                            runningtotals.CurrSet    = set;
                            db.SubmitChanges();
                        }

                        if (lastFamilyId != contributor.FamilyId)
                        {
                            lastFamilyId = contributor.FamilyId;

                            if (set == 0)
                            {
                                pageEvents.FamilySet[contributor.FamilyId] = 0;
                            }
                        }

                        var contributions = APIContribution.Contributions(db, contributor, FromDate, toDate, cs.Funds).ToList();
                        var pledges       = APIContribution.Pledges(db, contributor, toDate, cs.Funds).ToList();
                        var giftsinkind   = APIContribution.GiftsInKind(db, contributor, FromDate, toDate, cs.Funds).ToList();
                        var nontaxitems   = APIContribution.NonTaxItems(db, contributor, FromDate, toDate, cs.Funds).ToList();

                        if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) > 0)
                        {
                            contributor.MailingAddress = string.Join("<br/>", contributor.MailingAddress.SplitLines());
                            var taxSummary    = SumByFund(contributions);
                            var nontaxSummary = SumByFund(nontaxitems.Select(i => new NormalContribution(i)).ToList());
                            if (options.CombinedTaxSummary)
                            {
                                taxSummary.Combine(SumByFund(giftsinkind.Select(i => new NormalContribution(i)).ToList()));
                            }

                            var data = new StatementContext
                            {
                                fromDate       = FromDate,
                                toDate         = toDate,
                                header         = "",
                                notice         = "",
                                now            = DateTime.Now,
                                body           = "",
                                footer         = "",
                                contributor    = contributor,
                                envelopeNumber = Convert.ToString(Person.GetExtraValue(db, contributor.PeopleId, "EnvelopeNumber")?.IntValue),
                                contributions  = new ListOfNormalContributions(contributions),
                                pledges        = pledges,
                                giftsinkind    = giftsinkind,
                                nontaxitems    = nontaxitems,
                                taxSummary     = taxSummary,
                                nontaxSummary  = nontaxSummary,
                                totalGiven     = taxSummary.Total + nontaxSummary.Total
                            };
                            data.header = db.RenderTemplate(header, data);
                            data.notice = db.RenderTemplate(notice, data);
                            data.body   = db.RenderTemplate(bodyHtml, data);
                            data.footer = db.RenderTemplate(footer, data);
                            var htmlDocument = db.RenderTemplate(html, data);
                            document.Objects.Clear();
                            document.Objects.Add(new ObjectSettings
                            {
                                CountPages     = true,
                                FooterSettings = options.Footer.Settings,
                                HeaderSettings = options.Header.Settings,
                                HtmlText       = htmlDocument,
                                WebSettings    = new WebSettings
                                {
                                    EnableJavascript = false,
                                    PrintBackground  = true
                                },
                                LoadSettings = new LoadSettings {
                                    BlockLocalFileAccess = true
                                }
                            });
                        }
                        else
                        {
                            continue;
                        }

                        var bytes     = converter.Convert(document);
                        var pageCount = 0;
                        using (PdfReader reader = new PdfReader(bytes))
                        {
                            pageCount = reader.NumberOfPages;
                            for (int p = 0; p < pageCount; p++)
                            {
                                var page = writer.GetImportedPage(reader, p + 1);
                                writer.AddPage(page);
                            }
                        }

                        if (set == 0)
                        {
                            pageEvents.FamilySet[contributor.FamilyId] += pageCount;
                        }
                    }
                }
            }
            using (var combined = File.OpenRead(combinedPDFName))
            {
                combined.CopyTo(stream);
            }
        }
Example #9
0
        public void StandardMethod(Stream stream, CMSDataContext db, IEnumerable <ContributorInfo> q, StatementSpecification cs, int set = 0)
        {
            pageEvents.set      = set;
            pageEvents.PeopleId = 0;
            var contributors = q;
            var toDate       = ToDate.Date.AddHours(24).AddSeconds(-1);

            var font     = FontFactory.GetFont(FontFactory.HELVETICA, 11);
            var boldfont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11);

            var doc = new Document(PageSize.LETTER);

            doc.SetMargins(36f, 30f, 24f, 36f);
            var w = PdfWriter.GetInstance(doc, stream);

            w.PageEvent = pageEvents;
            doc.Open();
            var dc = w.DirectContent;

            var prevfid       = 0;
            var runningtotals = UUId.HasValue ? db.ContributionsRuns.Where(mm => mm.UUId == UUId).SingleOrDefault() : null;

            if (runningtotals != null)
            {
                runningtotals.Processed = 0;
                db.SubmitChanges();
            }
            var count = 0;

            foreach (var ci in contributors)
            {
                if (set > 0 && pageEvents.FamilySet[ci.PeopleId] != set)
                {
                    continue;
                }

                var contributions = APIContribution.Contributions(db, ci, FromDate, toDate, cs.Funds).ToList();
                var pledges       = APIContribution.Pledges(db, ci, toDate, cs.Funds).ToList();
                var giftsinkind   = APIContribution.GiftsInKind(db, ci, FromDate, toDate, cs.Funds).ToList();
                var nontaxitems   = db.Setting("DisplayNonTaxOnStatement", "false").ToBool()
                    ? APIContribution.NonTaxItems(db, ci, FromDate, toDate, cs.Funds).ToList()
                    : new List <NonTaxContribution>();

                if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) == 0)
                {
                    if (runningtotals != null)
                    {
                        runningtotals.Processed += 1;
                        runningtotals.CurrSet    = set;
                        db.SubmitChanges();
                    }
                    if (set == 0)
                    {
                        pageEvents.FamilySet[ci.PeopleId] = 0;
                    }

                    continue;
                }

                pageEvents.NextPeopleId = ci.PeopleId;
                doc.NewPage();
                if (prevfid != ci.FamilyId)
                {
                    prevfid = ci.FamilyId;
                    pageEvents.EndPageSet();
                    pageEvents.PeopleId = ci.PeopleId;
                }

                if (set == 0)
                {
                    pageEvents.FamilySet[ci.PeopleId] = 0;
                }

                count++;

                var css = @"
<style>
h1 { font-size: 24px; font-weight:normal; margin-bottom:0; }
h2 { font-size: 11px; font-weight:normal; margin-top: 0; }
p { font-size: 11px; }
</style>
";
                //----Church Name

                var t1 = new PdfPTable(1)
                {
                    TotalWidth = 72f * 5f
                };
                t1.DefaultCell.Border = Rectangle.NO_BORDER;
                string nameOfChurch = db.Setting("NameOfChurch", "Name of Church");
                string startAddress = db.Setting("StartAddress", "Start Address");
                string churchPhone  = db.Setting("ChurchPhone", "(000) 000-0000");
                var    html1        = cs.Header ?? db.ContentHtml("StatementHeader", string.Format(Resource1.ContributionStatementHeader, nameOfChurch, startAddress, churchPhone));
                var    html2        = cs.Notice ?? db.ContentHtml("StatementNotice", string.Format(Resource1.ContributionStatementNotice, nameOfChurch));

                var mh = new MyHandler();
                using (var sr = new StringReader(css + html1))
                {
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh, sr);
                }

                var cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }

                t1.AddCell(cell);
                t1.AddCell("\n");

                var t1a = new PdfPTable(1)
                {
                    TotalWidth = 72f * 5f
                };
                t1a.DefaultCell.Border = Rectangle.NO_BORDER;

                var ae = new PdfPTable(1);
                ae.DefaultCell.Border = Rectangle.NO_BORDER;
                ae.WidthPercentage    = 100;

                var a = new PdfPTable(1);
                a.DefaultCell.Indent = 25f;
                a.DefaultCell.Border = Rectangle.NO_BORDER;
                a.AddCell(new Phrase(ci.Name, font));
                foreach (var line in ci.MailingAddress.SplitLines())
                {
                    a.AddCell(new Phrase(line, font));
                }

                cell = new PdfPCell(a)
                {
                    Border = Rectangle.NO_BORDER
                };
                ae.AddCell(cell);

                cell = new PdfPCell(t1a.DefaultCell);
                cell.AddElement(ae);
                t1a.AddCell(ae);

                //-----Notice

                var t2 = new PdfPTable(1)
                {
                    TotalWidth = 72f * 3f
                };
                t2.DefaultCell.Border = Rectangle.NO_BORDER;

                var envno = "";
                if (db.Setting("PrintEnvelopeNumberOnStatement"))
                {
                    var ev = Person.GetExtraValue(db, ci.PeopleId, "EnvelopeNumber");
                    var s  = Util.PickFirst(ev.Data, ev.IntValue.ToString(), ev.StrValue);
                    if (s.HasValue())
                    {
                        envno = $"env: {s}";
                    }
                }

                t2.AddCell(db.Setting("NoPrintDateOnStatement")
                    ? new Phrase($"\nid:{ci.PeopleId}{envno} {ci.CampusId}", font)
                    : new Phrase($"\nprinted: {DateTime.Now:d} id:{ci.PeopleId}{envno} {ci.CampusId}", font));

                t2.AddCell("");
                var mh2 = new MyHandler();
                using (var sr = new StringReader(css + html2))
                {
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh2, sr);
                }

                cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh2.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }

                t2.AddCell(cell);

                // POSITIONING OF ADDRESSES
                //----Header

                var yp = doc.BottomMargin + db.Setting("StatementRetAddrPos", "10.125").ToFloat() * 72f;
                t1.WriteSelectedRows(0, -1, doc.LeftMargin - 0.1875f * 72f, yp, dc);

                yp = doc.BottomMargin + db.Setting("StatementAddrPos", "8.3375").ToFloat() * 72f;
                t1a.WriteSelectedRows(0, -1, doc.LeftMargin, yp, dc);

                yp = doc.BottomMargin + 10.125f * 72f;
                t2.WriteSelectedRows(0, -1, doc.LeftMargin + 72f * 4.4f, yp, dc);

                //----Contributions

                doc.Add(new Paragraph(" "));
                doc.Add(new Paragraph(" ")
                {
                    SpacingBefore = 72f * 2.125f
                });

                doc.Add(new Phrase($"\n  Period: {FromDate:d} - {toDate:d}", boldfont));

                var pos = w.GetVerticalPosition(true);

                var ct     = new ColumnText(dc);
                var gutter = 20f;
                if (NumberOfColumns == 1)
                {
                    gutter = 0;
                }
                var colwidth = (doc.Right - doc.Left - gutter) / NumberOfColumns;

                var t = (NumberOfColumns == 2)
                ? new PdfPTable(new[] { 18f, 24f, 15f })
                : new PdfPTable(new[] { 18f, 25f, 15f, 15f, 30f })
                {
                    WidthPercentage = 100
                };
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell = new PdfPCell(t.DefaultCell)
                {
                    Colspan = (NumberOfColumns == 2) ? 3 : 5,
                    Phrase  = new Phrase("Contributions\n", boldfont)
                };
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Date", boldfont));
                t.AddCell(new Phrase("Description", boldfont));

                cell = new PdfPCell(t.DefaultCell)
                {
                    HorizontalAlignment = Element.ALIGN_RIGHT,
                    Phrase = new Phrase("Amount", boldfont)
                };
                t.AddCell(cell);

                if (NumberOfColumns == 1)
                {
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_CENTER,
                        Phrase = ShowCheckNo ? new Phrase("Check No", boldfont) : new Phrase("", boldfont)
                    };

                    t.AddCell(cell);

                    t.AddCell(ShowNotes ? new Phrase("Notes", boldfont) : new Phrase("", boldfont));
                }

                t.DefaultCell.Border = Rectangle.NO_BORDER;

                var total = 0m;
                foreach (var c in contributions)
                {
                    t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                    t.AddCell(new Phrase(GetFundDisplayText(db, () => c.FundName, () => c.FundDescription), font));

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font)
                    };
                    t.AddCell(cell);
                    if (NumberOfColumns == 1)
                    {
                        cell = new PdfPCell(t.DefaultCell)
                        {
                            HorizontalAlignment = Element.ALIGN_CENTER,
                            Phrase = ShowCheckNo ? new Phrase(c.CheckNo, font) : new Phrase("", font)
                        };

                        t.AddCell(cell);

                        t.AddCell(ShowNotes ? new Phrase(c.Description?.Trim() ?? "", font) : new Phrase("", font));
                    }
                    total += (c.ContributionAmount ?? 0);
                }

                t.DefaultCell.Border = Rectangle.TOP_BORDER;

                cell = new PdfPCell(t.DefaultCell)
                {
                    Colspan = 2,
                    Phrase  = new Phrase("Total Contributions for period", boldfont)
                };
                t.AddCell(cell);

                cell = new PdfPCell(t.DefaultCell)
                {
                    HorizontalAlignment = Element.ALIGN_RIGHT,
                    Phrase = new Phrase(total.ToString("N2"), font)
                };
                t.AddCell(cell);
                if (NumberOfColumns == 1)
                {
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Colspan = 2,
                        Phrase  = new Phrase("")
                    };
                    t.AddCell(cell);
                }

                ct.AddElement(t);

                //------Pledges

                if (pledges.Count > 0)
                {
                    t = new PdfPTable((NumberOfColumns == 1)
                        ? new[] { 25f, 15f, 15f, 15f, 30f }
                        : new[] { 16f, 12f, 12f })
                    {
                        WidthPercentage = 100,
                        HeaderRows      = 2,
                    };
                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Colspan = (NumberOfColumns == 1) ? 5 : 3,
                        Phrase  = new Phrase("\n\nPledges\n", boldfont)
                    };
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Fund", boldfont));

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase("Pledge", boldfont)
                    };
                    t.AddCell(cell);

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase("Given", boldfont)
                    };
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    if (NumberOfColumns == 1)
                    {
                        t.AddCell(new Phrase("", boldfont));
                        t.AddCell(new Phrase("", boldfont));
                    }

                    foreach (var c in pledges)
                    {
                        t.AddCell(new Phrase(GetFundDisplayText(db, () => c.FundName, () => c.FundDescription), font));

                        cell = new PdfPCell(t.DefaultCell)
                        {
                            HorizontalAlignment = Element.ALIGN_RIGHT,
                            Phrase = new Phrase(c.Pledged.ToString2("N2"), font)
                        };
                        t.AddCell(cell);

                        cell = new PdfPCell(t.DefaultCell)
                        {
                            HorizontalAlignment = Element.ALIGN_RIGHT,
                            Phrase = new Phrase(c.Given.ToString2("N2"), font)
                        };
                        t.AddCell(cell);

                        if (NumberOfColumns == 1)
                        {
                            t.AddCell(new Phrase("", boldfont));
                            t.AddCell(new Phrase("", boldfont));
                        }
                    }

                    ct.AddElement(t);
                }

                //------Gifts In Kind

                if (giftsinkind.Count > 0)
                {
                    t = new PdfPTable((NumberOfColumns == 1)
                        ? new[] { 18f, 25f, 15f, 15f, 30f }
                        : new[] { 12f, 18f, 20f });

                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    // Headers
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Colspan = (NumberOfColumns == 1) ? 5 : 3,
                        Phrase  = new Phrase("\n\nGifts in Kind\n", boldfont)
                    };
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Phrase = new Phrase("Fund", boldfont)
                    };
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Phrase = new Phrase("Description", boldfont)
                    };
                    t.AddCell(cell);

                    if (NumberOfColumns == 1)
                    {
                        t.AddCell(new Phrase("", boldfont));
                        t.AddCell(new Phrase("", boldfont));
                    }

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    foreach (var c in giftsinkind)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                        cell = new PdfPCell(t.DefaultCell)
                        {
                            Phrase = new Phrase(GetFundDisplayText(db, () => c.FundName, () => c.FundDescription), font)
                        };
                        t.AddCell(cell);

                        cell = new PdfPCell(t.DefaultCell)
                        {
                            Colspan = (NumberOfColumns == 1) ? 3 : 1,
                            Phrase  = new Phrase(c.Description, font)
                        };
                        t.AddCell(cell);
                    }

                    ct.AddElement(t);
                }

                //-----Summary

                t = new PdfPTable((NumberOfColumns == 1)
                    ? new[] { 40f, 15f, 45f }
                    : new[] { 29f, 9f });

                t.WidthPercentage    = 100;
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell = new PdfPCell(t.DefaultCell)
                {
                    Colspan = (NumberOfColumns == 1) ? 3 : 2,
                    Phrase  = new Phrase("\n\nPeriod Summary\n", boldfont)
                };
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Fund", boldfont));

                cell = new PdfPCell(t.DefaultCell)
                {
                    HorizontalAlignment = Element.ALIGN_RIGHT,
                    Phrase = new Phrase("Amount", boldfont)
                };
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.NO_BORDER;
                if (NumberOfColumns == 1)
                {
                    t.AddCell(new Phrase("", boldfont));
                }

                foreach (var c in APIContribution.GiftSummary(db, ci, FromDate, toDate, cs.Funds))
                {
                    t.AddCell(new Phrase(GetFundDisplayText(db, () => c.FundName, () => c.FundDescription), font));

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase(c.Total.ToString2("N2"), font)
                    };
                    t.AddCell(cell);

                    if (NumberOfColumns == 1)
                    {
                        t.AddCell(new Phrase("", boldfont));
                    }
                }

                t.DefaultCell.Border = Rectangle.TOP_BORDER;
                t.AddCell(new Phrase("Total contributions for period", boldfont));

                cell = new PdfPCell(t.DefaultCell)
                {
                    HorizontalAlignment = Element.ALIGN_RIGHT,
                    Phrase = new Phrase(total.ToString("N2"), font)
                };
                t.AddCell(cell);

                if (NumberOfColumns == 1)
                {
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Phrase = new Phrase("")
                    };
                    t.AddCell(cell);
                }
                ct.AddElement(t);

                //------NonTax

                if (nontaxitems.Count > 0)
                {
                    t = new PdfPTable((NumberOfColumns == 1)
                        ? new[] { 18f, 25f, 15f, 15f, 30f }
                        : new[] { 18f, 24f, 15f });

                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Colspan = (NumberOfColumns == 1) ? 5 : 3,
                        Phrase  = new Phrase("\n\nNon Tax-Deductible Items\n", boldfont)
                    };
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    t.AddCell(new Phrase("Description", boldfont));
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase("Amount", boldfont)
                    };
                    t.AddCell(cell);
                    if (NumberOfColumns == 1)
                    {
                        t.AddCell(new Phrase("", boldfont));
                        t.AddCell(new Phrase("", boldfont));
                    }

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    var ntotal = 0m;
                    foreach (var c in nontaxitems)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                        t.AddCell(new Phrase(GetFundDisplayText(db, () => c.FundName, () => c.FundDescription), font));
                        cell = new PdfPCell(t.DefaultCell)
                        {
                            HorizontalAlignment = Element.ALIGN_RIGHT,
                            Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font)
                        };
                        t.AddCell(cell);
                        if (NumberOfColumns == 1)
                        {
                            t.AddCell(new Phrase("", boldfont));
                            t.AddCell(ShowNotes ? new Phrase(c.Description, font) : new Phrase("", font));
                        }
                        ntotal += (c.ContributionAmount ?? 0);
                    }

                    t.DefaultCell.Border = Rectangle.TOP_BORDER;
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        Colspan = 2,
                        Phrase  = new Phrase("Total Non Tax-Deductible Items for period", boldfont)
                    };
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell)
                    {
                        HorizontalAlignment = Element.ALIGN_RIGHT,
                        Phrase = new Phrase(ntotal.ToString("N2"), font)
                    };
                    t.AddCell(cell);
                    if (NumberOfColumns == 1)
                    {
                        t.AddCell(new Phrase("", boldfont));
                        t.AddCell(new Phrase("", boldfont));
                    }

                    ct.AddElement(t);
                }

                var col    = 0;
                var status = 0;
                while (ColumnText.HasMoreText(status))
                {
                    switch (col)
                    {
                    case 0:
                        ct.SetSimpleColumn(doc.Left, doc.Bottom, doc.Left + colwidth, pos);
                        break;

                    case 1:
                        ct.SetSimpleColumn(doc.Right - colwidth, doc.Bottom, doc.Right, pos);
                        break;
                    }

                    status = ct.Go();
                    if (NumberOfColumns == 2)
                    {
                        ++col;
                        if (col <= 1)
                        {
                            continue;
                        }
                        col = 0;
                    }
                    pos = doc.Top;
                    doc.NewPage();
                }
                if (runningtotals != null)
                {
                    runningtotals.Processed += 1;
                    runningtotals.CurrSet    = set;
                    db.SubmitChanges();
                }
            }

            if (count == 0)
            {
                doc.NewPage();
                doc.Add(new Paragraph("no data"));
                var a = new Anchor("see this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html")
                {
                    Reference = "https://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting"
                };
                doc.Add(a);
            }
            doc.Close();

            if (set == LastSet() && runningtotals != null)
            {
                runningtotals.Completed = DateTime.Now;
            }

            db.SubmitChanges();
        }
        public override void ExecuteResult(ControllerContext context)
        {
            var response = context.HttpContext.Response;

            response.ContentType = "application/pdf";
            response.AddHeader("content-disposition", "filename=foo.pdf");
            var cs = ContributionStatements.GetStatementSpecification(statementType ?? "all");

            if (showCheckNo || showNotes)
            {
                var c = new ContributionStatementsExtra
                {
                    FamilyId    = FamilyId,
                    FromDate    = FromDate,
                    PeopleId    = PeopleId,
                    SpouseId    = SpouseId,
                    ToDate      = ToDate,
                    typ         = typ,
                    ShowCheckNo = showCheckNo,
                    ShowNotes   = showNotes
                };

                IEnumerable <ContributorInfo> q = null;
                switch (typ)
                {
                case 1:
                    q = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, PeopleId, SpouseId, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;

                case 2:
                    FamilyId = DbUtil.Db.People.Single(p => p.PeopleId == PeopleId).FamilyId;
                    q        = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, 0, 0, FamilyId, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;

                case 3:
                    q = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, 0, 0, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;
                }
                c.Run(response.OutputStream, DbUtil.Db, q, cs);
            }
            else
            {
                var c = new ContributionStatements
                {
                    FamilyId = FamilyId,
                    FromDate = FromDate,
                    PeopleId = PeopleId,
                    SpouseId = SpouseId,
                    ToDate   = ToDate,
                    typ      = typ
                };

                IEnumerable <ContributorInfo> q = null;
                switch (typ)
                {
                case 1:
                    q = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, PeopleId, SpouseId, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;

                case 2:
                    FamilyId = DbUtil.Db.People.Single(p => p.PeopleId == PeopleId).FamilyId;
                    q        = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, 0, 0, FamilyId, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;

                case 3:
                    q = APIContribution.Contributors(DbUtil.Db, FromDate, ToDate, 0, 0, 0, cs.Funds, noaddressok, useMinAmt, singleStatement: singleStatement);
                    break;
                }
                c.Run(response.OutputStream, DbUtil.Db, q, cs);
            }
        }
        public void Run(Stream stream, CMSDataContext db, IEnumerable <ContributorInfo> q, ContributionStatements.StatementSpecification cs, int set = 0)
        {
            pageEvents.set      = set;
            pageEvents.PeopleId = 0;
            var contributors = q;

            PdfContentByte dc;
            var            font     = FontFactory.GetFont(FontFactory.HELVETICA, 11);
            var            boldfont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 11);

            var doc = new Document(PageSize.LETTER);

            doc.SetMargins(36f, 30f, 24f, 36f);
            var w = PdfWriter.GetInstance(doc, stream);

            w.PageEvent = pageEvents;
            doc.Open();
            dc = w.DirectContent;

            var prevfid       = 0;
            var runningtotals = db.ContributionsRuns.OrderByDescending(mm => mm.Id).FirstOrDefault();

            runningtotals.Processed = 0;
            db.SubmitChanges();
            var count = 0;

            foreach (var ci in contributors)
            {
                if (set > 0 && pageEvents.FamilySet[ci.PeopleId] != set)
                {
                    continue;
                }

                var contributions = APIContribution.Contributions(db, ci, FromDate, ToDate, cs.Funds).ToList();
                var pledges       = APIContribution.Pledges(db, ci, ToDate, cs.Funds).ToList();
                var giftsinkind   = APIContribution.GiftsInKind(db, ci, FromDate, ToDate, cs.Funds).ToList();
                var nontaxitems   = db.Setting("DisplayNonTaxOnStatement", "false").ToBool()
                    ? APIContribution.NonTaxItems(db, ci, FromDate, ToDate, cs.Funds).ToList()
                    : new List <NonTaxContribution>();

                if ((contributions.Count + pledges.Count + giftsinkind.Count + nontaxitems.Count) == 0)
                {
                    runningtotals.Processed += 1;
                    runningtotals.CurrSet    = set;
                    db.SubmitChanges();
                    if (set == 0)
                    {
                        pageEvents.FamilySet[ci.PeopleId] = 0;
                    }
                    continue;
                }

                pageEvents.NextPeopleId = ci.PeopleId;
                doc.NewPage();
                if (prevfid != ci.FamilyId)
                {
                    prevfid = ci.FamilyId;
                    pageEvents.EndPageSet();
                    pageEvents.PeopleId = ci.PeopleId;
                }
                if (set == 0)
                {
                    pageEvents.FamilySet[ci.PeopleId] = 0;
                }
                count++;

                var css = @"
<style>
h1 { font-size: 24px; font-weight:normal; margin-bottom:0; }
h2 { font-size: 11px; font-weight:normal; margin-top: 0; }
p { font-size: 11px; }
</style>
";
                //----Church Name

                var t1 = new PdfPTable(1);
                t1.TotalWidth         = 72f * 5f;
                t1.DefaultCell.Border = Rectangle.NO_BORDER;

                var mh = new MyHandler();
                using (var sr = new StringReader(css + cs.Header))
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh, sr);

                var cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }
                //cell.FixedHeight = 72f * 1.25f;
                t1.AddCell(cell);
                t1.AddCell("\n");

                var t1a = new PdfPTable(1);
                t1a.TotalWidth         = 72f * 5f;
                t1a.DefaultCell.Border = Rectangle.NO_BORDER;

                var ae = new PdfPTable(1);
                ae.DefaultCell.Border = Rectangle.NO_BORDER;
                ae.WidthPercentage    = 100;

                var a = new PdfPTable(1);
                a.DefaultCell.Indent = 25f;
                a.DefaultCell.Border = Rectangle.NO_BORDER;
                a.AddCell(new Phrase(ci.Name, font));
                foreach (var line in ci.MailingAddress.SplitLines())
                {
                    a.AddCell(new Phrase(line, font));
                }
                cell = new PdfPCell(a)
                {
                    Border = Rectangle.NO_BORDER
                };
                //cell.FixedHeight = 72f * 1.0625f;
                ae.AddCell(cell);

                cell = new PdfPCell(t1a.DefaultCell);
                cell.AddElement(ae);
                t1a.AddCell(ae);

                //-----Notice

                var t2 = new PdfPTable(1);
                t2.TotalWidth         = 72f * 3f;
                t2.DefaultCell.Border = Rectangle.NO_BORDER;

                var envno = "";
                if (db.Setting("PrintEnvelopeNumberOnStatement"))
                {
                    var ev = Person.GetExtraValue(db, ci.PeopleId, "EnvelopeNumber");
                    var s  = Util.PickFirst(ev.Data, ev.IntValue.ToString(), ev.StrValue);
                    if (s.HasValue())
                    {
                        envno = $" env: {Util.PickFirst(ev.Data, ev.IntValue.ToString(), ev.StrValue)}";
                    }
                }
                t2.AddCell(db.Setting("NoPrintDateOnStatement")
                    ? new Phrase($"\nid:{ci.PeopleId}{envno} {ci.CampusId}", font)
                    : new Phrase($"\nprinted: {DateTime.Now:d} id:{ci.PeopleId}{envno} {ci.CampusId}", font));

                t2.AddCell("");
                var mh2 = new MyHandler();
                using (var sr = new StringReader(css + cs.Notice))
                    XMLWorkerHelper.GetInstance().ParseXHtml(mh2, sr);
                cell = new PdfPCell(t1.DefaultCell);
                foreach (var e in mh2.elements)
                {
                    if (e.Chunks.Count > 0)
                    {
                        cell.AddElement(e);
                    }
                }
                t2.AddCell(cell);

                // POSITIONING OF ADDRESSES
                //----Header

                var yp = doc.BottomMargin +
                         db.Setting("StatementRetAddrPos", "10.125").ToFloat() * 72f;
                t1.WriteSelectedRows(0, -1,
                                     doc.LeftMargin - 0.1875f * 72f, yp, dc);

                yp = doc.BottomMargin +
                     db.Setting("StatementAddrPos", "8.3375").ToFloat() * 72f;
                t1a.WriteSelectedRows(0, -1, doc.LeftMargin, yp, dc);

                yp = doc.BottomMargin + 10.125f * 72f;
                t2.WriteSelectedRows(0, -1, doc.LeftMargin + 72f * 4.4f, yp, dc);

                //----Contributions

                doc.Add(new Paragraph(" "));
                doc.Add(new Paragraph(" ")
                {
                    SpacingBefore = 72f * 2.125f
                });

                doc.Add(new Phrase($"\n  Period: {FromDate:d} - {ToDate:d}", boldfont));

                var pos = w.GetVerticalPosition(true);

                var ct       = new ColumnText(dc);
                var colwidth = (doc.Right - doc.Left);

                var t = new PdfPTable(new[] { 15f, 25f, 15f, 15f, 30f });
                t.WidthPercentage    = 100;
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 5;
                cell.Phrase  = new Phrase("Contributions\n", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Date", boldfont));
                t.AddCell(new Phrase("Description", boldfont));

                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase("Amount", boldfont);
                t.AddCell(cell);

                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_CENTER;

                if (ShowCheckNo)
                {
                    cell.Phrase = new Phrase("Check No", boldfont);
                }
                else
                {
                    cell.Phrase = new Phrase("", boldfont);
                }

                t.AddCell(cell);

                if (ShowNotes)
                {
                    t.AddCell(new Phrase("Notes", boldfont));
                }
                else
                {
                    t.AddCell(new Phrase("", boldfont));
                }

                t.DefaultCell.Border = Rectangle.NO_BORDER;

                var total = 0m;
                foreach (var c in contributions)
                {
                    t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                    t.AddCell(new Phrase(c.FundName, font));

                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font);
                    t.AddCell(cell);

                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_CENTER;

                    if (ShowCheckNo)
                    {
                        cell.Phrase = new Phrase(c.CheckNo, font);
                    }
                    else
                    {
                        cell.Phrase = new Phrase("", font);
                    }

                    t.AddCell(cell);

                    if (ShowNotes)
                    {
                        t.AddCell(new Phrase(c.Description.trim(), font));
                    }
                    else
                    {
                        t.AddCell(new Phrase("", font));
                    }

                    total += (c.ContributionAmount ?? 0);
                }

                t.DefaultCell.Border = Rectangle.TOP_BORDER;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 2;
                cell.Phrase  = new Phrase("Total Contributions for period", boldfont);
                t.AddCell(cell);

                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase(total.ToString("N2"), font);
                t.AddCell(cell);

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 2;
                cell.Phrase  = new Phrase("");
                t.AddCell(cell);

                ct.AddElement(t);

                //------Pledges

                if (pledges.Count > 0)
                {
                    t = new PdfPTable(new[] { 25f, 15f, 15f, 15f, 30f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 5;
                    cell.Phrase  = new Phrase("\n\nPledges\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Fund", boldfont));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Pledge", boldfont);
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Given", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.AddCell(new Phrase("", boldfont));
                    t.AddCell(new Phrase("", boldfont));

                    foreach (var c in pledges)
                    {
                        t.AddCell(new Phrase(c.FundName, font));

                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.Pledged.ToString2("N2"), font);
                        t.AddCell(cell);

                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.Given.ToString2("N2"), font);
                        t.AddCell(cell);

                        t.AddCell(new Phrase("", boldfont));
                        t.AddCell(new Phrase("", boldfont));
                    }
                    ct.AddElement(t);
                }

                //------Gifts In Kind

                if (giftsinkind.Count > 0)
                {
                    t = new PdfPTable(new[] { 15f, 25f, 15f, 15f, 30f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    // Headers
                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 5;
                    cell.Phrase  = new Phrase("\n\nGifts in Kind\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    cell        = new PdfPCell(t.DefaultCell);
                    cell.Phrase = new Phrase("Fund", boldfont);
                    t.AddCell(cell);
                    cell        = new PdfPCell(t.DefaultCell);
                    cell.Phrase = new Phrase("Description", boldfont);
                    t.AddCell(cell);

                    t.AddCell(new Phrase("", boldfont));
                    t.AddCell(new Phrase("", boldfont));

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    foreach (var c in giftsinkind)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                        cell = new PdfPCell(t.DefaultCell);

                        cell.Phrase = new Phrase(c.FundName, font);
                        t.AddCell(cell);

                        cell         = new PdfPCell(t.DefaultCell);
                        cell.Colspan = 3;
                        cell.Phrase  = new Phrase(c.Description, font);
                        t.AddCell(cell);
                    }
                    ct.AddElement(t);
                }

                //-----Summary

                t = new PdfPTable(new[] { 40f, 15f, 45f });
                t.WidthPercentage    = 100;
                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.HeaderRows         = 2;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Colspan = 3;
                cell.Phrase  = new Phrase("\n\nPeriod Summary\n", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                t.AddCell(new Phrase("Fund", boldfont));

                cell = new PdfPCell(t.DefaultCell);
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase("Amount", boldfont);
                t.AddCell(cell);

                t.DefaultCell.Border = Rectangle.NO_BORDER;
                t.AddCell(new Phrase("", boldfont));

                foreach (var c in APIContribution.GiftSummary(db, ci, FromDate, ToDate, cs.Funds))
                {
                    t.AddCell(new Phrase(c.FundName, font));

                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(c.Total.ToString2("N2"), font);
                    t.AddCell(cell);

                    t.AddCell(new Phrase("", boldfont));
                }

                t.DefaultCell.Border = Rectangle.NO_BORDER;

                cell         = new PdfPCell(t.DefaultCell);
                cell.Border  = Rectangle.TOP_BORDER;
                cell.Colspan = 1;
                cell.Phrase  = new Phrase("Total Contributions for period", boldfont);
                t.AddCell(cell);

                cell        = new PdfPCell(t.DefaultCell);
                cell.Border = Rectangle.TOP_BORDER;
                cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                cell.Phrase = new Phrase(total.ToString("N2"), font);
                t.AddCell(cell);

                cell        = new PdfPCell(t.DefaultCell);
                cell.Phrase = new Phrase("");
                t.AddCell(cell);

                ct.AddElement(t);

                //------NonTax

                if (nontaxitems.Count > 0)
                {
                    t = new PdfPTable(new[] { 15f, 25f, 15f, 15f, 30f });
                    t.WidthPercentage    = 100;
                    t.DefaultCell.Border = Rectangle.NO_BORDER;
                    t.HeaderRows         = 2;

                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 5;
                    cell.Phrase  = new Phrase("\n\nNon Tax-Deductible Items\n", boldfont);
                    t.AddCell(cell);

                    t.DefaultCell.Border = Rectangle.BOTTOM_BORDER;
                    t.AddCell(new Phrase("Date", boldfont));
                    t.AddCell(new Phrase("Description", boldfont));
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase("Amount", boldfont);
                    t.AddCell(cell);
                    t.AddCell(new Phrase("", boldfont));
                    t.AddCell(new Phrase("", boldfont));

                    t.DefaultCell.Border = Rectangle.NO_BORDER;

                    var ntotal = 0m;
                    foreach (var c in nontaxitems)
                    {
                        t.AddCell(new Phrase(c.ContributionDate.ToString2("d"), font));
                        t.AddCell(new Phrase(c.FundName, font));
                        cell = new PdfPCell(t.DefaultCell);
                        cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                        cell.Phrase = new Phrase(c.ContributionAmount.ToString2("N2"), font);
                        t.AddCell(cell);
                        t.AddCell(new Phrase("", boldfont));
                        if (ShowNotes)
                        {
                            t.AddCell(new Phrase(c.Description, font));
                        }
                        else
                        {
                            t.AddCell(new Phrase("", font));
                        }

                        ntotal += (c.ContributionAmount ?? 0);
                    }
                    t.DefaultCell.Border = Rectangle.TOP_BORDER;
                    cell         = new PdfPCell(t.DefaultCell);
                    cell.Colspan = 2;
                    cell.Phrase  = new Phrase("Total Non Tax-Deductible Items for period", boldfont);
                    t.AddCell(cell);
                    cell = new PdfPCell(t.DefaultCell);
                    cell.HorizontalAlignment = Element.ALIGN_RIGHT;
                    cell.Phrase = new Phrase(ntotal.ToString("N2"), font);
                    t.AddCell(cell);
                    t.AddCell(new Phrase("", boldfont));
                    t.AddCell(new Phrase("", boldfont));


                    ct.AddElement(t);
                }

                var status = 0;
                while (ColumnText.HasMoreText(status))
                {
                    ct.SetSimpleColumn(doc.Left, doc.Bottom, doc.Left + colwidth, pos);

                    status = ct.Go();
                    pos    = doc.Top;
                    doc.NewPage();
                }

                runningtotals.Processed += 1;
                runningtotals.CurrSet    = set;
                db.SubmitChanges();
            }

            if (count == 0)
            {
                doc.NewPage();
                doc.Add(new Paragraph("no data"));
                var a = new Anchor("see this help document docs.touchpointsoftware.com/Finance/ContributionStatements.html")
                {
                    Reference = "http://docs.touchpointsoftware.com/Finance/ContributionStatements.html#troubleshooting"
                };
                doc.Add(a);
            }
            doc.Close();

            if (set == LastSet())
            {
                runningtotals.Completed = DateTime.Now;
            }
            db.SubmitChanges();
        }
        public void DoWork(ContributionStatements.StatementSpecification cs)
        {
            Db = DbUtil.Create(Host);
            DbUtil.Db.CommandTimeout = 1200;

            var noaddressok = !DbUtil.Db.Setting("RequireAddressOnStatement", true);

            showCheckNo = DbUtil.Db.Setting("RequireCheckNoOnStatement");
            showNotes   = DbUtil.Db.Setting("RequireNotesOnStatement");
            const bool UseMinAmt = true;

            var qc            = APIContribution.Contributors(DbUtil.Db, fd, td, 0, 0, 0, cs.Funds, noaddressok, UseMinAmt, StartsWith, Sort, tagid: TagId, excludeelectronic: ExcludeElectronic);
            var runningtotals = DbUtil.Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();

            runningtotals.Count = qc.Count();
            DbUtil.Db.SubmitChanges();
            if (showCheckNo || showNotes)
            {
                var c = new ContributionStatementsExtra
                {
                    FromDate    = fd,
                    ToDate      = td,
                    typ         = 3,
                    ShowCheckNo = showCheckNo,
                    ShowNotes   = showNotes
                };
                using (var stream = new FileStream(OutputFile, FileMode.Create))
                {
                    c.Run(stream, Db, qc, cs);
                }

                LastSet = c.LastSet();
                var sets = c.Sets();
                foreach (var set in sets)
                {
                    using (var stream = new FileStream(Output(OutputFile, set), FileMode.Create))
                    {
                        c.Run(stream, Db, qc, cs, set);
                    }
                }

                runningtotals           = DbUtil.Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();
                runningtotals.LastSet   = LastSet;
                runningtotals.Sets      = string.Join(",", sets);
                runningtotals.Completed = DateTime.Now;
                DbUtil.Db.SubmitChanges();
            }
            else
            {
                var c = new ContributionStatements
                {
                    FromDate = fd,
                    ToDate   = td,
                    typ      = 3
                };
                using (var stream = new FileStream(OutputFile, FileMode.Create))
                {
                    c.Run(stream, Db, qc, cs);
                }

                LastSet = c.LastSet();
                var sets = c.Sets();
                foreach (var set in sets)
                {
                    using (var stream = new FileStream(Output(OutputFile, set), FileMode.Create))
                    {
                        c.Run(stream, Db, qc, cs, set);
                    }
                }

                runningtotals           = DbUtil.Db.ContributionsRuns.OrderByDescending(mm => mm.Id).First();
                runningtotals.LastSet   = LastSet;
                runningtotals.Sets      = string.Join(",", sets);
                runningtotals.Completed = DateTime.Now;
                DbUtil.Db.SubmitChanges();
            }
        }
        public ActionResult ContributionStatements(DateTime?fromDate, DateTime?endDate, string startswith, string sort, int?tagid, bool excludeelectronic, string customstatement = null, bool exportcontributors = false)
        {
            if (!fromDate.HasValue || !endDate.HasValue)
            {
                return(Content("<h3>Must have a Startdate and Enddate</h3>"));
            }

            if (fromDate.Value > endDate.Value)
            {
                return(Content("<h3>The Startdate must be earlier than the Enddate</h3>"));
            }

            var spec = ContributionStatementsExtract.GetStatementSpecification(CurrentDatabase, customstatement);

            if (!startswith.HasValue())
            {
                startswith = null;
            }
            var        noaddressok = !CurrentDatabase.Setting("RequireAddressOnStatement", true);
            const bool useMinAmt   = true;

            if (tagid == 0)
            {
                tagid = null;
            }
            var qc           = APIContribution.Contributors(CurrentDatabase, fromDate.Value, endDate.Value, 0, 0, 0, spec.Funds, noaddressok, useMinAmt, startswith, sort, tagid: tagid, excludeelectronic: excludeelectronic);
            var contributors = qc.ToList();

            if (exportcontributors)
            {
                return(ExcelExportModel.ToDataTable(contributors).ToExcel("Contributors.xlsx"));
            }
            var statementsRun = new ContributionsRun
            {
                Started   = DateTime.Now,
                Count     = contributors.Count,
                Processed = 0,
                UUId      = Guid.NewGuid(),
                UserId    = CurrentDatabase.UserId,
            };

            CurrentDatabase.ContributionsRuns.InsertOnSubmit(statementsRun);
            CurrentDatabase.SubmitChanges();
            var cul  = CurrentDatabase.Setting("Culture", "en-US");
            var host = CurrentDatabase.Host;
            var id   = $"{statementsRun.UUId:n}";

            var output = Output(host, id);

            if (tagid == 0)
            {
                tagid = null;
            }

            var showCheckNo = CurrentDatabase.Setting("RequireCheckNoOnStatement");
            var showNotes   = CurrentDatabase.Setting("RequireNotesOnStatement");
            var statements  = new ContributionStatements
            {
                UUId     = Guid.Parse(id),
                FromDate = fromDate.Value,
                ToDate   = endDate.Value,
                typ      = 3,
                //TODO: once we switch to entirely html-based statement templates we won't need to check for these options
                NumberOfColumns = showCheckNo || showNotes ? 1 : 2,
                ShowCheckNo     = showCheckNo,
                ShowNotes       = showNotes,
            };

            if (CurrentDatabase.Setting("UseNewStatementsFormat"))
            {
                // Must do this before entering the background worker because it relies on the Application context
                statements.GetConverter();
            }

            var elmah = Elmah.ErrorLog.GetDefault(System.Web.HttpContext.Current);

            HostingEnvironment.QueueBackgroundWorkItem(ct =>
            {
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(cul);
                Thread.CurrentThread.CurrentCulture   = CultureInfo.CreateSpecificCulture(cul);
                try
                {
                    var m = new ContributionStatementsExtract(host, fromDate.Value, endDate.Value, output, startswith, sort, tagid, excludeelectronic)
                    {
                        id = id
                    };
                    m.DoWork(statements, spec, contributors);
                }
                catch (Exception e)
                {
                    elmah.Log(new Elmah.Error(e));
                    var db        = CMSDataContext.Create(host);
                    var run       = db.ContributionsRuns.Single(c => c.UUId == Guid.Parse(id));
                    run.Error     = e.Message;
                    run.Completed = DateTime.Now;
                    db.SubmitChanges();
                }
            });
            return(Redirect($"/Statements/Progress/{id}"));
        }