Move Ticket Name to the Participant model.
This commit is contained in:
parent
cc4dd76438
commit
2ff06bdb76
5 changed files with 20 additions and 18 deletions
14
db.go
14
db.go
|
|
@ -201,6 +201,7 @@ func migrateV2(db *sql.DB) error {
|
||||||
// and links volunteers to participants via participant_id.
|
// and links volunteers to participants via participant_id.
|
||||||
func migrateV3(db *sql.DB) error {
|
func migrateV3(db *sql.DB) error {
|
||||||
addColumnIfMissing(db, "volunteers", "participant_id INTEGER REFERENCES participants(id)")
|
addColumnIfMissing(db, "volunteers", "participant_id INTEGER REFERENCES participants(id)")
|
||||||
|
addColumnIfMissing(db, "participants", "ticket_name TEXT NOT NULL DEFAULT ''")
|
||||||
|
|
||||||
// Seed participants from volunteers first (better name data: preferred_name).
|
// Seed participants from volunteers first (better name data: preferred_name).
|
||||||
db.Exec(`
|
db.Exec(`
|
||||||
|
|
@ -424,6 +425,7 @@ type Participant struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
PreferredName string `json:"preferred_name"`
|
PreferredName string `json:"preferred_name"`
|
||||||
|
TicketName string `json:"ticket_name"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Pronouns string `json:"pronouns"`
|
Pronouns string `json:"pronouns"`
|
||||||
Note string `json:"note"`
|
Note string `json:"note"`
|
||||||
|
|
@ -860,7 +862,7 @@ func (app *App) attendeeCounts() (total, checkedIn int, err error) {
|
||||||
|
|
||||||
// --- Participants ---
|
// --- Participants ---
|
||||||
|
|
||||||
const participantCols = `id, email, preferred_name, phone, pronouns, note, created_at, updated_at, deleted_at`
|
const participantCols = `id, email, preferred_name, ticket_name, phone, pronouns, note, created_at, updated_at, deleted_at`
|
||||||
|
|
||||||
func (app *App) listParticipants(search, since string) ([]Participant, error) {
|
func (app *App) listParticipants(search, since string) ([]Participant, error) {
|
||||||
var q string
|
var q string
|
||||||
|
|
@ -900,8 +902,8 @@ func (app *App) getParticipantByEmail(email string) (*Participant, error) {
|
||||||
|
|
||||||
func (app *App) createParticipant(p Participant) (*Participant, error) {
|
func (app *App) createParticipant(p Participant) (*Participant, error) {
|
||||||
res, err := app.db.Exec(
|
res, err := app.db.Exec(
|
||||||
`INSERT INTO participants (email, preferred_name, phone, pronouns, note, updated_at) VALUES (?, ?, ?, ?, ?, ?)`,
|
`INSERT INTO participants (email, preferred_name, ticket_name, phone, pronouns, note, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||||
strings.ToLower(p.Email), p.PreferredName, p.Phone, p.Pronouns, p.Note, now(),
|
strings.ToLower(p.Email), p.PreferredName, p.TicketName, p.Phone, p.Pronouns, p.Note, now(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -912,9 +914,9 @@ func (app *App) createParticipant(p Participant) (*Participant, error) {
|
||||||
|
|
||||||
func (app *App) updateParticipant(p Participant) error {
|
func (app *App) updateParticipant(p Participant) error {
|
||||||
_, err := app.db.Exec(
|
_, err := app.db.Exec(
|
||||||
`UPDATE participants SET email=?, preferred_name=?, phone=?, pronouns=?, note=?, updated_at=?
|
`UPDATE participants SET email=?, preferred_name=?, ticket_name=?, phone=?, pronouns=?, note=?, updated_at=?
|
||||||
WHERE id=? AND deleted_at IS NULL`,
|
WHERE id=? AND deleted_at IS NULL`,
|
||||||
strings.ToLower(p.Email), p.PreferredName, p.Phone, p.Pronouns, p.Note, now(), p.ID,
|
strings.ToLower(p.Email), p.PreferredName, p.TicketName, p.Phone, p.Pronouns, p.Note, now(), p.ID,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -957,7 +959,7 @@ func queryParticipants(db *sql.DB, q string, args ...any) ([]Participant, error)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var p Participant
|
var p Participant
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&p.ID, &p.Email, &p.PreferredName, &p.Phone, &p.Pronouns, &p.Note,
|
&p.ID, &p.Email, &p.PreferredName, &p.TicketName, &p.Phone, &p.Pronouns, &p.Note,
|
||||||
&p.CreatedAt, &p.UpdatedAt, &p.DeletedAt,
|
&p.CreatedAt, &p.UpdatedAt, &p.DeletedAt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
return ($allTickets ?? []).filter(t => t.participant_id === participantId)
|
return ($allTickets ?? []).filter(t => t.participant_id === participantId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function checkedInCount(participantId) {
|
function checkedInCount(participantId) {
|
||||||
return ticketsFor(participantId).filter(t => t.checked_in_at).length
|
return ticketsFor(participantId).filter(t => t.checked_in_at).length
|
||||||
}
|
}
|
||||||
|
|
@ -367,6 +368,9 @@
|
||||||
{#if p.pronouns}
|
{#if p.pronouns}
|
||||||
<span class="text-muted" style="font-size:0.78rem"> · {p.pronouns}</span>
|
<span class="text-muted" style="font-size:0.78rem"> · {p.pronouns}</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if p.ticket_name && p.ticket_name !== p.preferred_name}
|
||||||
|
<div class="text-muted" style="font-size:0.78rem">Ticket: {p.ticket_name}</div>
|
||||||
|
{/if}
|
||||||
{#if p.note}
|
{#if p.note}
|
||||||
<div class="text-muted" style="font-size:0.78rem">{p.note}</div>
|
<div class="text-muted" style="font-size:0.78rem">{p.note}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -299,9 +299,6 @@
|
||||||
{:else if !participantHasTickets(v.participant_id)}
|
{:else if !participantHasTickets(v.participant_id)}
|
||||||
<span class="badge badge-partial" style="margin-left:0.4rem" title="No ticket on file">No ticket</span>
|
<span class="badge badge-partial" style="margin-left:0.4rem" title="No ticket on file">No ticket</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if v.ticket_name && v.ticket_name !== v.name}
|
|
||||||
<div class="text-muted" style="font-size:0.78rem">Ticket: {v.ticket_name}</div>
|
|
||||||
{/if}
|
|
||||||
{#if v.email}
|
{#if v.email}
|
||||||
<div class="text-muted" style="font-size:0.78rem">{v.email}</div>
|
<div class="text-muted" style="font-size:0.78rem">{v.email}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,13 @@ func (app *App) handlePublicSignup(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Update participant's personal details if they signed up with more info.
|
// Update participant's personal details if they signed up with more info.
|
||||||
if body.Phone != "" || body.Pronouns != "" {
|
if body.Phone != "" || body.Pronouns != "" || body.TicketName != "" {
|
||||||
app.db.Exec(`UPDATE participants SET
|
app.db.Exec(`UPDATE participants SET
|
||||||
phone = CASE WHEN phone = '' THEN ? ELSE phone END,
|
phone = CASE WHEN phone = '' THEN ? ELSE phone END,
|
||||||
pronouns = CASE WHEN pronouns = '' THEN ? ELSE pronouns END,
|
pronouns = CASE WHEN pronouns = '' THEN ? ELSE pronouns END,
|
||||||
|
ticket_name = CASE WHEN ticket_name = '' THEN ? ELSE ticket_name END,
|
||||||
updated_at = ?
|
updated_at = ?
|
||||||
WHERE id = ?`, body.Phone, body.Pronouns, now(), participant.ID)
|
WHERE id = ?`, body.Phone, body.Pronouns, body.TicketName, now(), participant.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmToken, err := generateConfirmationToken()
|
confirmToken, err := generateConfirmationToken()
|
||||||
|
|
@ -93,7 +94,6 @@ func (app *App) handlePublicSignup(w http.ResponseWriter, r *http.Request) {
|
||||||
ParticipantID: &participant.ID,
|
ParticipantID: &participant.ID,
|
||||||
Name: body.PreferredName,
|
Name: body.PreferredName,
|
||||||
PreferredName: body.PreferredName,
|
PreferredName: body.PreferredName,
|
||||||
TicketName: body.TicketName,
|
|
||||||
Email: body.Email,
|
Email: body.Email,
|
||||||
Phone: body.Phone,
|
Phone: body.Phone,
|
||||||
Pronouns: body.Pronouns,
|
Pronouns: body.Pronouns,
|
||||||
|
|
|
||||||
|
|
@ -337,8 +337,8 @@ func TestPublicSignupTicketNameDoesNotOverwritePreferredName(t *testing.T) {
|
||||||
if p.PreferredName != "Titania" {
|
if p.PreferredName != "Titania" {
|
||||||
t.Errorf("participant preferred_name = %q, want %q (not ticket_name)", p.PreferredName, "Titania")
|
t.Errorf("participant preferred_name = %q, want %q (not ticket_name)", p.PreferredName, "Titania")
|
||||||
}
|
}
|
||||||
if vol.TicketName != "Titania Fairweather" {
|
if p.TicketName != "Titania Fairweather" {
|
||||||
t.Errorf("vol.TicketName = %q, want %q", vol.TicketName, "Titania Fairweather")
|
t.Errorf("participant.TicketName = %q, want %q", p.TicketName, "Titania Fairweather")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,12 +349,11 @@ func TestConfirmEmailAssignsKioskCode(t *testing.T) {
|
||||||
app.db.Exec(`INSERT OR REPLACE INTO config (key, value) VALUES ('shift_signups_open', 'true')`)
|
app.db.Exec(`INSERT OR REPLACE INTO config (key, value) VALUES ('shift_signups_open', 'true')`)
|
||||||
app.baseURL = "https://example.com"
|
app.baseURL = "https://example.com"
|
||||||
|
|
||||||
participant, _ := app.createParticipant(Participant{PreferredName: "Titania", Email: "titania@example.com"})
|
participant, _ := app.createParticipant(Participant{PreferredName: "Titania", TicketName: "Titania Fairweather", Email: "titania@example.com"})
|
||||||
token := "abc123def456"
|
token := "abc123def456"
|
||||||
app.createVolunteer(Volunteer{
|
app.createVolunteer(Volunteer{
|
||||||
Name: "Titania",
|
Name: "Titania",
|
||||||
PreferredName: "Titania",
|
PreferredName: "Titania",
|
||||||
TicketName: "Titania Fairweather",
|
|
||||||
Email: "titania@example.com",
|
Email: "titania@example.com",
|
||||||
ParticipantID: &participant.ID,
|
ParticipantID: &participant.ID,
|
||||||
ConfirmationToken: &token,
|
ConfirmationToken: &token,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue