← Back to Systems Operations Hub

📦 Product Catalog System

Multi-Brand Shopify Integration with Inventory Management

Database: Nova_StaX_DB | Documentation for Justin & Development Team

System Overview

Purpose: Centralized product catalog management system supporting 8 brand-specific Shopify stores with real-time inventory synchronization, multi-location warehousing, and comprehensive API access for product operations.

Key Features

🎯 Multi-Brand Support

Single database managing products for 8+ brands, each with dedicated Shopify stores.

🔄 Bidirectional Sync

Real-time synchronization between local database and Shopify stores (create, update, delete).

📊 Inventory Management

Multi-location inventory tracking with automated reorder points and low-stock alerts.

🚀 RESTful API

Complete CRUD operations for products, variants, inventory, and analytics.

🪝 Webhook Integration

Shopify webhooks for order events, product updates, and inventory changes.

🔒 Azure Integration

Azure SQL Database, Blob Storage for images, Key Vault for secrets.

System Architecture Diagram

Product SKU Entry UI
Flask API (product_catalog_api.py)
Nova_StaX_DB (Azure SQL)
Shopify Sync Service
8 Shopify Stores


Azure Blob Storage (Images)
Product Images


Shopify Webhooks
Inventory Updates

Technology Stack

Component Technology Purpose
Backend API Flask (Python) RESTful API endpoints for product operations
Database Azure SQL (Nova_StaX_DB) Centralized product catalog and inventory
E-commerce Platform Shopify (8 stores) Online storefronts for each brand
Image Storage Azure Blob Storage Product images with CDN delivery
Secrets Management Azure Key Vault Shopify API tokens, database connection strings
Authentication Azure AD (Tenant-only) Secure product management access
Frontend HTML/JavaScript Product SKU Entry interface

Database Architecture

Database: Nova_StaX_DB on dranschak-family-server (West US 2)
Server: dranschak-family-server.database.windows.net
Tier: General Purpose Gen5, 2 vCores, 250 GB storage
Cost: $260/month (existing - no new database cost)

9 Core Tables

Table Name Purpose Key Fields
Brands Brand definitions BrandID, BrandName, BrandCode, ShopifyStoreURL, ShopifyAccessToken
Categories Hierarchical product categories CategoryID, CategoryName, ParentCategoryID, DisplayOrder
Products Master product catalog ProductID, SKU, ProductName, BasePrice, ShopifyProductID, IsShopifySync
ProductVariants Product variations (size/color) VariantID, VariantSKU, Size, Color, Price, ShopifyVariantID
ProductImages Product images (Azure Blob URLs) ImageID, ProductID, ImageURL, IsPrimary, DisplayOrder
InventoryLocations Warehouse/fulfillment centers LocationID, LocationName, LocationCode, LocationType
Inventory Multi-location stock levels InventoryID, VariantID, LocationID, QuantityAvailable, ReorderPoint
ShopifySyncLog Audit trail for Shopify operations LogID, ProductID, SyncType, SyncStatus, ErrorMessage, SyncedAt
ProductPricingHistory Price change tracking HistoryID, ProductID, OldPrice, NewPrice, ChangedAt

3 Database Views

View Name Purpose
vw_ProductCatalog Denormalized product data (products + brands + categories + primary images)
vw_InventoryStatus Current inventory levels across all locations
vw_LowStockAlerts Products below reorder point (automated alerts)

2 Stored Procedures

Procedure Purpose Parameters
sp_AdjustInventory Safely adjust inventory quantities @VariantID, @LocationID, @Adjustment, @UpdatedBy, @Reason
sp_CreateProductWithVariant Create product + default variant atomically @SKU, @ProductName, @BrandID, @CategoryID, @BasePrice, @CreatedBy

Relationships

Brands (1) → (M) Products
Categories (1) → (M) Products (hierarchical, self-referencing)
Products (1) → (M) ProductVariants
Products (1) → (M) ProductImages
ProductVariants (1) → (M) Inventory
InventoryLocations (1) → (M) Inventory
Products (1) → (M) ShopifySyncLog
Products (1) → (M) ProductPricingHistory
Schema File: apps/production_ready/drantechai_developer_flaskapp/database/schemas/product_catalog_schema.sql
Contains complete schema with indexes, triggers, sample data, and verification queries.

Brand-Store Mappings

Each brand has a dedicated Shopify store with unique credentials. Products are filtered by BrandID to ensure proper routing.

Brand Code Shopify Store Primary Products Status
CellJourney CJ celljourney.myshopify.com Supplements, wellness products Active
EnableYou EY enableyou.myshopify.com AI services, QSpective products Active
QSpective QS qspective.myshopify.com Business intelligence tools Active
Nova_X NX novax.myshopify.com Astrology, wellness tech Active
LuckyFig LF luckyfig.myshopify.com Lifestyle products Active
SarcasticMushroom SM sarcasticmushroom.myshopify.com Novelty items Active
5WhyGlobal 5W 5whyglobal.myshopify.com Consulting services Pending
DranTech.ai DT drantech.myshopify.com Enterprise AI solutions Active

Environment Variables Required (Per Brand)

# CellJourney Example
SHOPIFY_CJ_ACCESS_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxxx
SHOPIFY_CJ_STORE_URL=celljourney.myshopify.com
SHOPIFY_CJ_LOCATION_ID=12345678901  # Primary fulfillment location ID

# Repeat for each brand:
SHOPIFY_EY_ACCESS_TOKEN=...
SHOPIFY_QS_ACCESS_TOKEN=...
SHOPIFY_NX_ACCESS_TOKEN=...
SHOPIFY_LF_ACCESS_TOKEN=...
SHOPIFY_SM_ACCESS_TOKEN=...
SHOPIFY_5W_ACCESS_TOKEN=...
SHOPIFY_DT_ACCESS_TOKEN=...
Security: Shopify access tokens should be stored in Azure Key Vault, NOT in code or environment files. Use Key Vault references in Azure App Service Configuration.

API Reference

Base URL: https://www.drantech.ai/api/products

Authentication: Azure AD tenant authentication required (Authorization header with JWT token)

Product Endpoints

GET /api/products

List all products with optional filters.

Parameter Type Description
brandId int (optional) Filter by brand
categoryId int (optional) Filter by category
isActive bool (default: true) Filter by active status
shopifySync bool (optional) Filter by Shopify sync status
page int (default: 1) Page number
pageSize int (default: 50, max: 200) Results per page
GET /api/products?brandId=1&categoryId=5&page=1&pageSize=20

Response:
{
  "products": [
    {
      "productId": 1,
      "sku": "CJ-SUP-1732022400",
      "name": "CellOptimize Pro",
      "basePrice": 49.99,
      "brand": "CellJourney",
      "category": "Supplements",
      "shopifySync": true,
      "shopifyProductId": 7891234567890,
      "variantCount": 3,
      "primaryImageUrl": "https://..."
    }
  ],
  "total": 45,
  "page": 1,
  "pageSize": 20,
  "totalPages": 3
}

POST /api/products

Create new product with optional Shopify sync.

POST /api/products
Content-Type: application/json
Authorization: Bearer {token}

{
  "name": "CellOptimize Pro",
  "description": "Advanced cellular optimization supplement",
  "brandId": 1,
  "categoryId": 5,
  "basePrice": 49.99,
  "tags": ["supplement", "wellness", "cellular"],
  "shopifySync": true,
  "seoTitle": "CellOptimize Pro - Cellular Health Supplement",
  "seoDescription": "Scientifically formulated for optimal cellular health"
}

Response (201 Created):
{
  "success": true,
  "productId": 123,
  "sku": "CJ-SUP-1732022400",
  "shopifyProductId": 7891234567890
}

GET /api/products/{productId}

Get detailed product information including variants and images.

GET /api/products/123

Response:
{
  "productId": 123,
  "sku": "CJ-SUP-1732022400",
  "name": "CellOptimize Pro",
  "description": "...",
  "brand": {
    "id": 1,
    "name": "CellJourney",
    "code": "CJ",
    "shopifyStoreUrl": "celljourney.myshopify.com"
  },
  "category": {
    "id": 5,
    "name": "Supplements"
  },
  "variants": [
    {
      "variantId": 456,
      "sku": "CJ-SUP-1732022400-30CT",
      "name": "30 capsules",
      "price": 49.99,
      "inventoryQuantity": 150
    }
  ],
  "images": [...]
}

PUT /api/products/{productId}

Update product details (partial updates supported).

DELETE /api/products/{productId}

Soft delete product (sets IsActive = 0).

Inventory Endpoints

GET /api/products/variants/{variantId}/inventory

Get inventory levels across all locations.

POST /api/products/variants/{variantId}/inventory/adjust

Adjust inventory quantity.

POST /api/products/variants/456/inventory/adjust

{
  "locationId": 1,
  "adjustment": -5,
  "reason": "Order fulfillment"
}

Response:
{
  "success": true,
  "newQuantity": 145
}

Shopify Sync Endpoints

POST /api/products/{productId}/sync-shopify

Manually trigger Shopify sync.

Analytics Endpoints

GET /api/products/analytics/low-stock

Get products below reorder point.

GET /api/products/analytics/brand-summary

Product count summary by brand.

Helper Endpoints

GET /api/products/brands

List all active brands.

GET /api/products/categories

List all categories (hierarchical).

Shopify Integration

Integration Flow

1. Create Product in Database
2. shopify_sync_service.py
3. Shopify Admin API
4. Store ShopifyProductID


5. Shopify Webhook (Order Created)
6. webhooks_bp.py
7. Update Inventory

Shopify API Client Usage

from shopify_sync_service import ShopifyClient

# Initialize client for CellJourney
client = ShopifyClient('CJ')

# Create product
shopify_product_id = client.create_product({
    "title": "CellOptimize Pro",
    "body_html": "Advanced supplement...",
    "vendor": "CellJourney",
    "product_type": "Supplements",
    "tags": ["supplement", "wellness"],
    "variants": [
        {
            "sku": "CJ-SUP-1732022400",
            "price": "49.99",
            "option1": "30 capsules"
        }
    ]
})

# Update product
client.update_product(shopify_product_id, {
    "title": "CellOptimize Pro (Updated)"
})

# Sync inventory
client.update_inventory(
    shopify_inventory_item_id=12345,
    shopify_location_id=67890,
    quantity=150
)

Webhook Configuration

Webhook Topic Endpoint Purpose
orders/create /webhooks/shopify/orders/create Reduce inventory when order placed
orders/cancelled /webhooks/shopify/orders/cancelled Restore inventory when order cancelled
products/update /webhooks/shopify/products/update Sync product changes from Shopify to database
Webhook Security: All Shopify webhooks use HMAC-SHA256 signature verification via X-Shopify-Hmac-SHA256 header to prevent spoofing.

How-To Guides

How to Add a New Product

  1. Navigate to Product SKU Entry: Go to /products/product_sku_entry.html
  2. Select Brand: Choose the brand from dropdown (e.g., CellJourney)
  3. Select Category: Pick category (e.g., Supplements → Cellular Health)
  4. Enter Product Details:
    • Product Name
    • Description
    • Base Price
    • Cost Price (optional)
    • Compare At Price (for discounts)
    • Tags (comma-separated)
  5. Add Variants (if applicable):
    • Size (e.g., 30 capsules, 60 capsules)
    • Color
    • Material
    • Price per variant
  6. Upload Images: Drag-drop product images (auto-uploads to Azure Blob Storage)
  7. Set Initial Inventory: Enter quantity for each warehouse location
  8. Enable Shopify Sync: Toggle "Sync to Shopify" if you want product in Shopify store immediately
  9. Click "Create Product": System will:
    • Auto-generate SKU
    • Save to Nova_StaX_DB
    • Create Shopify product (if sync enabled)
    • Upload images to Azure Blob
    • Log sync attempt to ShopifySyncLog

How to Update Inventory

  1. Go to Inventory Dashboard: Access from Product SKU Entry page
  2. Find Product/Variant: Search by SKU or product name
  3. Select Location: Choose warehouse (East Coast, West Coast, etc.)
  4. Enter Adjustment:
    • Positive number = Add inventory (e.g., +100 for new shipment)
    • Negative number = Remove inventory (e.g., -5 for manual order)
  5. Add Reason: Document adjustment (e.g., "Received shipment", "Damaged goods")
  6. Submit: System will:
    • Update Inventory table
    • Sync to Shopify (if product is synced)
    • Trigger low-stock alert if below reorder point

How to Sync Product to Shopify

  1. Automatic Sync (Recommended):
    • Enable "Sync to Shopify" when creating product
    • System automatically creates Shopify product
  2. Manual Sync:
    • Navigate to product details
    • Click "Sync to Shopify Now" button
    • View sync status in ShopifySyncLog table
  3. API Sync:
    POST /api/products/123/sync-shopify

How to Configure Shopify API Credentials

  1. Create Shopify Private App:
    • Log into Shopify admin (e.g., celljourney.myshopify.com/admin)
    • Go to Settings → Apps and sales channels → Develop apps
    • Click "Create an app"
    • Name: "DranTechAI Product Sync"
    • Configure Admin API scopes:
      • read_products, write_products
      • read_inventory, write_inventory
      • read_orders
    • Install app and copy Admin API access token
  2. Store in Azure Key Vault:
    • Open Azure Portal → Key Vault (qi3ci-keyvault)
    • Secrets → Generate/Import
    • Name: SHOPIFY-CJ-ACCESS-TOKEN
    • Value: shpat_xxxxxxxxxxxxx
    • Repeat for each brand
  3. Configure App Service:
    • Azure Portal → App Service (cell-journet or Dranschak-East2-App)
    • Configuration → Application settings
    • Add references:
      SHOPIFY_CJ_ACCESS_TOKEN = @Microsoft.KeyVault(SecretUri=https://qi3ci-keyvault.vault.azure.net/secrets/SHOPIFY-CJ-ACCESS-TOKEN)

Troubleshooting

Common Issues

❌ "Product failed to sync to Shopify"

Symptoms: Product created in database but not appearing in Shopify store.

Diagnosis:

  1. Check ShopifySyncLog table:
    SELECT TOP 10 * FROM ShopifySyncLog
    WHERE SyncStatus = 'Failed'
    ORDER BY SyncedAt DESC;
  2. Review ErrorMessage column for API errors

Solutions:

❌ "SKU already exists"

Cause: Duplicate SKU in Products table.

Solution:

  1. Check existing SKUs:
    SELECT SKU, ProductName FROM Products WHERE SKU = 'CJ-SUP-1732022400';
  2. Modify SKU or update existing product instead of creating new one

❌ "Inventory not syncing to Shopify"

Diagnosis:

  1. Verify variant has ShopifyVariantID:
    SELECT VariantSKU, ShopifyVariantID FROM ProductVariants WHERE VariantID = 456;
  2. Check Shopify location ID configured:
    echo $env:SHOPIFY_CJ_LOCATION_ID

Solution: Ensure variant is synced to Shopify first, then inventory sync will work.

❌ "Database connection failed"

Symptoms: API returns "Failed to fetch products".

Solution:

  1. Check connection string in App Service Configuration:
    AZURE_SQL_CONNECTIONSTRING
  2. Verify Azure SQL firewall allows App Service IP
  3. Test connection:
    sqlcmd -S dranschak-family-server.database.windows.net -d Nova_StaX_DB -U {user} -P {pass}

❌ "Images not uploading to Azure Blob"

Diagnosis:

  1. Check Blob Storage container exists: product-images
  2. Verify CORS configured for frontend domain
  3. Check connection string in Key Vault: AZURE_STORAGE_CONNECTIONSTRING

Debugging Tools

Tool Purpose
Azure Portal → SQL Database Query Editor Run SQL queries directly on Nova_StaX_DB
Shopify Admin → Settings → Notifications → Webhooks View webhook delivery status
Azure App Service → Log stream Real-time API logs
SELECT * FROM ShopifySyncLog Audit trail of all Shopify operations
SELECT * FROM vw_LowStockAlerts Inventory alerts

Deployment Checklist

Pre-Deployment

☐ Database Setup

  • Execute product_catalog_schema.sql on Nova_StaX_DB
  • Verify all 9 tables created
  • Confirm seed data loaded (5 brands, 20 categories, 5 locations)
  • Test views and stored procedures

☐ Azure Resources

  • Create Blob Storage container: product-images
  • Configure CORS for www.drantech.ai
  • Set container access level: Blob (anonymous read)

☐ Shopify Apps

  • Create private app for each brand (8 total)
  • Configure API scopes (read/write products, inventory)
  • Copy access tokens
  • Note location IDs

☐ Azure Key Vault

  • Store database connection string
  • Store Blob Storage connection string
  • Store Shopify access tokens (8)
  • Store Shopify location IDs (8)

Deployment Steps

  1. Deploy Backend Code:
    cd backend/blueprints/ecomm_flows
    git add product_catalog_api.py shopify_sync_service.py __init__.py
    git commit -m "Add Product Catalog API with Shopify integration"
    git push origin main
  2. Configure App Service:
    • Add environment variables from Key Vault
    • Restart app service
  3. Register Blueprints:
    • Update main app.py to import register_ecomm_blueprints
    • Call registration function
  4. Deploy Frontend:
    • Update Product SKU Entry page
    • Test image upload to Blob Storage
  5. Configure Webhooks:
    • For each Shopify store, add webhooks:
      • orders/create → https://www.drantech.ai/webhooks/shopify/orders/create
      • orders/cancelled → https://www.drantech.ai/webhooks/shopify/orders/cancelled
      • products/update → https://www.drantech.ai/webhooks/shopify/products/update

Post-Deployment Verification

  1. Test API Endpoints:
    # List brands
    curl https://www.drantech.ai/api/products/brands
    
    # Create test product
    curl -X POST https://www.drantech.ai/api/products \
      -H "Authorization: Bearer {token}" \
      -H "Content-Type: application/json" \
      -d '{"name": "Test Product", "brandId": 1, "categoryId": 5, "basePrice": 19.99}'
  2. Verify Shopify Sync:
    • Check Shopify admin for test product
    • Verify ShopifySyncLog for successful sync
  3. Test Inventory Update:
    • Adjust inventory via API
    • Verify Shopify inventory updated
  4. Test Webhooks:
    • Place test order in Shopify
    • Verify inventory reduced in database
Success Metrics:
  • API response time < 200ms
  • Shopify sync success rate > 99%
  • Product entry time < 3 minutes
  • Webhook delivery success > 98%

Additional Resources

Questions? Contact development team or review the comprehensive implementation plan in the docs folder.