public FinancialStatementGeneratorUploadGivingStatementResult UploadGivingStatementDocument([FromBody] FinancialStatementGeneratorUploadGivingStatementData uploadGivingStatementData) { var rockContext = new RockContext(); var saveOptions = uploadGivingStatementData?.FinancialStatementIndividualSaveOptions; if (saveOptions == null) { throw new FinancialGivingStatementArgumentException("FinancialStatementIndividualSaveOptions must be specified"); } if (!saveOptions.SaveStatementsForIndividuals) { throw new FinancialGivingStatementArgumentException("FinancialStatementIndividualSaveOptions.SaveStatementsForIndividuals is not enabled."); } var documentTypeId = saveOptions.DocumentTypeId; if (!documentTypeId.HasValue) { throw new FinancialGivingStatementArgumentException("Document Type must be specified"); } var documentType = new DocumentTypeService(rockContext) .Queryable() .AsNoTracking() .Where(dt => dt.Id == documentTypeId.Value) .Select(a => new { BinaryFileTypeId = ( int? )a.BinaryFileTypeId }) .FirstOrDefault(); if (documentType == null) { throw new FinancialGivingStatementArgumentException("DocumentType must be specified"); } if (documentType.BinaryFileTypeId == null) { throw new FinancialGivingStatementArgumentException("DocumentType.BinaryFileType must be specified"); } var pdfData = uploadGivingStatementData.PDFData; string fileName = saveOptions.DocumentName + ".pdf"; var financialStatementGeneratorRecipient = uploadGivingStatementData.FinancialStatementGeneratorRecipient; if (financialStatementGeneratorRecipient == null) { throw new FinancialGivingStatementArgumentException("FinancialStatementGeneratorRecipient must be specified"); } var documentName = saveOptions.DocumentName; List <int> documentPersonIds; if (financialStatementGeneratorRecipient.PersonId.HasValue) { // If we are saving for a person that gives an individual, just give document to that person (ignore the FinancialStatementIndividualSaveOptionsSaveFor option) // only upload the document to the individual person documentPersonIds = new List <int>(); documentPersonIds.Add(financialStatementGeneratorRecipient.PersonId.Value); } else { var groupId = financialStatementGeneratorRecipient.GroupId; var givingFamilyMembersQuery = new GroupMemberService(rockContext).GetByGroupId(groupId, false); // limit to family members within the same giving group givingFamilyMembersQuery = givingFamilyMembersQuery.Where(a => a.Person.GivingGroupId.HasValue && a.Person.GivingGroupId == groupId); if (saveOptions.DocumentSaveFor == FinancialStatementGeneratorOptions.FinancialStatementIndividualSaveOptions.FinancialStatementIndividualSaveOptionsSaveFor.AllActiveAdultsInGivingGroup) { documentPersonIds = givingFamilyMembersQuery .Where(a => a.Person.AgeClassification == AgeClassification.Adult).Select(a => a.PersonId).ToList(); } else if (saveOptions.DocumentSaveFor == FinancialStatementGeneratorOptions.FinancialStatementIndividualSaveOptions.FinancialStatementIndividualSaveOptionsSaveFor.AllActiveFamilyMembersInGivingGroup) { documentPersonIds = givingFamilyMembersQuery .Select(a => a.PersonId).ToList(); } else if (saveOptions.DocumentSaveFor == FinancialStatementGeneratorOptions.FinancialStatementIndividualSaveOptions.FinancialStatementIndividualSaveOptionsSaveFor.PrimaryGiver) { // Set document for PrimaryGiver (aka Head of Household). // Note that HeadOfHouseHold would calculated based on family members within the same giving group var headOfHouseHoldPersonId = givingFamilyMembersQuery.GetHeadOfHousehold(s => ( int? )s.PersonId); documentPersonIds = new List <int>(); if (headOfHouseHoldPersonId.HasValue) { documentPersonIds.Add(headOfHouseHoldPersonId.Value); } } else { // shouldn't happen documentPersonIds = new List <int>(); } } var today = RockDateTime.Today; var tomorrow = today.AddDays(1); foreach (var documentPersonId in documentPersonIds) { // Create the document, linking the entity and binary file. if (saveOptions.OverwriteDocumentsOfThisTypeCreatedOnSameDate == true) { using (var deleteDocContext = new RockContext()) { var deleteDocumentService = new DocumentService(deleteDocContext); // See if there is an existing one. // Note include BinaryFile in the Get since we'll have to mark it temporary if it exists. var existingDocument = deleteDocumentService.Queryable().Where( a => a.DocumentTypeId == documentTypeId.Value && a.EntityId == documentPersonId && a.CreatedDateTime.HasValue && a.CreatedDateTime >= today && a.CreatedDateTime < tomorrow) .Include(a => a.BinaryFile).FirstOrDefault(); // NOTE: Delete vs update since we normally don't change the contents of documents/binary files once they've been created if (existingDocument != null) { deleteDocumentService.Delete(existingDocument); deleteDocContext.SaveChanges(); } } } // Create the binary file. var binaryFile = new BinaryFile { BinaryFileTypeId = documentType.BinaryFileTypeId, MimeType = "application/pdf", FileName = fileName, FileSize = pdfData.Length, IsTemporary = false, ContentStream = new MemoryStream(pdfData) }; new BinaryFileService(rockContext).Add(binaryFile); rockContext.SaveChanges(); Document document = new Document { DocumentTypeId = documentTypeId.Value, EntityId = documentPersonId, PurposeKey = saveOptions.DocumentPurposeKey, Name = saveOptions.DocumentName, Description = saveOptions.DocumentDescription }; document.SetBinaryFile(binaryFile.Id, rockContext); var documentService = new DocumentService(rockContext); documentService.Add(document); } rockContext.SaveChanges(); return(new FinancialStatementGeneratorUploadGivingStatementResult { NumberOfIndividuals = documentPersonIds.Count }); }