Skip to main content

Product

๐Ÿ“– Overviewโ€‹

internal/api/v1/billing/services/product.service.js provides CRUD-style operations for Stripe products and prices. It powers catalogue management inside DashClicks, enabling teams to search, filter, add, archive, or delete products and associated pricing. The service centralises Stripe interactions, ensuring consistent pagination, metadata, and error handling.

Primary Controller: product.controller.js

๐Ÿ”— External Dependenciesโ€‹

  • Stripe Products API โ€“ Create, retrieve, update, archive, and delete products.
  • Stripe Prices API โ€“ Manage recurring and one-time price entries.
  • Stripe Files API โ€“ Upload assets (e.g., product images) and optional file links.
  • Stripe Subscriptions API โ€“ Count active subscriptions per price when requested.

๐Ÿง  Key Behavioursโ€‹

  • Supports search-based pagination via stripe.products.search when a query is provided.
  • Differentiates active vs archived status filters, translating them to Stripe active flags.
  • Harmonises price interval naming (one_time โ†’ one-time) for UI consistency.
  • Buckets prices into archive/unarchive arrays for quick UI rendering.
  • Wraps Stripe connection failures with the standard custom error helper.

๐Ÿ”„ Data Flowโ€‹

flowchart TD
UI[Catalogue UI] -->|GET/POST| Controller
Controller --> Service
Service -->|stripeAccount| Stripe
Stripe --> Products
Stripe --> Prices
Stripe --> Files

๐Ÿงฉ Functionsโ€‹

Retrievalโ€‹

  • getProducts({ status, search, limit, lastProductId, firstProductId, nextPage, type, currency, stripeBilling })
    • Lists products, applies optional search, and eagerly loads associated prices (up to 100).
    • Returns cursor metadata, has_more, and price buckets.
  • getFilters({ stripeBilling })
    • Auto-paginates Stripe products to compute counts for Active vs Archived filters.
  • getProduct({ productId, expand, stripeBilling })
    • Retrieves a single product, optionally expanding price arrays with subscription counts.

Mutationโ€‹

  • addProduct({ productDetails, priceDetails, stripeBilling })
    • Creates a product (respecting requested status), then creates prices from payload.
  • addFiles({ file, purpose, fileLinkData, stripeBilling })
    • Reads file buffer, uploads via Stripe Files API, optionally creating file links.
  • addPrice({ productId, priceDetails, stripeBilling })
    • Adds a new price, supporting custom intervals when requested.
  • updateProduct({ productId, productDetails, priceDetails, stripeBilling })
    • Updates product metadata, adds or renames prices, and honours archive flags.
  • archiveProduct({ productId, active, stripeBilling }) / archivePrice({ priceId, active, stripeBilling })
    • Toggles active state for products or prices.
  • updatePrice({ priceId, priceDetails, stripeBilling })
    • Performs partial updates on price metadata (e.g., nickname).
  • deleteProduct({ productId, stripeBilling })
    • Attempts deletion; converts Stripe dependency errors into a friendly archive suggestion.

๐Ÿงช Testing Notesโ€‹

  • Mock Stripe responses when unit testing getProducts to cover search and pagination branches.
  • For end-to-end flows, verify price buckets and subscription counts when expand = true.

โš ๏ธ Operational Considerationsโ€‹

  • Controllers should limit limit to avoid hitting Stripe rate limits when expanding prices.
  • Custom interval pricing requires additional fields (interval_type, interval_count) in payloads.
  • File uploads rely on file.data containing a local path readable by the Node process.
๐Ÿ’ฌ

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM