Exemple #1
0
        public static async Task <object> Handle(string organizationId, RosterRequest request)
        {
            request.pathParameters.TryGetValue("seaTurtleId", out string seaTurtleId);

            var seaTurtleService = new SeaTurtleService(organizationId);

            return(request.resource switch
            {
                "/sea-turtle-list-items" => request.httpMethod switch
                {
                    "GET" => await seaTurtleService.GetSeaTurtleListItems(),
                    _ => throw new ArgumentOutOfRangeException(ErrorHelper.InvalidHttpMethodForResource(request.httpMethod, request.resource)),
                },
        public static async Task <object> Handle(string organizationId, RosterRequest request)
        {
            const string baseMasterReportFileName_Page1 = "MASTER - Marine Turtle Holding Facility Quarterly Report Page 1.pdf";
            const string baseMasterReportFileName_Page2 = "MASTER - Marine Turtle Holding Facility Quarterly Report Page 2.pdf";
            const string baseMasterReportFileName_Page3 = "MASTER - Marine Turtle Holding Facility Quarterly Report Page 3.pdf";

            const int PAGE_1_LINES_PER_PAGE = 8;
            const int PAGE_2_LINES_PER_PAGE = 22;
            const int PAGE_3_LINES_PER_PAGE = 34;

            var       filledReportFileNames = new List <string>();
            var       fileTimestamp         = $"{DateTime.Now:yyyyMMddHHmmss} UTC";
            var       basePath = AppDomain.CurrentDomain.BaseDirectory;
            PdfReader pdfReader;

            var reportOptions = JsonSerializer.Deserialize <MarineTurtleHoldingFacilityQuarterlyReportOptionsDto>(request.body.GetRawText());

            reportOptions.dateFrom ??= "0000-00-00";
            reportOptions.dateThru ??= "9999-99-99";

            var organizationService = new OrganizationService(organizationId);
            var organization        = await organizationService.GetOrganization();

            var organizationAndPermitNumber = $"{organization.organizationName} - {organization.permitNumber}";

            string monthsAndYearOfReport;
            var    dateFrom = ReportHelper.ToDate(reportOptions.dateFrom);
            var    dateThru = ReportHelper.ToDate(reportOptions.dateThru);

            if (dateFrom.Year == dateThru.Year)
            {
                monthsAndYearOfReport = $"{dateFrom:dd} {dateFrom:MMMM} - {dateThru:dd} {dateThru:MMMM} {dateThru.Year}";
            }
            else
            {
                monthsAndYearOfReport = $"{dateFrom:dd} {dateFrom:MMMM} {dateFrom.Year} - {dateThru:dd} {dateThru:MMMM} {dateThru.Year}";
            }

            var seaTurtleService = new SeaTurtleService(organizationId);
            var seaTurtles       = (await seaTurtleService.GetSeaTurtles())
                                   .Where(x => !string.IsNullOrEmpty(x.dateAcquired) && x.dateAcquired.CompareTo(reportOptions.dateThru) <= 0)
                                   .Where(x => string.IsNullOrEmpty(x.dateRelinquished) || (!string.IsNullOrEmpty(x.dateRelinquished) && reportOptions.dateFrom.CompareTo(x.dateRelinquished) <= 0))
                                   .OrderBy(x => x.sidNumber)
                                   .ThenBy(x => x.dateAcquired)
                                   .ThenBy(x => x.seaTurtleName);

            var seaTurtleMapperConfiguration = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap <SeaTurtleModel, HoldingFacilitySeaTurtleReportItem>();
            });
            var seaTurtleMapper = new Mapper(seaTurtleMapperConfiguration);

            var seaTurtleReportItems = new List <HoldingFacilitySeaTurtleReportItem>();

            foreach (var seaTurtle in seaTurtles)
            {
                //----------------------------------------------------------------
                //-- kludge to account for all the data we want to cram into the
                //-- status/tag number line...ugh...
                //----------------------------------------------------------------
                var reportTagNumberFieldData = await GetReportTagNumberFieldData(organizationId, seaTurtle, reportOptions);

                var lines = ReportHelper.WrapLine(reportTagNumberFieldData, 92);

                //-- add main information line for this sea turtle
                var item = seaTurtleMapper.Map <HoldingFacilitySeaTurtleReportItem>(seaTurtle);
                item.reportTagNumberFieldData = lines.Length > 0 ? lines[0] : string.Empty;
                seaTurtleReportItems.Add(item);

                //-- add any status/tag info that overflowed to additional lines
                for (int i = 1; i < lines.Length; i++)
                {
                    seaTurtleReportItems.Add(new HoldingFacilitySeaTurtleReportItem
                    {
                        reportTagNumberFieldData = lines[i]
                    });
                }
            }

            var holdingTankService = new HoldingTankService(organizationId);
            var holdingTanks       = await holdingTankService.GetHoldingTanks();

            var holdingTankMeasurementReportItems = new List <HoldingFacilityHoldingTankMeasurementReportItem>();

            foreach (var holdingTank in holdingTanks)
            {
                var holdingTankMeasurementMapperConfiguration = new MapperConfiguration(cfg =>
                {
                    cfg.CreateMap <HoldingTankMeasurementModel, HoldingFacilityHoldingTankMeasurementReportItem>()
                    .ConstructUsing(x => new HoldingFacilityHoldingTankMeasurementReportItem(holdingTank.holdingTankName));
                });
                var holdingTankMeasurementMapper = new Mapper(holdingTankMeasurementMapperConfiguration);

                var holdingTankMeasurementService = new HoldingTankMeasurementService(organizationId, holdingTank.holdingTankId);
                var items = (await holdingTankMeasurementService.GetHoldingTankMeasurements())
                            .Where(x => reportOptions.dateFrom.CompareTo(x.dateMeasured) <= 0 && x.dateMeasured.CompareTo(reportOptions.dateThru) <= 0)
                            .Select(x => holdingTankMeasurementMapper.Map <HoldingFacilityHoldingTankMeasurementReportItem>(x))
                ;

                holdingTankMeasurementReportItems.AddRange(items);
            }

            if (reportOptions.groupTankDataBy == "tank")
            {
                holdingTankMeasurementReportItems = holdingTankMeasurementReportItems
                                                    .OrderBy(x => x.holdingTankName)
                                                    .ThenBy(x => x.dateMeasured).ToList();
            }
            else
            {
                holdingTankMeasurementReportItems = holdingTankMeasurementReportItems
                                                    .OrderBy(x => x.dateMeasured)
                                                    .ThenBy(x => x.holdingTankName).ToList();
            }

            //-- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] -- [PAGE 1] --

            var masterReportFileName_Page1 = Path.Combine(basePath, "pdf", baseMasterReportFileName_Page1);
            var filledReportFileName_Page1 = Path.Combine("/tmp", baseMasterReportFileName_Page1.Replace("MASTER - ", "FILLED - ").Replace(".pdf", $" - {fileTimestamp}.pdf"));

            filledReportFileNames.Add(filledReportFileName_Page1);

            pdfReader = new PdfReader(masterReportFileName_Page1);
            pdfReader.RemoveUsageRights();

            using (var fs = new FileStream(filledReportFileName_Page1, FileMode.Create))
            {
                var pdfStamper = new PdfStamper(pdfReader, fs, '\0', false);

                var info = pdfReader.Info;
                info["Title"]       = baseMasterReportFileName_Page1.Replace("MASTER - ", "").Replace(".pdf", $" - {fileTimestamp}.pdf");
                pdfStamper.MoreInfo = info;

                var acroFields = pdfStamper.AcroFields;

                acroFields.SetField("txtOrganizationAndPermitNumber", organizationAndPermitNumber);
                acroFields.SetField("txtMonthsAndYearOfReport", monthsAndYearOfReport);

                var pageOneItems = seaTurtleReportItems.Take(PAGE_1_LINES_PER_PAGE).ToList();
                for (int i = 0; i < pageOneItems.Count; i++)
                {
                    var item = pageOneItems[i];
                    FillSectionOneRow(acroFields, (i + 1).ToString().PadLeft(2, '0'), item, reportOptions);
                }

                pdfStamper.FormFlattening = true; // 'true' to make the PDF read-only
                pdfStamper.Close();
            }
            pdfReader.Close();

            //-- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] -- [PAGE 2] --

            var page2Items = seaTurtleReportItems.Skip(PAGE_1_LINES_PER_PAGE).ToList().ChunkBy(PAGE_2_LINES_PER_PAGE);

            for (int chunkIndex = 0; chunkIndex < page2Items.Count; chunkIndex++)
            {
                var masterReportFileName_Page2 = Path.Combine(basePath, "pdf", baseMasterReportFileName_Page2);
                var filledReportFileName_Page2 = Path.Combine("/tmp", baseMasterReportFileName_Page2.Replace("MASTER - ", "FILLED - ").Replace(".pdf", $" - {fileTimestamp} - {chunkIndex.ToString().PadLeft(2, '0')}.pdf"));
                filledReportFileNames.Add(filledReportFileName_Page2);

                pdfReader = new PdfReader(masterReportFileName_Page2);
                pdfReader.RemoveUsageRights();

                using (var fs = new FileStream(filledReportFileName_Page2, FileMode.Create))
                {
                    var pdfStamper = new PdfStamper(pdfReader, fs, '\0', false);

                    var info = pdfReader.Info;
                    info["Title"]       = baseMasterReportFileName_Page2.Replace("MASTER - ", "").Replace(".pdf", $" - {fileTimestamp}.pdf");
                    pdfStamper.MoreInfo = info;

                    var acroFields = pdfStamper.AcroFields;

                    acroFields.SetField("txtOrganizationAndPermitNumber", organizationAndPermitNumber);
                    acroFields.SetField("txtMonthsAndYearOfReport", monthsAndYearOfReport);

                    for (int i = 0; i < page2Items[chunkIndex].Count; i++)
                    {
                        var item = page2Items[chunkIndex][i];
                        FillSectionOneRow(acroFields, (i + 1 + PAGE_1_LINES_PER_PAGE).ToString().PadLeft(2, '0'), item, reportOptions);
                    }

                    pdfStamper.FormFlattening = true; // 'true' to make the PDF read-only
                    pdfStamper.Close();
                }
                pdfReader.Close();
            }

            //-- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] -- [PAGE 3] --

            var page3Items = holdingTankMeasurementReportItems.ChunkBy(PAGE_3_LINES_PER_PAGE);

            for (int chunkIndex = 0; chunkIndex < page3Items.Count; chunkIndex++)
            {
                var masterReportFileName_Page3 = Path.Combine(basePath, "pdf", baseMasterReportFileName_Page3);
                var filledReportFileName_Page3 = Path.Combine("/tmp", baseMasterReportFileName_Page3.Replace("MASTER - ", "FILLED - ").Replace(".pdf", $" - {fileTimestamp} - {chunkIndex.ToString().PadLeft(2, '0')}.pdf"));
                filledReportFileNames.Add(filledReportFileName_Page3);

                pdfReader = new PdfReader(masterReportFileName_Page3);
                pdfReader.RemoveUsageRights();

                using (var fs = new FileStream(filledReportFileName_Page3, FileMode.Create))
                {
                    var pdfStamper = new PdfStamper(pdfReader, fs, '\0', false);

                    var info = pdfReader.Info;
                    info["Title"]       = baseMasterReportFileName_Page3.Replace("MASTER - ", "").Replace(".pdf", $" - {fileTimestamp}.pdf");
                    pdfStamper.MoreInfo = info;

                    var acroFields = pdfStamper.AcroFields;

                    acroFields.SetField("txtOrganizationAndPermitNumber", organizationAndPermitNumber);
                    acroFields.SetField("txtMonthsAndYearOfReport", monthsAndYearOfReport);

                    for (int i = 0; i < page3Items[chunkIndex].Count; i++)
                    {
                        var item        = page3Items[chunkIndex][i];
                        var fieldNumber = (i + 1).ToString().PadLeft(2, '0');
                        acroFields.SetField($"txtDate{fieldNumber}", item.dateMeasured);
                        acroFields.SetField($"txtTank{fieldNumber}", item.holdingTankName);
                        acroFields.SetField($"txtTemperature{fieldNumber}", item.temperature);
                        acroFields.SetField($"txtSalinity{fieldNumber}", item.salinity);
                        acroFields.SetField($"txtPH{fieldNumber}", item.ph);
                    }

                    pdfStamper.FormFlattening = true; // 'true' to make the PDF read-only
                    pdfStamper.Close();
                }
                pdfReader.Close();
            }

            // =========================================================================================================================

            const string masterReportFileName_Final = "MASTER - Marine Turtle Holding Facility Quarterly Report.pdf";
            var          filledReportFileName_Final = Path.Combine("/tmp", masterReportFileName_Final.Replace("MASTER - ", "FILLED - ").Replace(".pdf", $" - {fileTimestamp}.pdf"));

            ReportHelper.ConcatenatePdfFiles(filledReportFileNames, filledReportFileName_Final);

            var bytes = await File.ReadAllBytesAsync(filledReportFileName_Final);

            return(bytes);
        }
        public static async Task <object> Handle(string organizationId, RosterRequest request)
        {
            var response = new ContentDto();

            var reportOptions = JsonSerializer.Deserialize <ReportOptionsDateRangeDto>(request.body.GetRawText());

            reportOptions.dateFrom ??= "0000-00-00";
            reportOptions.dateThru ??= "9999-99-99";

            var seaTurtleService = new SeaTurtleService(organizationId);
            var seaTurtles       = (await seaTurtleService.GetSeaTurtles())
                                   .Where(x => !string.IsNullOrEmpty(x.dateAcquired) && x.dateAcquired.CompareTo(reportOptions.dateThru) <= 0)
                                   .Where(x => string.IsNullOrEmpty(x.dateRelinquished) || (!string.IsNullOrEmpty(x.dateRelinquished) && reportOptions.dateFrom.CompareTo(x.dateRelinquished) <= 0))
                                   .OrderBy(x => x.sidNumber)
                                   .ThenBy(x => x.dateAcquired)
                                   .ThenBy(x => x.seaTurtleName);

            response.totalCount = seaTurtles.Count();

            SummaryItemDto GetSummaryItem(string label, string propertyName)
            {
                var count = seaTurtles.Count(x => Convert.ToBoolean(x.GetType().GetProperty(propertyName).GetValue(x)));

                return(new SummaryItemDto
                {
                    label = label,
                    count = count,
                    percentageOfTotal = (double)count / response.totalCount * 100
                });
            }

            response.summaryItems.Add(GetSummaryItem("Boat/Propeller strike", nameof(SeaTurtleModel.injuryBoatStrike)));
            response.summaryItems.Add(GetSummaryItem("Intestinal impaction", nameof(SeaTurtleModel.injuryIntestinalImpaction)));
            response.summaryItems.Add(GetSummaryItem("Line/Net entanglement", nameof(SeaTurtleModel.injuryLineEntanglement)));
            response.summaryItems.Add(GetSummaryItem("Fish hook", nameof(SeaTurtleModel.injuryFishHook)));
            response.summaryItems.Add(GetSummaryItem("Upper respiratory", nameof(SeaTurtleModel.injuryUpperRespiratory)));
            response.summaryItems.Add(GetSummaryItem("Shark/Bird bite", nameof(SeaTurtleModel.injuryAnimalBite)));
            response.summaryItems.Add(GetSummaryItem("Fibropapilloma", nameof(SeaTurtleModel.injuryFibropapilloma)));
            response.summaryItems.Add(GetSummaryItem("Misc. epidemic", nameof(SeaTurtleModel.injuryMiscEpidemic)));
            response.summaryItems.Add(GetSummaryItem("DOA", nameof(SeaTurtleModel.injuryDoa)));
            response.summaryItems.Add(GetSummaryItem("Other", nameof(SeaTurtleModel.injuryOther)));

            var noneCount = seaTurtles.Count(x =>
                                             !x.injuryBoatStrike && !x.injuryIntestinalImpaction && !x.injuryLineEntanglement &&
                                             !x.injuryFishHook && !x.injuryUpperRespiratory && !x.injuryAnimalBite &&
                                             !x.injuryFibropapilloma && !x.injuryMiscEpidemic && !x.injuryDoa && !x.injuryOther
                                             );

            var noneCountSummaryItem = new SummaryItemDto
            {
                label             = "None",
                count             = noneCount,
                percentageOfTotal = (double)noneCount / response.totalCount * 100
            };

            response.summaryItems.Add(noneCountSummaryItem);

            foreach (var seaTurtle in seaTurtles)
            {
                var detailItem = new DetailItemDto
                {
                    seaTurtleId               = seaTurtle.seaTurtleId,
                    seaTurtleName             = seaTurtle.seaTurtleName ?? seaTurtle.sidNumber,
                    injuryBoatStrike          = seaTurtle.injuryBoatStrike,
                    injuryIntestinalImpaction = seaTurtle.injuryIntestinalImpaction,
                    injuryLineEntanglement    = seaTurtle.injuryLineEntanglement,
                    injuryFishHook            = seaTurtle.injuryFishHook,
                    injuryUpperRespiratory    = seaTurtle.injuryUpperRespiratory,
                    injuryAnimalBite          = seaTurtle.injuryAnimalBite,
                    injuryFibropapilloma      = seaTurtle.injuryFibropapilloma,
                    injuryMiscEpidemic        = seaTurtle.injuryMiscEpidemic,
                    injuryDoa   = seaTurtle.injuryDoa,
                    injuryOther = seaTurtle.injuryOther,
                };

                response.detailItems.Add(detailItem);
            }

            return(response);
        }
Exemple #4
0
        public static async Task <object> Handle(string organizationId, RosterRequest request)
        {
            var response = new ContentDto();

            var reportOptions = JsonSerializer.Deserialize <TurtleTagReportOptionsDto>(request.body.GetRawText());

            reportOptions.dateFrom ??= "0000-00-00";
            reportOptions.dateThru ??= "9999-99-99";

            var seaTurtleService = new SeaTurtleService(organizationId);
            var seaTurtles       = (await seaTurtleService.GetSeaTurtles()).OrderBy(x => x.dateAcquired).ThenBy(x => x.sidNumber).ThenBy(x => x.seaTurtleName);

            foreach (var seaTurtle in seaTurtles)
            {
                var detailItem = new DetailItemDto
                {
                    seaTurtleId       = seaTurtle.seaTurtleId,
                    sidNumber         = seaTurtle.sidNumber,
                    seaTurtleName     = seaTurtle.seaTurtleName,
                    dateRelinquished  = seaTurtle.dateRelinquished,
                    strandingIdNumber = seaTurtle.strandingIdNumber,
                };

                var seaTurtleTagService = new SeaTurtleTagService(organizationId, seaTurtle.seaTurtleId);
                var seaTurtleTags       = await seaTurtleTagService.GetSeaTurtleTags();

                seaTurtleTags = seaTurtleTags.Where(x =>
                                                    (reportOptions.isPit && x.tagType == "PIT") ||
                                                    (reportOptions.isLff && x.location == "LFF" && x.tagType != "PIT") ||
                                                    (reportOptions.isRff && x.location == "RFF" && x.tagType != "PIT") ||
                                                    (reportOptions.isLrf && x.location == "LRF" && x.tagType != "PIT") ||
                                                    (reportOptions.isRrf && x.location == "RRF" && x.tagType != "PIT")
                                                    ).ToList();
                var orderedTags = seaTurtleTags.OrderBy(x => x.tagType != "PIT").ThenBy(x => x.location);
                detailItem.tags = orderedTags.Select(x => new DetailItemTagDto {
                    label = x.tagType == "PIT" ? "PIT" : x.location, tagNumber = x.tagNumber, dateTagged = x.dateTagged
                }).ToList();

                var includeItem = false;
                switch (reportOptions.filterDateType)
                {
                case "dateTagged":
                    includeItem = detailItem.tags.Any(x => !string.IsNullOrEmpty(x.dateTagged) &&
                                                      (reportOptions.dateFrom.CompareTo(x.dateTagged) <= 0 && x.dateTagged.CompareTo(reportOptions.dateThru) <= 0));
                    break;

                case "dateAcquired":
                    includeItem = string.IsNullOrEmpty(seaTurtle.dateAcquired) ||
                                  (reportOptions.dateFrom.CompareTo(seaTurtle.dateAcquired) <= 0 && seaTurtle.dateAcquired.CompareTo(reportOptions.dateThru) <= 0);
                    break;

                case "dateRelinquished":
                    if (reportOptions.includeNonRelinquishedTurtles)
                    {
                        includeItem = string.IsNullOrEmpty(seaTurtle.dateRelinquished) ||
                                      (reportOptions.dateFrom.CompareTo(seaTurtle.dateRelinquished) <= 0 && seaTurtle.dateRelinquished.CompareTo(reportOptions.dateThru) <= 0);
                    }
                    else
                    {
                        includeItem = !string.IsNullOrEmpty(seaTurtle.dateRelinquished) &&
                                      (reportOptions.dateFrom.CompareTo(seaTurtle.dateRelinquished) <= 0 && seaTurtle.dateRelinquished.CompareTo(reportOptions.dateThru) <= 0);
                    }
                    break;

                default:
                    break;
                }

                if (includeItem)
                {
                    response.detailItems.Add(detailItem);
                }
            }

            return(response);
        }
Exemple #5
0
        public static async Task <object> Handle(string organizationId, RosterRequest request)
        {
            var reportOptions = JsonSerializer.Deserialize <TaggingDataFormReportOptionsDto>(request.body.GetRawText());

            var fileTimestamp = $"{DateTime.Now:yyyyMMddHHmmss} UTC";

            const string baseMasterReportFileName = "MASTER - Tagging Data form.pdf";
            var          basePath = AppDomain.CurrentDomain.BaseDirectory;

            var masterReportFileName = Path.Combine(basePath, "pdf", baseMasterReportFileName);
            var filledReportFileName = Path.Combine("/tmp", baseMasterReportFileName.Replace("MASTER - ", "FILLED - ").Replace(".pdf", $" - {fileTimestamp}.pdf"));

            var organizationService = new OrganizationService(organizationId);
            var organization        = await organizationService.GetOrganization();

            var organizationInformation = $"{organization.organizationName} - {organization.phone} - {organization.emailAddress}";

            var seaTurtleService = new SeaTurtleService(organizationId);
            var seaTurtle        = await seaTurtleService.GetSeaTurtle(reportOptions.seaTurtleId);

            var seaTurtleTagService = new SeaTurtleTagService(organizationId, reportOptions.seaTurtleId);
            var seaTurtleTags       = await seaTurtleTagService.GetSeaTurtleTags();

            var seaTurtleMorphometricService = new SeaTurtleMorphometricService(organizationId, reportOptions.seaTurtleId);
            var seaTurtleMorphometrics       = await seaTurtleMorphometricService.GetSeaTurtleMorphometrics();

            var nonPitTags = seaTurtleTags.Where(x => x.tagType != "PIT" && !string.IsNullOrWhiteSpace(x.tagNumber));

            var flipperTagLeftFront  = string.Join(", ", nonPitTags.Where(x => x.location == "LFF").Select(x => x.tagNumber));
            var flipperTagRightFront = string.Join(", ", nonPitTags.Where(x => x.location == "RFF").Select(x => x.tagNumber));
            var flipperTagLeftRear   = string.Join(", ", nonPitTags.Where(x => x.location == "LRF").Select(x => x.tagNumber));
            var flipperTagRightRear  = string.Join(", ", nonPitTags.Where(x => x.location == "RRF").Select(x => x.tagNumber));

            var pitTags        = seaTurtleTags.Where(x => x.tagType == "PIT");
            var pitTagNumber   = string.Join(", ", pitTags.Where(x => !string.IsNullOrWhiteSpace(x.tagNumber)).Select(x => x.tagNumber));
            var pitTagLocation = string.Join(", ", pitTags.Where(x => !string.IsNullOrWhiteSpace(x.location)).Select(x => x.location));

            //----------------------------------------------------------------------------------------------------

            var pdfReader = new PdfReader(masterReportFileName);

            pdfReader.RemoveUsageRights();

            var fs         = new FileStream(filledReportFileName, FileMode.Create);
            var pdfStamper = new PdfStamper(pdfReader, fs, '\0', false);

            var info = pdfReader.Info;

            info["Title"]       = baseMasterReportFileName.Replace("MASTER - ", "").Replace(".pdf", $" - {fileTimestamp}.pdf");
            pdfStamper.MoreInfo = info;

            var acroFields = pdfStamper.AcroFields;

            acroFields.SetField("txtSID", reportOptions.printSidOnForm ? $"SID:  {seaTurtle.sidNumber}" : string.Empty);
            acroFields.SetField("txtSpecies", seaTurtle.species);

            string dateCaptured = seaTurtle.dateCaptured ?? seaTurtle.dateAcquired;

            if (!string.IsNullOrEmpty(dateCaptured))
            {
                acroFields.SetField("txtDateCapturedDay", dateCaptured.Substring(8, 2));
                acroFields.SetField("txtDateCapturedMonth", dateCaptured.Substring(5, 2));
                acroFields.SetField("txtDateCapturedYear", dateCaptured.Substring(0, 4));
            }

            if (!string.IsNullOrEmpty(seaTurtle.dateRelinquished))
            {
                acroFields.SetField("txtDateReleasedDay", seaTurtle.dateRelinquished.Substring(8, 2));
                acroFields.SetField("txtDateReleasedMonth", seaTurtle.dateRelinquished.Substring(5, 2));
                acroFields.SetField("txtDateReleasedYear", seaTurtle.dateRelinquished.Substring(0, 4));
            }

            acroFields.SetField("txtFlipperTagLeftFront", flipperTagLeftFront);
            acroFields.SetField("txtFlipperTagRightFront", flipperTagRightFront);
            acroFields.SetField("txtFlipperTagLeftRear", flipperTagLeftRear);
            acroFields.SetField("txtFlipperTagRightRear", flipperTagRightRear);

            acroFields.SetField("txtPitTagNumber", pitTagNumber);
            acroFields.SetField("txtPitTagLocation", pitTagLocation);

            if (seaTurtle.wasCarryingTagsWhenEnc)
            {
                acroFields.SetField("radTurtleCarryingTags", "Yes");

                if (seaTurtle.recaptureType == "S")
                {
                    acroFields.SetField("radRecapture", "1");
                }
                else if (seaTurtle.recaptureType == "D")
                {
                    acroFields.SetField("radRecapture", "2");
                }
            }
            else
            {
                acroFields.SetField("radTurtleCarryingTags", "No");
            }

            acroFields.SetField("txtTagReturnAddress", seaTurtle.tagReturnAddress);

            acroFields.SetField("txtOrganizationInformation", organizationInformation);

            switch (seaTurtle.captureProjectType)
            {
            case "N":
                acroFields.SetField("radProjectType", "NestingBeach");
                switch (seaTurtle.didTurtleNest)
                {
                case "Y":
                    acroFields.SetField("radDidTurtleNest", "Yes");
                    break;

                case "N":
                    acroFields.SetField("radDidTurtleNest", "No");
                    break;

                case "U":
                    acroFields.SetField("radDidTurtleNest", "Undetermined");
                    break;

                default:
                    break;
                }
                break;

            case "T":
                acroFields.SetField("radProjectType", "TangleNet");
                break;

            case "P":
                acroFields.SetField("radProjectType", "PoundNet");
                break;

            case "H":
                acroFields.SetField("radProjectType", "HandCatch");
                break;

            case "S":
                acroFields.SetField("radProjectType", "Stranding");
                break;

            case "O":
                acroFields.SetField("radProjectType", "Other");
                acroFields.SetField("txtProjectTypeOther", seaTurtle.captureProjectOther);
                break;

            default:
                break;
            }

            if (reportOptions.populateFacilityField)
            {
                acroFields.SetField("txtFacility", organizationInformation);
            }

            var acquiredCounty    = !string.IsNullOrEmpty(seaTurtle.acquiredCounty) ? $"; County: {seaTurtle.acquiredCounty}" : string.Empty;
            var acquiredLatitude  = !string.IsNullOrEmpty(seaTurtle.acquiredLatitude) ? $"; Latitude: {seaTurtle.acquiredLatitude}" : string.Empty;
            var acquiredLongitude = !string.IsNullOrEmpty(seaTurtle.acquiredLongitude) ? $"; Longitude: {seaTurtle.acquiredLongitude}" : string.Empty;
            var captureLocation   = $"{seaTurtle.acquiredFrom}{acquiredCounty}{acquiredLatitude}{acquiredLongitude}".TrimStart(' ', ';');

            acroFields.SetField("txtCaptureLocation", captureLocation);

            var relinquishedCounty    = !string.IsNullOrEmpty(seaTurtle.relinquishedCounty) ? $"; County: {seaTurtle.relinquishedCounty}" : string.Empty;
            var relinquishedLatitude  = !string.IsNullOrEmpty(seaTurtle.relinquishedLatitude) ? $"; Latitude: {seaTurtle.relinquishedLatitude}" : string.Empty;
            var relinquishedLongitude = !string.IsNullOrEmpty(seaTurtle.relinquishedLongitude) ? $"; Longitude: {seaTurtle.relinquishedLongitude}" : string.Empty;
            var releaseLocation       = $"{seaTurtle.relinquishedTo}{relinquishedCounty}{relinquishedLatitude}{relinquishedLongitude}".TrimStart(' ', ';');

            acroFields.SetField("txtReleaseLocation", releaseLocation);

            // If first string is greater than second string, it returns 1 else it returns -1.
            var dateAcquired        = string.IsNullOrWhiteSpace(seaTurtle.dateAcquired) ? "0000-00-00" : seaTurtle.dateAcquired;
            var dateRelinquished    = string.IsNullOrWhiteSpace(seaTurtle.dateRelinquished) ? "9999-99-99" : seaTurtle.dateRelinquished;
            var closestMorphometric = new SeaTurtleMorphometricModel();

            if (reportOptions.useMorphometricsClosestTo == "dateAcquired")
            {
                // get first after acquired...
                closestMorphometric = seaTurtleMorphometrics
                                      .Where(x => string.Compare(dateAcquired, x.dateMeasured) == -1)
                                      .OrderBy(x => x.dateMeasured)
                                      .FirstOrDefault();

                //...if none, try earliest date
                closestMorphometric ??= seaTurtleMorphometrics
                .OrderBy(x => x.dateMeasured)
                .FirstOrDefault();
            }
            else //if (useMorphometricsClosestTo == "dateRelinquished")
            {
                // get first before relinquished...
                closestMorphometric = seaTurtleMorphometrics
                                      .Where(x => string.Compare(dateRelinquished, x.dateMeasured) == 1)
                                      .OrderByDescending(x => x.dateMeasured)
                                      .FirstOrDefault();

                //...if none, try latest date
                closestMorphometric ??= seaTurtleMorphometrics
                .OrderByDescending(x => x.dateMeasured)
                .FirstOrDefault();
            }

            if (closestMorphometric != null)
            {
                if (closestMorphometric.sclNotchNotchValue > 0)
                {
                    if (closestMorphometric.sclNotchNotchUnits == "cm")
                    {
                        acroFields.SetField("txtSclMinCm", Convert.ToString(closestMorphometric.sclNotchNotchValue));
                    }
                    else if (closestMorphometric.sclNotchNotchUnits == "in")
                    {
                        acroFields.SetField("txtSclMinIn", Convert.ToString(closestMorphometric.sclNotchNotchValue));
                    }
                }
                if (closestMorphometric.sclNotchTipValue > 0)
                {
                    if (closestMorphometric.sclNotchTipUnits == "cm")
                    {
                        acroFields.SetField("txtSclNotchTipCm", Convert.ToString(closestMorphometric.sclNotchTipValue));
                    }
                    else if (closestMorphometric.sclNotchTipUnits == "in")
                    {
                        acroFields.SetField("txtSclNotchTipIn", Convert.ToString(closestMorphometric.sclNotchTipValue));
                    }
                }
                if (closestMorphometric.scwValue > 0)
                {
                    if (closestMorphometric.scwUnits == "cm")
                    {
                        acroFields.SetField("txtScwCm", Convert.ToString(closestMorphometric.scwValue));
                    }
                    else if (closestMorphometric.scwUnits == "in")
                    {
                        acroFields.SetField("txtScwIn", Convert.ToString(closestMorphometric.scwValue));
                    }
                }
                if (closestMorphometric.cclNotchNotchValue > 0)
                {
                    if (closestMorphometric.cclNotchNotchUnits == "cm")
                    {
                        acroFields.SetField("txtCclMinCm", Convert.ToString(closestMorphometric.cclNotchNotchValue));
                    }
                    else if (closestMorphometric.cclNotchNotchUnits == "in")
                    {
                        acroFields.SetField("txtCclMinIn", Convert.ToString(closestMorphometric.cclNotchNotchValue));
                    }
                }
                if (closestMorphometric.cclNotchTipValue > 0)
                {
                    if (closestMorphometric.cclNotchTipUnits == "cm")
                    {
                        acroFields.SetField("txtCclNotchTipCm", Convert.ToString(closestMorphometric.cclNotchTipValue));
                    }
                    else if (closestMorphometric.cclNotchTipUnits == "in")
                    {
                        acroFields.SetField("txtCclNotchTipIn", Convert.ToString(closestMorphometric.cclNotchTipValue));
                    }
                }
                if (closestMorphometric.ccwValue > 0)
                {
                    if (closestMorphometric.ccwUnits == "cm")
                    {
                        acroFields.SetField("txtCcwCm", Convert.ToString(closestMorphometric.ccwValue));
                    }
                    else if (closestMorphometric.ccwUnits == "in")
                    {
                        acroFields.SetField("txtCcwIn", Convert.ToString(closestMorphometric.ccwValue));
                    }
                }
                if (closestMorphometric.weightValue > 0)
                {
                    if (closestMorphometric.weightUnits == "kg")
                    {
                        acroFields.SetField("txtWeightKg", Convert.ToString(closestMorphometric.weightValue));
                    }
                    else if (closestMorphometric.weightUnits == "lb")
                    {
                        acroFields.SetField("txtWeightLbs", Convert.ToString(closestMorphometric.weightValue));
                    }
                }
            }

            if (seaTurtle.inspectedForTagScars)
            {
                acroFields.SetField("radTagScars", "Yes");
                acroFields.SetField("txtTagScars", seaTurtle.tagScarsLocated);
            }
            else
            {
                acroFields.SetField("radTagScars", "No");
            }

            if (seaTurtle.scannedForPitTags)
            {
                acroFields.SetField("radPitTags", "Yes");
                acroFields.SetField("txtPitTags", seaTurtle.pitTagsScanFrequency);
            }
            else
            {
                acroFields.SetField("radPitTags", "No");
            }

            if (seaTurtle.scannedForMagneticWires)
            {
                acroFields.SetField("radMagneticWires", "Yes");
                acroFields.SetField("txtMagneticWires", seaTurtle.magneticWiresLocated);
            }
            else
            {
                acroFields.SetField("radMagneticWires", "No");
            }

            if (seaTurtle.inspectedForLivingTags)
            {
                acroFields.SetField("radLivingTags", "Yes");
                acroFields.SetField("txtLivingTags", seaTurtle.livingTagsLocated);
            }
            else
            {
                acroFields.SetField("radLivingTags", "No");
            }

            acroFields.SetField("radAdditionalRemarksOnBack", reportOptions.additionalRemarksOrDataOnBackOfForm ? "Yes" : "No");

            // =============================================================================

            pdfStamper.FormFlattening = true; // 'true' to make the PDF read-only
            pdfStamper.Close();
            pdfReader.Close();

            var bytes = await File.ReadAllBytesAsync(filledReportFileName);

            return(bytes);
        }