Skip to content

Location API Pagination Update

This guide documents the update to the location APIs to implement proper pagination and fix coordinate extraction issues.

Overview

The delivery and storage location APIs have been updated to:

  1. Fix coordinate extraction: Coordinates are now properly extracted from PostGIS geometry and returned in the correct nested format
  2. Implement pagination: APIs now return paginated responses with metadata instead of simple lists
  3. Improve consistency: Both delivery and storage location APIs use the same response format

API Changes

Before (Old Format)

The location APIs previously returned a simple list of locations:

[
  {
    "id": 1,
    "name": "Store 826 - FARMINGTON, NM",
    "latitude": 36.731928216532104,
    "longitude": -108.2261896133423,
    "production_run_id": 3
  }
]

Issues with the old format:

  • Coordinates were returned as flat latitude and longitude fields
  • No pagination metadata (total count, page info)
  • Inconsistent with other paginated APIs in the system

After (New Format)

The location APIs now return a paginated response with proper coordinate nesting:

{
  "items": [
    {
      "id": 1,
      "name": "Store 826 - FARMINGTON, NM",
      "coordinates": {
        "latitude": 36.731928216532104,
        "longitude": -108.2261896133423
      },
      "production_run_id": 3
    }
  ],
  "total": 22,
  "page": 1,
  "size": 10,
  "pages": 3
}

Benefits of the new format:

  • Coordinates are properly nested under a coordinates object
  • Pagination metadata provides total count and page information
  • Consistent with other paginated APIs in the system
  • Better support for frontend pagination components

Affected Endpoints

Delivery Locations

  • GET /api/v1/delivery-locations/ - List delivery locations with pagination
  • Response Model: schemas.base.PaginatedResponse

Storage Locations

  • GET /api/v1/storage-locations/ - List storage locations with pagination
  • Response Model: schemas.base.PaginatedResponse

Pagination Parameters

Both endpoints support the following query parameters:

Parameter Type Default Description
skip integer 0 Number of items to skip (for pagination)
limit integer 100 Maximum number of items to return
production_run_id integer None Filter by production run ID

Response Schema

The paginated response includes the following fields:

Field Type Description
items array List of location objects
total integer Total number of locations (before pagination)
page integer Current page number (1-based)
size integer Number of items per page (same as limit)
pages integer Total number of pages

Frontend Updates

API Client Fix

The main issue was in the frontend API client layer. The generic request function was "unwrapping" paginated responses:

// Problem: The request function was extracting items from paginated responses
if (response.data && response.data.items && response.data.total !== undefined) {
  return {
    data: response.data.items as T, // Only returning items array
    total: response.data.total,
    page: config.pagination?.page,
    pageSize: config.pagination?.pageSize,
  };
}

Solution: Changed location APIs to use apiClient.get() directly instead of the request wrapper:

// Before (using request wrapper)
const response = await request<PaginatedResponse>({
  method: "GET",
  url: "/delivery-locations/",
  pagination: { page, pageSize },
});
return response.data; // This was returning only the items array

// After (using apiClient directly)
const { data } = await apiClient.get("/delivery-locations/", { params });
return data; // This returns the full paginated response object

API Layer Changes

The frontend API layer has been updated to handle the new response format:

// Before
const response: { data: Location[]; total: number };

// After
const response: {
  items: Location[];
  total: number;
  page: number;
  size: number;
  pages: number;
};

Hook Changes

React hooks have been updated to access the new response structure:

// Before
const locations = data?.data || [];

// After
const locations = data?.items || [];

URL Corrections

Fixed incorrect API endpoint URLs in the frontend:

// Before (incorrect URLs)
"/locations/delivery/"  Should be "/delivery-locations/"
"/locations/storage/"   Should be "/storage-locations/"

// After (correct URLs)
"/delivery-locations/" 
"/storage-locations/"  

Coordinate Format

Coordinates are now consistently returned in the nested format:

{
  "coordinates": {
    "latitude": 36.731928216532104,
    "longitude": -108.2261896133423
  }
}

This format:

  • Matches the expected schema format
  • Is consistent with coordinate input format for create/update operations
  • Properly represents the hierarchical nature of coordinate data

Cache Updates

The caching system has been updated to handle the new response format:

  • Cache keys remain the same for consistency
  • Cached data is stored in the new paginated format
  • Cache invalidation works correctly with the new response structure

Testing

All tests have been updated to expect the new paginated response format:

  • 41 delivery location tests updated and passing
  • Response assertions check for items, total, page, size, and pages fields
  • Coordinate format validation ensures proper nesting

Migration Notes

For API Consumers

If you're consuming these APIs directly:

  1. Update response parsing: Access location data via response.items instead of response
  2. Update pagination logic: Use the new pagination metadata (total, page, pages)
  3. Update coordinate access: Access coordinates via location.coordinates.latitude instead of location.latitude

For Frontend Developers

The admin panel has been updated automatically, but if you have custom frontend code:

  1. Update API layer to handle new response format
  2. Update hooks to access items instead of data
  3. Update coordinate rendering to use nested format

Backward Compatibility

This is a breaking change for the location list endpoints. The individual location endpoints (GET by ID) maintain the same response format but with corrected coordinate nesting.

  • app/api/routes/delivery_locations.py - Delivery location API endpoints
  • app/api/routes/storage_locations.py - Storage location API endpoints
  • tracker-admin/src/api/locations.ts - Frontend API layer
  • tracker-admin/src/hooks/useLocations.ts - React hooks
  • tests/api/routes/test_delivery_locations.py - API tests

See Also