List and download tender documents - worker auto translation to english job
This commit is contained in:
@@ -30,6 +30,15 @@ type DocumentSummary struct {
|
||||
Error string `json:"error"` // empty string when no error
|
||||
}
|
||||
|
||||
// StoredDocument represents a document object stored for a tender in MinIO.
|
||||
type StoredDocument struct {
|
||||
ObjectName string `json:"-"`
|
||||
DocumentName string `json:"document_name"`
|
||||
Size int64 `json:"size"`
|
||||
LastModified int64 `json:"last_modified"`
|
||||
DocumentType string `json:"document_type,omitempty"`
|
||||
}
|
||||
|
||||
// TranslateRequest represents the request payload sent to the AI service
|
||||
// POST /ai/translate endpoint.
|
||||
type TranslateRequest struct {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio-go/v7"
|
||||
@@ -153,6 +154,89 @@ func (s *StorageClient) IsSummaryReady(ctx context.Context, noticeID string) (bo
|
||||
return tenderJSON.SummarizeStatus.Done, nil
|
||||
}
|
||||
|
||||
// ListDocuments lists document files stored under <noticeID>/.
|
||||
func (s *StorageClient) ListDocuments(ctx context.Context, noticeID string) ([]StoredDocument, error) {
|
||||
noticeID = strings.TrimSpace(noticeID)
|
||||
if noticeID == "" {
|
||||
return nil, fmt.Errorf("ai_summarizer: noticeID is required")
|
||||
}
|
||||
|
||||
prefix := fmt.Sprintf("%s/", noticeID)
|
||||
objectCh := s.client.ListObjects(ctx, s.config.MinioBucket, minio.ListObjectsOptions{
|
||||
Prefix: prefix,
|
||||
Recursive: true,
|
||||
})
|
||||
|
||||
documents := make([]StoredDocument, 0)
|
||||
for object := range objectCh {
|
||||
if object.Err != nil {
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to list documents for notice %s: %w", noticeID, object.Err)
|
||||
}
|
||||
if !isTenderDocumentObject(noticeID, object.Key) {
|
||||
continue
|
||||
}
|
||||
|
||||
documentName := filepath.Base(object.Key)
|
||||
documents = append(documents, StoredDocument{
|
||||
ObjectName: object.Key,
|
||||
DocumentName: documentName,
|
||||
Size: object.Size,
|
||||
LastModified: object.LastModified.Unix(),
|
||||
DocumentType: documentType(documentName),
|
||||
})
|
||||
}
|
||||
|
||||
s.logger.Info("Listed tender documents from storage", map[string]interface{}{
|
||||
"notice_id": noticeID,
|
||||
"documents_count": len(documents),
|
||||
})
|
||||
|
||||
return documents, nil
|
||||
}
|
||||
|
||||
func isTenderDocumentObject(noticeID, objectName string) bool {
|
||||
if objectName == "" || strings.HasSuffix(objectName, "/") {
|
||||
return false
|
||||
}
|
||||
|
||||
relativePath := strings.TrimPrefix(objectName, fmt.Sprintf("%s/", noticeID))
|
||||
if relativePath == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
filename := strings.ToLower(filepath.Base(relativePath))
|
||||
switch filename {
|
||||
case "tender.json", "ai_cache.db":
|
||||
return false
|
||||
}
|
||||
|
||||
switch strings.ToLower(filepath.Ext(filename)) {
|
||||
case ".json", ".db", ".sqlite", ".sqlite3":
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// DownloadDocument opens a document object from the configured MinIO bucket.
|
||||
func (s *StorageClient) DownloadDocument(ctx context.Context, objectName string) (io.ReadCloser, error) {
|
||||
objectName = strings.TrimSpace(objectName)
|
||||
if objectName == "" {
|
||||
return nil, fmt.Errorf("ai_summarizer: objectName is required")
|
||||
}
|
||||
|
||||
object, err := s.client.GetObject(ctx, s.config.MinioBucket, objectName, minio.GetObjectOptions{})
|
||||
if err != nil {
|
||||
var minioErr minio.ErrorResponse
|
||||
if errors.As(err, &minioErr) && minioErr.StatusCode == http.StatusNotFound {
|
||||
return nil, ErrObjectNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("ai_summarizer: failed to get document object: %w", err)
|
||||
}
|
||||
|
||||
return object, nil
|
||||
}
|
||||
|
||||
// GetAllSummaries lists all tender.json files in the MinIO bucket and returns
|
||||
// the overall_summary for each tender where summarize_status.done is true.
|
||||
// This is useful for batch-retrieving all summaries that the AI pipeline has
|
||||
@@ -233,3 +317,11 @@ func countDone(items []TenderSummaryItem) int {
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func documentType(filename string) string {
|
||||
extension := strings.TrimPrefix(strings.ToLower(filepath.Ext(filename)), ".")
|
||||
if extension == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return extension
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user