Skip to content

feat: Implement Meal Groups #63

@NoelVarghese2006

Description

@NoelVarghese2006

Feature: Implement Lunch Groups & User Check-In

Summary

Implement the backend logic, storage, and API endpoints to manage "Lunch Groups" for hackers. This feature allows super_admins to manage group assignments. Additionally, update the user schema to support a check-in status and a group identifier.

For the initial implementation, group assignment should be random. Only super_admins should have control over creating/assigning these groups.

What to build

DB Migrations

Create a new migration file inside cmd/migrate/migrations/ to alter the users table and seed default settings.

Requirements:

Alter users table:

  • Add column check_in: BOOLEAN, default FALSE. Used to determine if a user has checked into the event.
  • Add column group: TEXT (or VARCHAR), nullable. Used to store the group identifier for the user.
    • Keep the DB simple, enforce as a pseudo FK in the application

Update settings table:

  • Add a new setting (e.g., check_in_groups) to store the list of available group names.
  • This should be stored as a JSON array of strings.
  • The default value should be ["A", "B", "C", "D"].
  • These values must be editable via the API to allow for custom text names.

Store Layer

Groups Store Create internal/store/groups.go.

Concept: A store that handles the CRUD logic for group definitions (stored as a JSON list in settings) and the assignment of users to those groups.
Interface Methods:

  • List(ctx context.Context) ([]string, error): Retrieve the list of available group names.
  • GetByUserID(ctx context.Context, userID string) error: Get a user's current group.
  • Create(ctx context.Context, group string) error: Add a new group name to the list.
  • Delete(ctx context.Context, group string) error: Remove a group name. Constraint: This must cascade to the users table (set the group column to NULL for users currently in the deleted group).
  • Update(ctx context.Context, oldName, newName string) error: Rename a group. Constraint: This must cascade to the users table (update the group column for users currently in the old group).
  • AssignUser(ctx context.Context, userID string, group string) error: Assign a specific user to a group.
  • AssignRandom(ctx context.Context) error: Randomly assign unassigned users to the available groups.

Scans Store Update internal/store/scans.go

Check-In Logic:
Add SetCheckIn(ctx context.Context, userID string, checkedIn bool) error: Update the check_in status column for a specific user.

Infrastructure

Storage: Update internal/store/storage.go to include the new Groups interface and update the Scans interface.
Mocks: Update internal/store/mock_store.go to include mocks for all new methods in Groups and Scans.

API Handlers

Create cmd/api/groups.go.

Authorization: All new endpoints must be restricted to super admins using RequireRoleMiddleware(store.RoleSuperAdmin).
Handlers:

Group Definition Management:

  • listGroupsHandler: Retrieves the list of all available group names.
  • createGroupHandler: Adds a new group name to the settings.
  • updateGroupHandler: Renames an existing group, cascading the change to all assigned users.
  • deleteGroupHandler: Deletes a group name from settings and un-assigns all users from it (sets their group to NULL).

User Assignment & Status:

  • assignRandomGroupsHandler: Triggers the random assignment of unassigned users to the available groups.
  • assignUserGroupHandler: Assigns a single, specific user to a group.
  • setCheckInHandler: Updates the check_in status for a specific user.

Viewing Assignments:

  • getGroupAssignmentsHandler: Retrieves all users, organized by their assigned group. The response should also include a list of any unassigned users.
  • getByUserIDHandler: Get a user's current group.

Swagger Documentation: Ensure comprehensive Swagger documentation comments are included for all new handlers, detailing payloads, responses, and authorization requirements.

Wire Routes

Update cmd/api/api.go.

Requirements: Register the new routes under the /v1/superadmin group.
Proposed Structure:
Create a new route group for managing group definitions under /superadmin/groups:

GET /: listGroupsHandler
POST /: createGroupHandler
PUT /{oldName}: updateGroupHandler
DELETE /{groupName}: deleteGroupHandler

Create a new route group for managing assignments under /superadmin/group-assignments:

GET /: getGroupAssignmentsHandler
POST /random: assignRandomGroupsHandler
Add routes for individual user actions under the existing /superadmin/users/{userID} path:
PUT /group: assignUserGroupHandler
PUT /check-in: setCheckInHandler

Create a new route group for managing assignments under /group (hacker routes):

GET /: getByUserIDHandler

Testing

Create cmd/api/groups_test.go.

Test Cases:

Authorization:

❌ Fail if hacker or admin tries to access endpoints.
✅ Success if super_admin accesses endpoints.

Assignment:

✅ Successfully assigns groups to users (check DB state after request).

Check-In:

✅ Successfully toggles check-in status.

Group Definition

✅ Create group → appears in settings list
❌ Create duplicate group → should fail
❌ Create invalid group (empty string, too long, etc.)

Rename

✅ Rename group updates settings list
✅ All users in old group are updated to new group
❌ Rename to existing group name → should fail

Delete

✅ Delete group removes it from settings
✅ Users in that group get group = NULL
❌ Delete non-existent group → should fail

Constraint Behavior (important because you're using CHECK, not FK)

❌ Assign user to invalid group → should fail
✅ Assign user to valid group → succeeds

Random Assignment

✅ Only unassigned users are assigned
✅ Distribution is roughly even (optional but nice)
❌ No groups exist → should fail safely

Notes

The group column in the DB should be flexible enough to hold strings later, even if we start with single letters.
Cannot assign user to group if they are not checked in
Reuse existing patterns for error handling and JSON responses found in applications.go.
Once merged Hackathon Reset needs to clear groups in the settings table

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions