summaries.go
| 1 | package store |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "database/sql" |
| 6 | "time" |
| 7 | ) |
| 8 | |
| 9 | // Summary ist eine Zusammenfassung zum Mitgeben: Kind "gesamt" oder "sitzung". |
| 10 | type Summary struct { |
| 11 | ID, PatientID int64 |
| 12 | SessionID int64 // 0 = keine |
| 13 | Kind, Date, Title, Body string |
| 14 | Created, Updated time.Time |
| 15 | } |
| 16 | |
| 17 | const summaryCols = `id, patient_id, session_id, kind, date, title, body, created_at, updated_at` |
| 18 | |
| 19 | func 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 | |
| 28 | func (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 | |
| 45 | func (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 | |
| 50 | func (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 | |
| 64 | func (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 | |
| 76 | func (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 | |
| 82 | func (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. |
| 90 | type MailLog struct { |
| 91 | Recipient, Subject, Error string |
| 92 | OK bool |
| 93 | Sent time.Time |
| 94 | } |
| 95 | |
| 96 | func (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 | |
| 102 | func (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 |