package store import ( "context" "database/sql" "errors" "fmt" "time" "g.fc.run/ai/byre/internal/api" ) func (s *Store) LeadNotes(ctx context.Context, owner string) ([]api.LeadNote, error) { rows, err := s.db.QueryContext(ctx, `SELECT id, text, project_id, created_at, updated_at FROM lead_notes WHERE owner = ? ORDER BY created_at, id`, owner) if err != nil { return nil, err } defer rows.Close() notes := []api.LeadNote{} for rows.Next() { n := api.LeadNote{} projectID := "" createdAt := "" updatedAt := "" err = rows.Scan(&n.Id, &n.Text, &projectID, &createdAt, &updatedAt) if err != nil { return nil, err } if projectID != "" { n.ProjectId = &projectID } n.CreatedAt, err = parseTime(createdAt) if err != nil { return nil, err } n.UpdatedAt, err = parseTime(updatedAt) if err != nil { return nil, err } notes = append(notes, n) } return notes, rows.Err() } func (s *Store) SaveLeadNote(ctx context.Context, owner, id, projectID, text, actor string) (api.LeadNote, error) { at := time.Now().UTC() n := api.LeadNote{Id: id, Text: text, CreatedAt: at, UpdatedAt: at} if projectID != "" { n.ProjectId = &projectID } err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { if id == "" { n.Id = NewID() _, err := tx.ExecContext(ctx, `INSERT INTO lead_notes (id, owner, text, project_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)`, n.Id, owner, text, projectID, formatTime(at), formatTime(at)) if err != nil { return err } } else { createdAt := "" err := tx.QueryRowContext(ctx, `UPDATE lead_notes SET text = ?, project_id = ?, updated_at = ? WHERE id = ? AND owner = ? RETURNING created_at`, text, projectID, formatTime(at), id, owner).Scan(&createdAt) if errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("note %s: %w", id, ErrNotFound) } if err != nil { return err } n.CreatedAt, err = parseTime(createdAt) if err != nil { return err } } return emit(api.Event{Kind: "lead.note_saved", Owner: &owner, Actor: actor, Payload: ToPayload(n)}) }) return n, err } func (s *Store) DeleteLeadNote(ctx context.Context, owner, id, actor string) (string, error) { text := "" err := s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { err := tx.QueryRowContext(ctx, `DELETE FROM lead_notes WHERE id = ? AND owner = ? RETURNING text`, id, owner).Scan(&text) if errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("note %s: %w", id, ErrNotFound) } if err != nil { return err } return emit(api.Event{Kind: "lead.note_deleted", Owner: &owner, Actor: actor, Payload: map[string]any{"id": id, "text": text}}) }) return text, err }