/// <summary> /// Get the blue cards for a merit badge student /// </summary> /// <param name="student">The merit badge student we want to get the blue cards for</param> /// <param name="numberOfPDFs">The number of PDFs we are going to generate</param> /// <param name="writeVoid">Whether VOID should be written on unused blue cards</param> /// <returns>A MemoryStream containing the blue cards</returns> public static MemoryStream GetBlueCards(MeritBadgeStudentViewModel student, int numberOfPDFs, bool writeVoid = true) { var blueCardPDFFileName = BlueCardFields.BlueCardFormName; var blueCardPDFFilePath = Path.Combine("Files", blueCardPDFFileName); using Stream pdfInputStream = new FileStream(path: blueCardPDFFilePath, mode: FileMode.Open); using var resultPDFOutputStream = new MemoryStream(); using Stream resultPDFStream = FillForm(pdfInputStream, student, numberOfPDFs, writeVoid); resultPDFStream.Position = 0; resultPDFStream.CopyTo(resultPDFOutputStream); return(resultPDFOutputStream); }
/// <summary> /// Exports the blue cards /// </summary> /// <param name="classFile">File of classes</param> /// <param name="counselorFile">File of counselors</param> /// <param name="studentFile">File of students</param> /// <param name="studentEntryFile">File of student class entries</param> /// <param name="sortOrder">The sort order</param> /// <param name="writeVoid">Whether to separate the downloads by unit number</param> /// <returns>JSON to download the file through AJAX</returns> public async Task <IActionResult> OnPost(IFormFile classFile, IFormFile counselorFile, IFormFile studentFile, IFormFile studentEntryFile, int sortOrder, bool writeVoid) { if (sortOrder <= 0 || 5 <= sortOrder) { sortOrder = 1; } (Data, _) = await FileUtility.ImportFile(classFile, (int)FileTypeEnum.ClassFile); MeritBadgeClasses = Data.MeritBadgeClasses; (Data, _) = await FileUtility.ImportFile(counselorFile, (int)FileTypeEnum.CounselorFile); MeritBadgeCounselors = Data.MeritBadgeCounselors; (Data, _) = await FileUtility.ImportFile(studentFile, (int)FileTypeEnum.StudentFile); MeritBadgeStudents = Data.MeritBadgeStudents; (Data, _) = await FileUtility.ImportFile(studentEntryFile, (int)FileTypeEnum.StudentClassEntryFile); StudentClassEntries = Data.StudentClassEntries; if (MeritBadgeClasses == null || MeritBadgeCounselors == null || MeritBadgeStudents == null || StudentClassEntries == null) { return(NotFound("Error: One or more of the import files are invalid. Please validate the files before exporting.")); } if (sortOrder == 2) { MeritBadgeStudents = MeritBadgeStudents.OrderBy(s => s.FirstName).ToList(); } else if (sortOrder == 3) { MeritBadgeStudents = MeritBadgeStudents.OrderBy(s => s.LastName).ToList(); } else if (sortOrder == 4) { MeritBadgeStudents = MeritBadgeStudents.OrderBy(s => s.UnitNumber).ToList(); } Data = new MeritBadgeDataHelperModel { MeritBadgeClasses = MeritBadgeClasses, MeritBadgeCounselors = MeritBadgeCounselors, MeritBadgeStudents = MeritBadgeStudents, StudentClassEntries = StudentClassEntries, }; var byteArrays = new List <byte[]>(); foreach (var student in MeritBadgeStudents) { try { var mbcstudent = new MeritBadgeStudentViewModel(student, Data); if (mbcstudent.StudentClassEntries.Any()) { var numberOfPDFs = mbcstudent.StudentClassEntries.Count() / 3; numberOfPDFs += mbcstudent.StudentClassEntries.Count() % 3 != 0 ? 1 : 0; for (var i = 1; i <= numberOfPDFs; i++) { using var outputPDFStream = BlueCardUtility.GetBlueCards(mbcstudent, i, writeVoid); byteArrays.Add(outputPDFStream.ToArray()); } } } catch (Exception e) { return(NotFound($"Error: Unable to export blue cards for merit badge student with StudentId = {student.StudentId}. Error Message: {e.Message}")); } } var handle = Guid.NewGuid().ToString(); _cache.Set(handle, BlueCardUtility.ConcatenatePDFs(byteArrays), new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromMinutes(5))); var outputFileName = $"BlueCards_{DateTime.Now:yyyy-MM-dd}.pdf"; var result = new JsonResult(new { FileGuid = handle, FileName = outputFileName }); return(result); }
/// <summary> /// Utility method that fills out the blank blue card /// </summary> /// <param name="inputStream">The blank blue card</param> /// <param name="model">The merit badge student that contains the data</param> /// <param name="numberOfPDFs">The number of PDFs we are going to generate for the student</param> /// <param name="writeVoid">Whether VOID should be written on unused blue cards</param> /// <returns>A Stream containing the filled out PDF</returns> private static Stream FillForm(Stream inputStream, MeritBadgeStudentViewModel model, int numberOfPDFs, bool writeVoid) { Stream outStream = new MemoryStream(); PdfReader pdfReader = null; PdfStamper pdfStamper = null; try { pdfReader = new PdfReader(inputStream); pdfStamper = new PdfStamper(pdfReader, outStream); AcroFields form = pdfStamper.AcroFields; // Name BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.EMBEDDED); var studentName = model.FirstName + " " + model.LastName; form.SetField(BlueCardFields.StudentName, studentName); float fontSize = 250 / studentName.Length; if (fontSize > 12) { fontSize = 12; } if (fontSize < 5) { fontSize = 5; } form.SetFieldProperty(BlueCardFields.StudentName, "textsize", fontSize, null); form.SetFieldProperty(BlueCardFields.StudentName, "textfont", bf, null); form.RegenerateField(BlueCardFields.StudentName); form.SetField(BlueCardFields.Address, model.Address ?? ""); form.SetField(BlueCardFields.CityStateZip, string.Concat(model.City, " ", model.State, " ", model.ZipCode)); form.SetField(BlueCardFields.UnitTypeRB, model.UnitType); form.SetField(BlueCardFields.UnitType, model.UnitType); form.SetField(BlueCardFields.UnitNumber, model.UnitNumber.ToString()); form.SetField(BlueCardFields.District, model.District ?? ""); form.SetField(BlueCardFields.Council, model.Council ?? ""); var mbcclasses = model.StudentClassEntries.ToList(); for (var i = 1; i + 3 * (numberOfPDFs - 1) <= model.StudentClassEntries.Count() && i <= 3; i++) { var mbcclass = mbcclasses[i + 3 * (numberOfPDFs - 1) - 1]; var number = i.ToString(); if (i == 3) { number = ""; } form.SetField(BlueCardFields.MeritBadgeName + number, mbcclass.MeritBadgeClass.ClassName); form.SetFieldProperty(BlueCardFields.MeritBadgeName + number, "textfont", bf, null); form.RegenerateField(BlueCardFields.MeritBadgeName + number); form.SetField(BlueCardFields.DateApplied + number, ""); if (mbcclass.MeritBadgeClass.Counselor != null) { if (mbcclass.IsComplete && mbcclass.MeritBadgeClass.Counselor.DisplayName != null) { form.SetField(BlueCardFields.Counselor + number, mbcclass.MeritBadgeClass.Counselor.FirstName + " " + mbcclass.MeritBadgeClass.Counselor.LastName); } form.SetField(BlueCardFields.CounselorAddress + number, mbcclass.MeritBadgeClass.Counselor.Address); form.SetField(BlueCardFields.CounselorCityStateZip + number, $"{mbcclass.MeritBadgeClass.Counselor.City} {mbcclass.MeritBadgeClass.Counselor.State} {mbcclass.MeritBadgeClass.Counselor.ZipCode}"); form.SetField(BlueCardFields.CounselorPhone + number, mbcclass.MeritBadgeClass.Counselor.Telephone); } var requirementTitleList = mbcclass.RequirementList.Select(r => r.RequirementTitle).ToList(); var requirementList = mbcclass.RequirementList.ToList(); for (var j = 1; j <= requirementTitleList.Count; j++) { var appendString = number + "." + j.ToString("00"); form.SetField(BlueCardFields.Requirement + appendString, requirementTitleList[j - 1]); var fieldString = BlueCardFields.RequirementDate + appendString; var req = requirementList[j - 1]; form.SetField(fieldString, req.IsComplete ? req.CompletionDate.ToString("MM/dd/yyyy") : ""); form.SetFieldProperty(fieldString, "textsize", (float)6, null); form.RegenerateField(fieldString); var counselorInitials = string.Empty; if (mbcclass.MeritBadgeClass.Counselor != null) { counselorInitials = mbcclass.MeritBadgeClass.Counselor.FirstName.ElementAt(0).ToString().ToUpperInvariant() + mbcclass.MeritBadgeClass.Counselor.LastName.ElementAt(0).ToString().ToUpperInvariant(); } form.SetField(BlueCardFields.RequirementInitials + appendString, req.IsComplete ? counselorInitials : ""); } if (mbcclass.IsComplete) { form.SetField(BlueCardFields.DateCompleted + number, mbcclass.CompletionDate.ToString("MM/dd/yyyy")); } if (!string.IsNullOrWhiteSpace(mbcclass.Remarks)) { form.SetField(BlueCardFields.Remarks + number, mbcclass.Remarks); } } if (writeVoid && numberOfPDFs * 3 - mbcclasses.Count > 0) { form.SetField(BlueCardFields.BlueCardVoid1, "VOID"); if (numberOfPDFs * 3 - mbcclasses.Count > 1) { form.SetField(BlueCardFields.BlueCardVoid2, "VOID"); } } pdfStamper.FormFlattening = true; return(outStream); } finally { pdfStamper?.Close(); pdfReader?.Close(); } }