91 lines
2.6 KiB
Go
91 lines
2.6 KiB
Go
package services
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/HoHD/PR-Helper/models"
|
|
)
|
|
|
|
// SaveNote upserts a review note (insert or update if exists for the same analysis_id + scope + scope_key).
|
|
func SaveNote(db *sql.DB, analysisID int64, scope, scopeKey, content string) (*models.ReviewNote, error) {
|
|
now := time.Now().UTC()
|
|
|
|
// Try to find existing note
|
|
var existingID int64
|
|
err := db.QueryRow(`SELECT id FROM review_notes WHERE analysis_id = ? AND scope = ? AND scope_key = ?`,
|
|
analysisID, scope, scopeKey).Scan(&existingID)
|
|
|
|
if err == sql.ErrNoRows {
|
|
// Insert new
|
|
result, err := db.Exec(`INSERT INTO review_notes (analysis_id, scope, scope_key, content, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
analysisID, scope, scopeKey, content, now, now)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("insert note: %w", err)
|
|
}
|
|
id, _ := result.LastInsertId()
|
|
return &models.ReviewNote{
|
|
ID: id,
|
|
AnalysisID: analysisID,
|
|
Scope: scope,
|
|
ScopeKey: scopeKey,
|
|
Content: content,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query existing note: %w", err)
|
|
}
|
|
|
|
// Update existing
|
|
_, err = db.Exec(`UPDATE review_notes SET content = ?, updated_at = ? WHERE id = ?`, content, now, existingID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("update note: %w", err)
|
|
}
|
|
|
|
return &models.ReviewNote{
|
|
ID: existingID,
|
|
AnalysisID: analysisID,
|
|
Scope: scope,
|
|
ScopeKey: scopeKey,
|
|
Content: content,
|
|
UpdatedAt: now,
|
|
}, nil
|
|
}
|
|
|
|
// GetNotes returns all review notes for a given analysis, optionally filtered by scope.
|
|
func GetNotes(db *sql.DB, analysisID int64, scope string) ([]models.ReviewNote, error) {
|
|
var rows *sql.Rows
|
|
var err error
|
|
|
|
if scope != "" {
|
|
rows, err = db.Query(`SELECT id, analysis_id, scope, scope_key, content, created_at, updated_at FROM review_notes WHERE analysis_id = ? AND scope = ? ORDER BY id`,
|
|
analysisID, scope)
|
|
} else {
|
|
rows, err = db.Query(`SELECT id, analysis_id, scope, scope_key, content, created_at, updated_at FROM review_notes WHERE analysis_id = ? ORDER BY id`,
|
|
analysisID)
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query notes: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var notes []models.ReviewNote
|
|
for rows.Next() {
|
|
var n models.ReviewNote
|
|
if err := rows.Scan(&n.ID, &n.AnalysisID, &n.Scope, &n.ScopeKey, &n.Content, &n.CreatedAt, &n.UpdatedAt); err != nil {
|
|
continue
|
|
}
|
|
notes = append(notes, n)
|
|
}
|
|
return notes, nil
|
|
}
|
|
|
|
// DeleteNote deletes a specific review note by ID.
|
|
func DeleteNote(db *sql.DB, noteID int64) error {
|
|
_, err := db.Exec(`DELETE FROM review_notes WHERE id = ?`, noteID)
|
|
return err
|
|
}
|