summaries.go
⎇
Raw
1package store
2
3import (
4 "context"
5 "database/sql"
6 "time"
7)
8
9// Summary ist eine Zusammenfassung zum Mitgeben: Kind "gesamt" oder "sitzung".
10type Summary struct {
11 ID, PatientID int64
12 SessionID int64 // 0 = keine
13 Kind, Date, Title, Body string
14 Created, Updated time.Time
15}
16
17const summaryCols = `id, patient_id, session_id, kind, date, title, body, created_at, updated_at`
18
19func scanSummary(sc scanner) (Summary, error) {
20 var x Summary
21 var sid sql.NullInt64
22 var c, u int64
23 err := sc.Scan(&x.ID, &x.PatientID, &sid, &x.Kind, &x.Date, &x.Title, &x.Body, &c, &u)
24 x.SessionID, x.Created, x.Updated = sid.Int64, time.Unix(c, 0), time.Unix(u, 0)
25 return x, err
26}
27
28func (s *Store) Summaries(ctx context.Context, pid int64) ([]Summary, error) {
29 rows, err := s.db.QueryContext(ctx, `SELECT `+summaryCols+` FROM summaries WHERE patient_id = ? ORDER BY date DESC, id DESC`, pid)
30 if err != nil {
31 return nil, err
32 }
33 defer rows.Close()
34 var out []Summary
35 for rows.Next() {
36 x, err := scanSummary(rows)
37 if err != nil {
38 return nil, err
39 }
40 out = append(out, x)
41 }
42 return out, rows.Err()
43}
44
45func (s *Store) Summary(ctx context.Context, id int64) (Summary, error) {
46 x, err := scanSummary(s.db.QueryRowContext(ctx, `SELECT `+summaryCols+` FROM summaries WHERE id = ?`, id))
47 return x, notFound(err)
48}
49
50func (s *Store) CreateSummary(ctx context.Context, x Summary) (int64, error) {
51 var sid any
52 if x.SessionID > 0 {
53 sid = x.SessionID
54 }
55 res, err := s.db.ExecContext(ctx, `INSERT INTO summaries (patient_id, session_id, kind, date, title, body) VALUES (?, ?, ?, ?, ?, ?)`,
56 x.PatientID, sid, x.Kind, x.Date, x.Title, x.Body)
57 if err != nil {
58 return 0, err
59 }
60 s.touchPatient(ctx, x.PatientID)
61 return res.LastInsertId()
62}
63
64func (s *Store) UpdateSummary(ctx context.Context, x Summary) error {
65 res, err := s.db.ExecContext(ctx, `UPDATE summaries SET date=?, title=?, body=?, updated_at=unixepoch() WHERE id=?`,
66 x.Date, x.Title, x.Body, x.ID)
67 if err != nil {
68 return err
69 }
70 if n, _ := res.RowsAffected(); n == 0 {
71 return ErrNotFound
72 }
73 return nil
74}
75
76func (s *Store) DeleteSummary(ctx context.Context, id int64) (int64, error) {
77 var pid int64
78 err := s.db.QueryRowContext(ctx, `DELETE FROM summaries WHERE id = ? RETURNING patient_id`, id).Scan(&pid)
79 return pid, notFound(err)
80}
81
82func (s *Store) Session(ctx context.Context, id int64) (Session, error) {
83 var x Session
84 err := s.db.QueryRowContext(ctx, `SELECT id, patient_id, date, goal, note FROM sessions WHERE id = ?`, id).
85 Scan(&x.ID, &x.PatientID, &x.Date, &x.Goal, &x.Note)
86 return x, notFound(err)
87}
88
89// MailLog ist ein Eintrag im Versandprotokoll.
90type MailLog struct {
91 Recipient, Subject, Error string
92 OK bool
93 Sent time.Time
94}
95
96func (s *Store) LogMail(ctx context.Context, summaryID, patientID int64, l MailLog) error {
97 _, err := s.db.ExecContext(ctx, `INSERT INTO mail_log (summary_id, patient_id, recipient, subject, ok, error) VALUES (?, ?, ?, ?, ?, ?)`,
98 summaryID, patientID, l.Recipient, l.Subject, l.OK, l.Error)
99 return err
100}
101
102func (s *Store) MailLogFor(ctx context.Context, summaryID int64) ([]MailLog, error) {
103 rows, err := s.db.QueryContext(ctx, `SELECT recipient, subject, ok, error, sent_at FROM mail_log WHERE summary_id = ? ORDER BY id DESC`, summaryID)
104 if err != nil {
105 return nil, err
106 }
107 defer rows.Close()
108 var out []MailLog
109 for rows.Next() {
110 var l MailLog
111 var t int64
112 if err := rows.Scan(&l.Recipient, &l.Subject, &l.OK, &l.Error, &t); err != nil {
113 return nil, err
114 }
115 l.Sent = time.Unix(t, 0)
116 out = append(out, l)
117 }
118 return out, rows.Err()
119}
120