tender summary refactor

This commit is contained in:
Mazyar
2026-05-19 19:03:50 +03:30
parent 92d4b14b33
commit fcf2cae6bc
3 changed files with 41 additions and 25 deletions
+31 -15
View File
@@ -156,25 +156,41 @@ func languageInDone(done []string, language string) bool {
// TenderJSON represents the structure of the <notice_id>/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.
+2 -2
View File
@@ -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.
+8 -8
View File
@@ -278,13 +278,15 @@ func (s *StorageClient) resolveNoticeStoragePrefix(ctx context.Context, contract
// GetSummaryFromStorage fetches the
// PROC_<contractFolderID>/<noticePublicationID>/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,