- Added `businessPricing.service.js` to handle business customer pricing logic. - Introduced `money.js` for money parsing, formatting, and calculations. - Created `pricing.service.js` to manage variant quoting and promotion application. - Updated validation schemas in `catalogue.schemas.js` and `inventoryMerchandising.schemas.js` for new pricing and inventory features. - Implemented cron job for inventory reservation expiry in `inventoryReservationExpiry.cron.js`. - Created database migrations for catalogue and inventory structures. - Added unit tests for catalogue localization, validation, and inventory merchandising functionalities.
3.8 KiB
ZUMRI Catalogue API
Catalogue reads use /api/v1; /api remains compatible. Public endpoints require no authentication. Administrative endpoints require Phase 1 permissions. Examples use placeholders.
Localization
Locale priority is ?locale=en|si|ta, X-Locale, authenticated profile preference, Accept-Language, then English. Missing requested content falls back to English and then the first available translation.
Public products
GET /api/v1/productsGET /api/v1/products/:slugPOST /api/v1/products/:productId/reviews— authenticated customer
List query parameters: page, limit (maximum 100), category, brand, search, minPrice, maxPrice, featured, newArrival, locale, and sort=newest|price_asc|price_desc|name|featured. Unsupported sorts return 400. Stock and wholesale availability are intentionally absent.
{"data":[{"id":"<product-id>","slug":"<slug>","name":"<localized-name>","primaryImage":{"url":"<short-lived-url>"},"minPrice":"1000.00","maxPrice":"1200.00","currency":"LKR","featured":false,"newArrival":true}]}
Detail returns localized content/SEO, brand, categories, active variants, options, descriptive attributes, signed gallery media, a structured size guide, rating summary, and approved review preview. DRAFT, INACTIVE, ARCHIVED, and HIDDEN products always return 404 publicly.
Review body is {"rating":5,"title":"<title>","body":"<review>"}. status, verifiedPurchase, moderator, and user IDs are rejected. One review per user/product is enforced. Purchase verification defaults false until order integration exists.
Categories, brands, and collections
GET /api/v1/categories— tree; addflat=truefor a flat listGET /api/v1/categories/:slugGET /api/v1/brandsGET /api/v1/brands/:slugGET /api/v1/collectionsGET /api/v1/collections/:slug
Only active categories/brands and currently scheduled active collections are returned.
Administrative products
GET /api/v1/admin/products—catalogue.products.readPOST /api/v1/admin/products—catalogue.products.createGET /api/v1/admin/products/:id— read permissionPATCH /api/v1/admin/products/:id—catalogue.products.updateDELETE /api/v1/admin/products/:id—catalogue.products.delete; archives instead of deletingPOST /api/v1/admin/products/:productId/variantsPATCH /api/v1/admin/products/:productId/variants/:variantIdPOST /api/v1/admin/products/:productId/optionsPOST /api/v1/admin/products/:productId/mediaPOST /api/v1/admin/products/:productId/relations
Product creation atomically persists translations, category joins, variants, and owned Phase 2 uploads. Prices are decimal strings. Publishing requires English content, a brand, an active variant, and primary media. Published slugs are immutable.
Administrative content
POST|PATCH /api/v1/admin/brands[/:id]—catalogue.brands.managePOST|PATCH /api/v1/admin/categories[/:id]—catalogue.categories.managePOST /api/v1/admin/collections—catalogue.collections.managePOST /api/v1/admin/size-guides—catalogue.size-guides.manageGET /api/v1/admin/reviews—catalogue.reviews.readPATCH /api/v1/admin/reviews/:id/status—catalogue.reviews.moderate
Categories cannot parent themselves or form cycles. Referenced categories/brands have no hard-delete API. Collections use deterministic join ordering and publish windows. Size guides accept structured columns/rows, never HTML.
Media and prices
Media must be an AVAILABLE upload owned by the acting administrator. Linking transfers metadata ownership to the catalogue Product. Public responses contain short-lived signed URLs but never object keys, bucket names, or credentials. basePrice and optional compareAtPrice are display catalogue prices only; promotions and authoritative shopping pricing are deferred.