winofy-backend/CHANGELOG.md

4 KiB

Changelog

[Unreleased]

Fixed

  • GET /api/v1/stores/ — documented the category, neighborhood, search, lat, and lng query params for drf-spectacular so they render in swagger. The filtering itself already worked; only the OpenAPI schema was missing them (apps/stores/views.py).
  • GET /api/v1/products/ — same issue: documented the existing store, category, and search query params for swagger (apps/catalog/views.py).
  • Cart items: CartItemView was registered on both /api/v1/cart/items/ and /api/v1/cart/items/{item_uuid}/, so swagger showed POST/PATCH/DELETE on both paths — 3 of those 6 combinations crashed with a TypeError at runtime (item_uuid missing or unexpected). Split into CartItemView (POST only, list path) and CartItemDetailView (PATCH/DELETE only, detail path) so swagger only shows the combinations that actually work (apps/orders/views.py, apps/orders/urls.py).
  • Cancelling an order never restored the product stock that checkout() decremented, so cancelled orders' items stayed permanently out of stock. Added _restock_order_items(), run on the CANCELLED transition (apps/orders/services.py).
  • POST /api/v1/checkout/ always checked out the customer's entire cart, even when it held items from stores the customer didn't intend to order from yet. It now checks out only the requested stores when store_uuids is given (default: whole cart, unchanged), and only clears those stores' items — the rest of the cart is left intact for a later checkout (apps/orders/serializers.py, apps/orders/services.py).

Added

  • GET /api/v1/cities/?search= — search cities by name (apps/locations/views.py); previously no text search existed.
  • GET /api/v1/neighborhoods/?search= — search neighborhoods by neighborhood name or city name, alongside the existing city UUID filter (apps/locations/views.py).
  • GET /api/v1/stores/ now returns phone_number in the list (previously only on the single-store detail view) and a distance_km field, populated whenever lat/lng are passed (apps/stores/serializers.py).
  • Store latitude/longitude now come back on every store response — list, retrieve, and the seller's own store (GET/PATCH/POST /api/v1/seller/store/) — derived from Store.location via new Store.latitude/Store.longitude properties (apps/stores/models.py, apps/stores/serializers.py). Previously they were write-only on the seller serializer and absent everywhere else.
  • Test coverage for StoreViewSet list filtering (apps/stores/tests/test_store_list.py) — previously untested.
  • Test coverage for ProductViewSet list filtering (apps/catalog/tests/test_product_list.py) — previously untested.
  • Test coverage for CityViewSet/NeighborhoodViewSet list filtering (apps/locations/tests/test_location_list.py) — previously untested.
  • New Store.max_delivery_time_minutes field, set by the seller at registration (default 60), returned wherever a store appears in a response — store list/detail, the seller's own store, cart groups (GET /api/v1/cart/), and order/order-group serializers — so the checkout page's estimated-delivery-time UI no longer needs a frontend mock (apps/stores/models.py, apps/stores/serializers.py, migration 0003_store_max_delivery_time_minutes).
  • Documented CartSerializer's groups/grand_total fields for swagger (apps/orders/serializers.py) — they were SerializerMethodFields with no schema, showing as opaque strings instead of the actual nested structure.

Changed

  • Replaced hand-rolled get_queryset filtering with django-filter FilterSet classes (apps/{stores,catalog,locations,reviews}/filters.py) and filterset_fields (apps/orders status). django-filter was already installed and set as DEFAULT_FILTER_BACKENDS but unused everywhere; params are now auto-documented in swagger by drf-spectacular's django-filter integration, so the manual OpenApiParameter declarations for those fields were removed (stores keeps lat/lng manual since geo-distance isn't a plain filter).