Established Participants and Tickets model. Migrated concepts.
This commit is contained in:
parent
0df93e1886
commit
cd8e1e3b3b
22 changed files with 1345 additions and 191 deletions
128
handle_signup.go
128
handle_signup.go
|
|
@ -68,32 +68,23 @@ func (app *App) handlePublicSignup(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// Auto-match attendee by email or create new
|
||||
var attendeeID *int
|
||||
attendees, _ := app.listAttendees("", "", "")
|
||||
for _, a := range attendees {
|
||||
if strings.EqualFold(a.Email, body.Email) {
|
||||
id := a.ID
|
||||
attendeeID = &id
|
||||
break
|
||||
}
|
||||
// Find or create participant by email.
|
||||
name := body.PreferredName
|
||||
if body.TicketName != "" {
|
||||
name = body.TicketName
|
||||
}
|
||||
|
||||
if attendeeID == nil {
|
||||
name := body.PreferredName
|
||||
if body.TicketName != "" {
|
||||
name = body.TicketName
|
||||
}
|
||||
newAttendee, err := app.createAttendee(Attendee{
|
||||
Name: name,
|
||||
Email: body.Email,
|
||||
Phone: body.Phone,
|
||||
})
|
||||
if err != nil {
|
||||
writeError(w, "internal error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
attendeeID = &newAttendee.ID
|
||||
participant, _, err := app.upsertParticipant(body.Email, name)
|
||||
if err != nil {
|
||||
writeError(w, "internal error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Update participant's personal details if they signed up with more info.
|
||||
if body.Phone != "" || body.Pronouns != "" {
|
||||
app.db.Exec(`UPDATE participants SET
|
||||
phone = CASE WHEN phone = '' THEN ? ELSE phone END,
|
||||
pronouns = CASE WHEN pronouns = '' THEN ? ELSE pronouns END,
|
||||
updated_at = ?
|
||||
WHERE id = ?`, body.Phone, body.Pronouns, now(), participant.ID)
|
||||
}
|
||||
|
||||
confirmToken, err := generateConfirmationToken()
|
||||
|
|
@ -103,7 +94,7 @@ func (app *App) handlePublicSignup(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
vol := Volunteer{
|
||||
AttendeeID: attendeeID,
|
||||
ParticipantID: &participant.ID,
|
||||
Name: body.PreferredName,
|
||||
PreferredName: body.PreferredName,
|
||||
TicketName: body.TicketName,
|
||||
|
|
@ -159,17 +150,39 @@ func (app *App) handleConfirmEmail(w http.ResponseWriter, r *http.Request) {
|
|||
var signupsOpen string
|
||||
app.db.QueryRow(`SELECT value FROM config WHERE key = 'shift_signups_open'`).Scan(&signupsOpen)
|
||||
|
||||
if signupsOpen == "true" && vol.AttendeeID != nil {
|
||||
a, _ := app.getAttendee(*vol.AttendeeID)
|
||||
if a != nil && a.VolunteerToken == nil {
|
||||
t, err := app.generateUniqueToken()
|
||||
if err == nil {
|
||||
app.db.Exec(`UPDATE attendees SET volunteer_token=?, updated_at=? WHERE id=?`, t, now(), a.ID)
|
||||
a.VolunteerToken = &t
|
||||
if signupsOpen == "true" && vol.ParticipantID != nil {
|
||||
// Find a ticket with a code, or create/assign one.
|
||||
tickets, _ := app.listTickets(vol.ParticipantID, "")
|
||||
var code *string
|
||||
for _, tk := range tickets {
|
||||
if tk.Code != nil {
|
||||
code = tk.Code
|
||||
break
|
||||
}
|
||||
}
|
||||
if a != nil && a.VolunteerToken != nil {
|
||||
kioskLink := fmt.Sprintf("%s/v/%s", app.resolveBaseURL(), *a.VolunteerToken)
|
||||
if code == nil {
|
||||
// No coded ticket — find any ticket or create a stub, then generate code.
|
||||
var ticketID int
|
||||
if len(tickets) > 0 {
|
||||
ticketID = tickets[0].ID
|
||||
} else {
|
||||
stub, err := app.createTicket(Ticket{
|
||||
ParticipantID: vol.ParticipantID,
|
||||
Source: "manual",
|
||||
})
|
||||
if err == nil {
|
||||
ticketID = stub.ID
|
||||
}
|
||||
}
|
||||
if ticketID > 0 {
|
||||
if t, err := app.generateUniqueToken(); err == nil {
|
||||
app.db.Exec(`UPDATE tickets SET code=?, updated_at=? WHERE id=?`, t, now(), ticketID)
|
||||
code = &t
|
||||
}
|
||||
}
|
||||
}
|
||||
if code != nil {
|
||||
kioskLink := fmt.Sprintf("%s/v/%s", app.resolveBaseURL(), *code)
|
||||
response["kiosk_link"] = kioskLink
|
||||
go func() {
|
||||
if err := app.sendShiftSignupEmail(vol.Email, vol.PreferredName, kioskLink); err != nil {
|
||||
|
|
@ -203,36 +216,57 @@ func (app *App) handleToggleShiftSignups(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
|
||||
func (app *App) openShiftSignups() {
|
||||
// Generate kiosk tokens for confirmed volunteers whose attendees lack one
|
||||
vols, _ := app.listConfirmedVolunteersWithoutKioskToken()
|
||||
// Generate codes for tickets belonging to confirmed volunteers that have no code yet.
|
||||
vols, _ := app.listConfirmedVolunteersNeedingCode()
|
||||
for _, v := range vols {
|
||||
if v.AttendeeID == nil {
|
||||
if v.ParticipantID == nil {
|
||||
continue
|
||||
}
|
||||
// Find any ticket for this participant, or create a stub one.
|
||||
tickets, _ := app.listTickets(v.ParticipantID, "")
|
||||
var ticketID int
|
||||
if len(tickets) > 0 {
|
||||
ticketID = tickets[0].ID
|
||||
} else {
|
||||
stub, err := app.createTicket(Ticket{
|
||||
ParticipantID: v.ParticipantID,
|
||||
Source: "manual",
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ticketID = stub.ID
|
||||
}
|
||||
t, err := app.generateUniqueToken()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
app.db.Exec(`UPDATE attendees SET volunteer_token=?, updated_at=? WHERE id=?`, t, now(), *v.AttendeeID)
|
||||
app.db.Exec(`UPDATE tickets SET code=?, updated_at=? WHERE id=?`, t, now(), ticketID)
|
||||
}
|
||||
|
||||
// Email all confirmed volunteers with kiosk links
|
||||
// Email all confirmed volunteers that now have a ticket with a code.
|
||||
confirmed, _ := queryVolunteers(app.db, `
|
||||
SELECT `+volunteerCols+`
|
||||
FROM volunteers
|
||||
WHERE email_confirmed = 1 AND deleted_at IS NULL AND attendee_id IS NOT NULL`)
|
||||
SELECT `+volunteerSelect+` `+volunteerFrom+`
|
||||
WHERE v.email_confirmed = 1 AND v.deleted_at IS NULL AND v.participant_id IS NOT NULL`)
|
||||
baseURL := app.resolveBaseURL()
|
||||
sent := 0
|
||||
|
||||
for _, v := range confirmed {
|
||||
if v.AttendeeID == nil || v.Email == "" {
|
||||
if v.ParticipantID == nil || v.Email == "" {
|
||||
continue
|
||||
}
|
||||
a, _ := app.getAttendee(*v.AttendeeID)
|
||||
if a == nil || a.VolunteerToken == nil {
|
||||
tickets, _ := app.listTickets(v.ParticipantID, "")
|
||||
var code *string
|
||||
for _, tk := range tickets {
|
||||
if tk.Code != nil {
|
||||
code = tk.Code
|
||||
break
|
||||
}
|
||||
}
|
||||
if code == nil {
|
||||
continue
|
||||
}
|
||||
kioskLink := fmt.Sprintf("%s/v/%s", baseURL, *a.VolunteerToken)
|
||||
kioskLink := fmt.Sprintf("%s/v/%s", baseURL, *code)
|
||||
name := v.PreferredName
|
||||
if name == "" {
|
||||
name = v.Name
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue