@ -480,6 +480,8 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
if types := r . Form [ "documentTypes" ] ; len ( types ) > 0 {
if types := r . Form [ "documentTypes" ] ; len ( types ) > 0 {
docTypes = types
docTypes = types
log . Printf ( "Filtering by document types: %v" , docTypes )
log . Printf ( "Filtering by document types: %v" , docTypes )
} else {
log . Printf ( "No document types specified, will process all document types" )
}
}
// Get filename patterns to match (optional)
// Get filename patterns to match (optional)
@ -582,21 +584,54 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
// Get attachments using the most reliable method first
// Get attachments using the most reliable method first
var attachments [ ] map [ string ] interface { }
var attachments [ ] map [ string ] interface { }
// Try the specialized GetJobAttachments method first
// Try the direct attachment endpoint first - this should return ALL attachment types
attachments , err = session . GetJobAttachments ( jobID )
directAttachments , err := session . GetJobAttachmentsDirect ( jobID )
if err != nil {
log . Printf ( "Error getting direct attachments for job %s: %v" , jobID , err )
attachments = [ ] map [ string ] interface { } { } // Ensure it's initialized
} else {
attachments = directAttachments
if len ( attachments ) > 0 {
log . Printf ( "Found %d attachments via GetJobAttachmentsDirect for job %s" , len ( attachments ) , jobID )
}
}
// If no attachments found via direct method, try the comprehensive GetAttachmentsForJob method
if len ( attachments ) == 0 {
jobData , err := session . GetAttachmentsForJob ( jobID )
if err != nil {
if err != nil {
log . Printf ( "Error getting attachments for job %s: %v" , jobID , err )
log . Printf ( "Error getting attachments for job %s: %v" , jobID , err )
attachments = [ ] map [ string ] interface { } { } // Ensure it's initialized
attachments = [ ] map [ string ] interface { } { } // Ensure it's initialized
} else {
// Extract attachments from the job data response
attachments = extractAttachmentsFromJobData ( jobData , jobID )
if len ( attachments ) > 0 {
log . Printf ( "Found %d attachments via GetAttachmentsForJob for job %s" , len ( attachments ) , jobID )
}
}
}
// If still no attachments found, try the specialized GetJobAttachments method as fallback
if len ( attachments ) == 0 {
attachments , err = session . GetJobAttachments ( jobID )
if err != nil {
log . Printf ( "Error getting attachments via GetJobAttachments for job %s: %v" , jobID , err )
attachments = [ ] map [ string ] interface { } { } // Ensure it's initialized
} else if len ( attachments ) > 0 {
log . Printf ( "Found %d attachments via GetJobAttachments for job %s" , len ( attachments ) , jobID )
}
}
}
// If no attachments found, try the paperwork endpoint as fallback
// If still no attachments found, try the paperwork endpoint as final fallback
if len ( attachments ) == 0 {
if len ( attachments ) == 0 {
log . Printf ( "No attachments found via GetJobAttachments for job %s, trying paperwork endpoint" , jobID )
paperworkItems , err := session . GetJobPaperwork ( jobID )
paperworkItems , err := session . GetJobPaperwork ( jobID )
if err != nil {
if err != nil {
log . Printf ( "Error getting paperwork for job %s: %v" , jobID , err )
log . Printf ( "Error getting paperwork for job %s: %v" , jobID , err )
} else {
} else {
attachments = paperworkItems
attachments = paperworkItems
if len ( attachments ) > 0 {
log . Printf ( "Found %d attachments via GetJobPaperwork for job %s" , len ( attachments ) , jobID )
}
}
}
}
}
@ -624,6 +659,15 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
filename = fmt . Sprintf ( "Attachment ID: %s" , attachmentIDStr )
filename = fmt . Sprintf ( "Attachment ID: %s" , attachmentIDStr )
}
}
// Get purposeId for debugging
var purposeId float64
if pid , ok := attachment [ "purposeId" ] . ( float64 ) ; ok {
purposeId = pid
}
// Track if this attachment should be included
includeAttachment := true
// Check document type filter
// Check document type filter
if len ( docTypes ) > 0 {
if len ( docTypes ) > 0 {
typeMatches := false
typeMatches := false
@ -639,17 +683,21 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
}
}
}
}
if ! typeMatches {
if ! typeMatches {
continue
log . Printf ( "Job %s: Skipping '%s' (type %v) - no document type match" , jobID , filename , purposeId )
includeAttachment = false
}
}
}
}
// Check filename pattern
// Check filename pattern filter
if len ( filenamePatterns ) > 0 && ! matchesAnyPattern ( filename , filenamePatterns ) {
if includeAttachment && len ( filenamePatterns ) > 0 {
continue
if ! matchesAnyPattern ( filename , filenamePatterns ) {
log . Printf ( "Job %s: Skipping '%s' - no filename pattern match" , jobID , filename )
includeAttachment = false
}
}
}
// Check age filter if applicable
// Check age filter if applicable
if ageFilterDays > 0 {
if includeAttachment && ageFilterDays > 0 {
var createdAt time . Time
var createdAt time . Time
var hasDate bool
var hasDate bool
@ -670,13 +718,19 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
}
}
if hasDate && createdAt . After ( cutoffDate ) {
if hasDate && createdAt . After ( cutoffDate ) {
continue // Skip if not old enough
log . Printf ( "Job %s: Skipping '%s' - not old enough (%s)" , jobID , filename , createdAt . Format ( "2006-01-02" ) )
includeAttachment = false
}
}
}
}
// This attachment matches all criteria
// Add attachment if it passed all filters
if includeAttachment {
log . Printf ( "Job %s: Including '%s' (type %v) for deletion" , jobID , filename , purposeId )
attachmentsToDelete = append ( attachmentsToDelete , attachment )
attachmentsToDelete = append ( attachmentsToDelete , attachment )
}
}
}
log . Printf ( "Job %s: Found %d attachments to delete out of %d total attachments" , jobID , len ( attachmentsToDelete ) , len ( attachments ) )
jobResult . FilesFound = len ( attachmentsToDelete )
jobResult . FilesFound = len ( attachmentsToDelete )
@ -737,6 +791,8 @@ func BulkRemoveDocumentsHandler(w http.ResponseWriter, r *http.Request) {
deletionWg . Wait ( )
deletionWg . Wait ( )
log . Printf ( "Job %s: Deletion completed. Files found: %d, Files removed: %d, Success: %v" , jobID , jobResult . FilesFound , jobResult . FilesRemoved , jobResult . Success )
mu . Lock ( )
mu . Lock ( )
results . JobsProcessed ++
results . JobsProcessed ++
if jobResult . Success {
if jobResult . Success {
@ -1008,3 +1064,81 @@ func RemovalJobFileHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
}
}
// Helper function to extract attachments from job data response
func extractAttachmentsFromJobData ( jobData map [ string ] interface { } , jobID string ) [ ] map [ string ] interface { } {
attachments := make ( [ ] map [ string ] interface { } , 0 )
// Check if data key exists
if data , ok := jobData [ "data" ] . ( map [ string ] interface { } ) ; ok {
// Look for attachments directly in data
if attList , ok := data [ "attachments" ] . ( [ ] interface { } ) ; ok && len ( attList ) > 0 {
for _ , att := range attList {
if attachment , ok := att . ( map [ string ] interface { } ) ; ok {
attachments = append ( attachments , attachment )
}
}
return attachments
}
// Check for paperwork in data
if paperwork , ok := data [ "paperwork" ] . ( [ ] interface { } ) ; ok && len ( paperwork ) > 0 {
for _ , doc := range paperwork {
if docMap , ok := doc . ( map [ string ] interface { } ) ; ok {
attachments = append ( attachments , docMap )
}
}
return attachments
}
// Check for paperwork_objects (from fallback paperwork endpoint)
if paperworkObjects , ok := data [ "paperwork_objects" ] . ( [ ] interface { } ) ; ok && len ( paperworkObjects ) > 0 {
for _ , obj := range paperworkObjects {
if objMap , ok := obj . ( map [ string ] interface { } ) ; ok {
attachments = append ( attachments , objMap )
}
}
return attachments
}
// Check for other potential containers
for _ , key := range [ ] string { "objects" , "components" , "items" , "records" } {
if items , ok := data [ key ] . ( [ ] interface { } ) ; ok && len ( items ) > 0 {
for _ , item := range items {
if itemMap , ok := item . ( map [ string ] interface { } ) ; ok {
attachments = append ( attachments , itemMap )
}
}
return attachments
}
}
}
// Check for objects at root level
if objects , ok := jobData [ "objects" ] . ( [ ] interface { } ) ; ok && len ( objects ) > 0 {
for _ , obj := range objects {
if objMap , ok := obj . ( map [ string ] interface { } ) ; ok {
attachments = append ( attachments , objMap )
}
}
return attachments
}
return attachments
}
// Helper function to get map keys
func getMapKeys ( m interface { } ) [ ] string {
keys := make ( [ ] string , 0 )
switch m := m . ( type ) {
case map [ string ] interface { } :
for k := range m {
keys = append ( keys , k )
}
case map [ string ] string :
for k := range m {
keys = append ( keys , k )
}
}
return keys
}