VendorService — Physical Products Slice
core/services/vendor_service.dart · physical-products + inventory + files
Overview
Subset of VendorService dedicated to physical products: getPhysicalProducts, getPhysicalProductsRaw, getPhysicalProduct, createPhysicalProduct, updatePhysicalProduct, deletePhysicalProduct, plus inventory and file-upload helpers.
User Flow
- getPhysicalProductsRaw returns the raw response list — used by the list controller to skip Product.fromJson.
- createPhysicalProduct builds the full product including options, variants and pricing.
- uploadPublicFile (multipart) posts to /vendor/files and returns a public URL used as image src.
- setInventoryItemQuantity attaches stock to a variant at a stock location.
Cases & Edge Cases
- deletePhysicalProduct cascades to variants + inventory items server-side; clients still need to refetch.
- uploadPublicFile uses a separate Dio config — multipart can't share JSON defaults.
- Stock locations are per-seller (getStockLocations / createStockLocation) — auto-bootstrapped on first product create.
Code References
- lib/src/core/services/vendor_service.dart:176 // getPhysicalProducts
- lib/src/core/services/vendor_service.dart:230 // createPhysicalProduct
- lib/src/core/services/vendor_service.dart:250 // updatePhysicalProduct
- lib/src/core/services/vendor_service.dart:271 // deletePhysicalProduct
- lib/src/core/services/vendor_service.dart:650 // uploadPublicFile
API Calls
- GET
/vendor/products?type=physicalno statusTyped list of the seller's physical products (Product[]).
Response{ products: Product[] } /* typed */lib/src/core/services/vendor_service.dart:176 // getPhysicalProductsauth: seller. Consumed by seller_products_screen.dart.
- GET
/vendor/products?type=physicalno statusRaw-map variant used to skip Product.fromJson when the screen only needs a subset.
ResponseList<Map<string, any>> raw
lib/src/core/services/vendor_service.dart // getPhysicalProductsRawauth: seller. Same URL as the typed version, different parsing path.
- GET
/vendor/products/:idno statusPreload a single product for the edit screen.
Response{ product: Product }lib/src/features/seller/products/edit_product_screen.dartauth: seller.
- POST
/vendor/productsno statusCreate a new physical product with options + variants + images.
Request{ title, description, status, options: [{ title, values }], variants: [{ title, sku, prices: [{ currency_code, amount }], options: { <title>: <value> } }], images: [{ url }], thumbnail, ... }Response{ product: { id: string, variants: [{ id, inventory_item_id }, ...] } }lib/src/features/seller/products/create_product_screen.dart // via vendor_service.dart:230auth: seller. Returned inventory_item_ids are needed for the subsequent location-levels calls.
- POST
/vendor/products/:idno statusUpdate product fields (partial).
RequestPartial product fields
Response{ product: Product }lib/src/features/seller/products/edit_product_screen.dart // via vendor_service.dart:250auth: seller.
- DELETE
/vendor/products/:idno statusDelete a physical product.
Response200 (no body)
lib/src/features/seller/products/seller_products_screen.dart // Delete confirmauth: seller.
- GET
/vendor/stock-locationsno statusBootstrap the list of stock locations (warehouse / store).
Response{ stock_locations: [{ id, name, ... }] }lib/src/features/seller/products/create_product_screen.dart // location bootstrapauth: seller.
- POST
/vendor/stock-locationsno statusCreate a first-time stock location.
Request{ name: string, address?: any }Response{ stock_location: StockLocation }lib/src/features/seller/products/create_product_screen.dart // first-time creationauth: seller.
- POST
/vendor/inventory-items/:id/location-levelsno statusSet initial stocked_quantity for a variant at a stock location.
Request{ location_id: string, stocked_quantity: number }Response{ ... }lib/src/features/seller/products/create_product_screen.dartauth: seller. Called per variant post product-create.
- POST
/vendor/inventory-items/:id/location-levels/:levelIdno statusUpdate a variant's stocked_quantity at an existing location level.
Request{ stocked_quantity: number }Response{ ... }lib/src/features/seller/products/edit_product_screen.dart // variant stock changeauth: seller.
- POST
/vendor/product-location/:productIdno statusAttach a geographic location (lat/lng/address) to a product.
Request{ lat: number, lng: number, address?: string }Response{ ... }lib/src/features/seller/products/create_product_screen.dart // post-createauth: seller.
- POST
/vendor/filesno statusMultipart upload of a product image to the vendor files endpoint.
RequestFormData({ file: File, purpose: 'public' })Response{ url: string }lib/src/core/services/vendor_service.dart:650 // uploadPublicFileauth: seller. Used by both create + edit product screens for image upload.
Notes
Same VendorService is shared with seller-services (provisions slice) and seller-balance (Stripe slice). The class has grown to ~770 lines — splitting by domain is on the TODO list.