diff --git a/pkg/ai_summarizer/entities.go b/pkg/ai_summarizer/entities.go index d85dac0..1ee3212 100644 --- a/pkg/ai_summarizer/entities.go +++ b/pkg/ai_summarizer/entities.go @@ -156,25 +156,41 @@ func languageInDone(done []string, language string) bool { // TenderJSON represents the structure of the /tender.json file // stored in the AI service's MinIO bucket. type TenderJSON struct { - OverallSummary *string `json:"overall_summary"` - OverallSummaryCamel *string `json:"overallSummary"` - SummarizeStatus SummarizeStatus `json:"summarize_status"` - SummarizeStatusCamel SummarizeStatus `json:"summarizeStatus"` + // Summary is the current pipeline field for the tender-level summary text. + Summary string `json:"summary"` + OverallSummary *string `json:"overall_summary"` + OverallSummaryCamel *string `json:"overallSummary"` + SummarizeStatus SummarizeStatus `json:"summarize_status"` + SummarizeStatusCamel SummarizeStatus `json:"summarizeStatus"` Translations map[string]StoredTranslation `json:"translations"` - TranslationStatus TranslationStatus `json:"translation_status"` - TranslationStatusCamel TranslationStatus `json:"translationStatus"` + TranslationStatus TranslationStatus `json:"translation_status"` + TranslationStatusCamel TranslationStatus `json:"translationStatus"` } -// resolved returns whether summarization is marked done and the best-effort -// overall summary pointer (may be nil or empty when the pipeline finished -// without text yet). -func (t *TenderJSON) resolved() (done bool, overall *string) { - done = t.SummarizeStatus.isDone() || t.SummarizeStatusCamel.isDone() - overall = t.OverallSummary - if overall == nil || strings.TrimSpace(*overall) == "" { - overall = t.OverallSummaryCamel +// summaryText returns the best-effort tender-level summary (may be empty). +func (t *TenderJSON) summaryText() string { + if t == nil { + return "" } - return done, overall + for _, candidate := range []*string{t.OverallSummary, t.OverallSummaryCamel} { + if candidate == nil { + continue + } + if text := strings.TrimSpace(*candidate); text != "" { + return text + } + } + return strings.TrimSpace(t.Summary) +} + +// resolved returns whether summarization is marked done and the summary text +// (may be empty when the pipeline finished without text yet). +func (t *TenderJSON) resolved() (done bool, overall string) { + if t == nil { + return false, "" + } + done = t.SummarizeStatus.isDone() || t.SummarizeStatusCamel.isDone() + return done, t.summaryText() } // SummarizeStatus represents the summarization status inside tender.json. diff --git a/pkg/ai_summarizer/errors.go b/pkg/ai_summarizer/errors.go index 932b10f..4b42cb7 100644 --- a/pkg/ai_summarizer/errors.go +++ b/pkg/ai_summarizer/errors.go @@ -9,8 +9,8 @@ var ( ErrSummaryNotReady = errors.New("ai_summarizer: summary not ready yet") // ErrNoOverallSummary is returned when the pipeline is done but - // overall_summary is empty or null. - ErrNoOverallSummary = errors.New("ai_summarizer: overall_summary is empty") + // summary / overall_summary text is empty. + ErrNoOverallSummary = errors.New("ai_summarizer: tender summary is empty") // ErrTranslationNotReady is returned when tender.json exists but the // requested language is not listed in translation_status.done yet. diff --git a/pkg/ai_summarizer/storage.go b/pkg/ai_summarizer/storage.go index 1d3e7c7..38f2ffc 100644 --- a/pkg/ai_summarizer/storage.go +++ b/pkg/ai_summarizer/storage.go @@ -278,13 +278,15 @@ func (s *StorageClient) resolveNoticeStoragePrefix(ctx context.Context, contract // GetSummaryFromStorage fetches the // PROC_//tender.json file from the AI -// service's MinIO bucket, parses it, and returns the overall_summary string. +// service's MinIO bucket, parses it, and returns the tender summary text. +// +// Summary text is read from summary (current) or overall_summary (legacy). // // It returns: // - (summary, nil) on success // - ("", ErrObjectNotFound) if the tender.json does not exist (404) // - ("", ErrSummaryNotReady) if the file exists but summarize_status.done is false -// - ("", ErrNoOverallSummary) if done is true but overall_summary is empty/null +// - ("", ErrNoOverallSummary) if done is true but summary text is empty // - ("", error) for any other failure func (s *StorageClient) GetSummaryFromStorage(ctx context.Context, contractFolderID, noticePublicationID string) (string, error) { if strings.TrimSpace(contractFolderID) == "" { @@ -352,7 +354,7 @@ func (s *StorageClient) getTranslationFromObjectKey(ctx context.Context, objectK return entry, nil } -// getSummaryFromObjectKey reads tender.json at objectKey and returns overall_summary when ready. +// getSummaryFromObjectKey reads tender.json at objectKey and returns summary text when ready. // contractFolderID and noticePublicationID are used for logging only (may be empty when unknown). func (s *StorageClient) readTenderJSONAtKey(ctx context.Context, objectKey string) (*TenderJSON, error) { object, err := s.client.GetObject(ctx, s.config.MinioBucket, objectKey, minio.GetObjectOptions{}) @@ -403,17 +405,15 @@ func (s *StorageClient) getSummaryFromObjectKey(ctx context.Context, objectKey, return "", err } - done, overall := tenderJSON.resolved() + done, summaryText := tenderJSON.resolved() if !done { return "", ErrSummaryNotReady } - if overall == nil || strings.TrimSpace(*overall) == "" { + if summaryText == "" { return "", ErrNoOverallSummary } - summaryText := strings.TrimSpace(*overall) - - s.logger.Info("Retrieved overall_summary from storage", map[string]interface{}{ + s.logger.Info("Retrieved tender summary from storage", map[string]interface{}{ "contract_folder_id": contractFolderID, "notice_id": noticePublicationID, "object_key": objectKey,