Skip to the content.

Bulk Pole Checkout/Checkin Feature

Overview

The Bulk Checkout/Checkin feature allows admins and BPVA coaches to efficiently process multiple pole checkouts or checkins for a single athlete in one operation. This streamlines the workflow when athletes are renting or returning multiple poles simultaneously.

Key Features

Access

Who can use it:

How to access:

  1. Navigate to Admin → Pole Inventory
  2. On the Inventory or Active Rentals tab, tap the top floating action button (playlist icon) from the draggable FAB stack
    • The FAB stack contains three buttons: Bulk Checkout/Checkin, Quick Scan, and Add Pole
    • The FAB can be dragged to any position on screen
    • The FAB is hidden on the History tab

User Workflow

Checkout Mode (Default)

  1. Launch Screen: Tap the bulk checkout button (top button in FAB stack)
  2. Select Athlete: Choose the athlete from the dropdown
  3. Set Return Date (Optional): Tap to select expected return date
  4. Scan Poles:
    • Tap “Scan Pole” button
    • Scan pole’s QR code/barcode
    • Pole appears in the scanned list
    • Repeat for all poles to checkout
  5. Review List: Check the scanned poles list
    • Remove any poles by tapping the red X icon
  6. Process Checkout: Tap “Checkout X Poles” button
  7. View Results: Review success/failure summary dialog

Checkin Mode

  1. Switch Mode: Tap the toggle icon in the app bar (switches from logout to login icon)
  2. Select Athlete: Choose the athlete returning poles
  3. Scan Poles:
    • Tap “Scan Pole” button
    • Scan pole’s QR code/barcode
    • Only poles currently checked out to the athlete will be added
  4. Review List: Check the scanned poles list
  5. Process Checkin: Tap “Checkin X Poles” button
  6. View Results: Review success/failure summary dialog

Validation Rules

Checkout Mode Validations

Checkin Mode Validations

Error Messages

Scenario Message
Pole not found “Pole not found with barcode: {barcode}”
Already in list “{brand} {weight}lbs already added”
Wrong status (checkout) “{brand} {weight}lbs is {status}, not available for checkout”
Wrong status (checkin) “{brand} {weight}lbs is {status}, not checked out”
No athlete selected “Please select an athlete”
No poles scanned “Please scan at least one pole”

Technical Implementation

Files Created/Modified

New File:

Modified Files:

Data Flow

1. User scans pole barcode
   ↓
2. BulkCheckoutScreen queries PoleInventoryService.getPoleByBarcode()
   ↓
3. Validates pole status matches operation mode
   ↓
4. Adds pole to scanned list (in-memory)
   ↓
5. User taps "Checkout/Checkin X Poles" button
   ↓
6. For each pole in list:
   - Checkout mode: PoleInventoryService.checkoutPole()
   - Checkin mode: PoleInventoryService.returnPole()
   ↓
7. Collects success/error results
   ↓
8. Displays summary dialog

Batch Processing Logic

for (final pole in _scannedPoles) {
  try {
    if (_isCheckout) {
      await _poleInventoryService.checkoutPole(
        poleId: pole.id,
        athleteId: _selectedUserId!,
        athleteName: member.displayName,
        athleteEmail: member.email,
        adminUserId: currentUser.id,
        expectedReturnDate: _expectedReturnDate,
        notes: 'Bulk checkout',
      );
    } else {
      // Find active checkout and return pole
      await _poleInventoryService.returnPole(
        checkoutId: activeCheckout.id,
        adminUserId: currentUser.id,
        notes: 'Bulk checkin',
      );
    }
    successCount++;
  } catch (e) {
    errorCount++;
    errors.add('${pole.brand} ${pole.weight}lbs: $e');
  }
}

UI Components

Mode Indicator Card

Athlete Dropdown

Return Date Selector (Checkout Only)

Scanned Poles List

Action Buttons

Results Summary Dialog

Title: “Bulk Checkout Complete” or “Bulk Checkin Complete”

Content:

Behavior:

Example Use Cases

Use Case 1: New Athlete Rental

Scenario: Athlete renting 3 poles for the season

  1. Admin opens Bulk Checkout screen
  2. Selects athlete “John Smith”
  3. Sets return date to end of season (3 months)
  4. Scans 3 pole QR codes
  5. Reviews list: Essx 12’6” 130lbs, Essx 13’0” 140lbs, Gill 13’0” 135lbs
  6. Taps “Checkout 3 Poles”
  7. All succeed - auto-closes and returns to inventory

Use Case 2: End of Practice Returns

Scenario: Athlete returning borrowed poles after practice

  1. Admin opens Bulk Checkout screen
  2. Taps mode toggle to switch to Checkin Mode
  3. Selects athlete “Jane Doe”
  4. Scans 2 pole QR codes
  5. Reviews list: UCS 12’0” 125lbs, UCS 12’6” 130lbs
  6. Taps “Checkin 2 Poles”
  7. Both succeed - returns to inventory

Use Case 3: Partial Success

Scenario: Mixed results during checkout

  1. Admin scans 4 poles for checkout
  2. 3 poles are available
  3. 1 pole was already checked out
  4. Processes checkout
  5. Summary shows:
    • ✅ 3 successfully checked out
    • ❌ 1 error: “Essx 13’0” 140lbs is checkedOut, not available for checkout”
  6. Admin reviews errors and investigates the unavailable pole

Benefits Over Single-Pole Checkout

Feature Single (Quick Scan) Bulk Checkout
Athlete selection After scanning Before scanning
Multiple poles Scan → checkout → repeat Scan all → checkout once
Return date Set per pole Set once for all
Error review Immediate interrupt Summary at end
Workflow efficiency Good for 1 pole Excellent for 3+ poles

Future Enhancements (Potential)

Testing Recommendations

Manual Testing Checklist

Unit Test Coverage

BulkCheckoutScreen widget tests:

Integration tests:

Firestore Impact

Collections Modified

/poles/{poleId}

/pole_checkouts/{checkoutId} (new documents)

/pole_checkouts/{checkoutId} (updates)

Write Operations

Notes for Developers

  1. Singleton Services: The screen uses injected services or falls back to singleton instances
  2. Test Constructors: Service dependencies can be mocked for testing
  3. Error Collection: Batch processing collects all errors rather than stopping on first failure
  4. Notes Field: Hardcoded to “Bulk checkout” / “Bulk checkin” to distinguish from single-pole operations
  5. Active Checkout Query: For checkin, queries athlete’s checkout history to find active checkout for each pole
  6. Navigator Context: Careful handling of dialog contexts to avoid “BuildContext across async gaps” issues

Version History