Skip to content

MacFall7/ecom-dynamic-pricing

Repository files navigation

ecom-dynamic-pricing

FastAPI + Celery + Postgres + Redis SaaS skeleton for Shopify dynamic pricing with guardrails, rollback, and audit trail.

What this is

A working skeleton for a dynamic-pricing service that can run against a Shopify catalog without exposing the merchant to the usual blast radius. The interesting problem is that it's keeping a catalog-scale pricing engine from doing damage. This repo splits authority across four layers: the pricing engine proposes a price, the merchant policy gates it, the Shopify client executes the approved change, and the audit trail records every event so any change is reversible. The operational shape is Docker Compose, Celery workers, structured logs, health and readiness probes, and an Alembic migration path.

Stack

Layer Technologies
API FastAPI, Pydantic v2, uvicorn
Workers Celery, Redis broker
Data Postgres 16, SQLAlchemy 2.x, Alembic
Integration Shopify Admin API (stub), HMAC webhook verification
Observability Structured JSON logs, X-Process-Time middleware, Sentry (optional)
Frontend React 18, TypeScript, Vite
Infra Docker Compose, GitHub Actions

Design notes

  • Authority separation. The engine proposes, the policy gates, Shopify executes, the audit records. No layer holds two responsibilities. This is what makes the system safe to run unattended on a real catalog.
  • Guardrails are inputs, not exceptions. PricingEngine(min_margin, max_change_pct, new_product_protection_days) accepts its constraints in its constructor. The engine cannot produce a suggestion that violates them. There is no try/except path that "handles" a guardrail breach because no such breach is reachable.
  • Audit trail is the rollback substrate. Every applied price change writes an append-only price_events row. Rolling back N steps reads N events back and writes a new event with source=rollback, so the rollback itself is also auditable.
  • Observability is first-class. Structured logs are JSON. Every response carries X-Process-Time. /health/ready probes Postgres and Redis individually so a degraded dependency is visible at the load-balancer layer.

Known limitations

Area Status Notes
Shopify Admin API client Stub Method signature and HMAC verification are real; the wire call is a no-op. Cutover plan in TECHNICAL_DEBT.md.
Shopify OAuth flow Not implemented access_token field exists on merchants; install/callback routes are not wired.
Frontend Operator console stub Single page reads /health/ready. The suggestion-review and rollback UI are the next milestone.
Pricing signal Toy proposal The raw signal is demand_signal - inventory_pressure. The guardrail layer is the real engineering. Replacing the proposal step does not change the safety surface.
Auth on API None API routes are unauthenticated. Add merchant-scoped JWT or session middleware before exposing publicly.

Architecture

                  +--------------------+
   demand /       |  PricingEngine     |  pure function
   inventory ---> |  (guardrails as    | --+
   signal        |   constructor args)|   |
                  +--------------------+   | PriceSuggestion
                                            v
                  +--------------------+
                  |  MerchantPolicy    |  approve / hold / reject
                  +--------------------+
                            |
                            v approved
                  +--------------------+        +-------------------+
                  |  AuditTrail.record |------->|  price_events     |
                  +--------------------+        |  (append-only)    |
                            |                   +-------------------+
                            v
                  +--------------------+
                  |  ShopifyClient     |  external write
                  +--------------------+

Data flow on a price update:

  1. Demand or inventory event triggers a Celery task (or an HTTP /pricing/suggest call).
  2. Engine returns a PriceSuggestion with the guardrails that fired.
  3. Policy reads the suggestion and emits an ApprovalDecision — auto-apply, hold for review, or reject.
  4. On approval, AuditTrail.record writes a price_events row and updates products.current_price in the same flush.
  5. ShopifyClient.update_variant_price propagates the change to the merchant's storefront (currently stubbed).
  6. Rollback reads the last N price_events for a product and emits a new event with source=rollback.

Quick start

Requirements: Docker, Docker Compose.

cp .env.example .env
# edit .env if you need to override defaults
docker compose up --build

The API serves on http://localhost:8000. The frontend dev server is cd frontend && npm install && npm run dev (port 5173, proxies /api to the backend).

Bootstrapping the schema is handled by the api service on startup (alembic upgrade head). If running the API outside Docker:

cd backend
pip install -r requirements-dev.txt
alembic upgrade head
uvicorn app.main:app --reload

Tests

cd backend
pip install -r requirements-dev.txt
pytest

The suite covers the pricing engine's guardrail surface, the merchant policy's auto-apply window, and the health endpoints. The Shopify client and Celery task layers are not exercised by tests in this repo — see TECHNICAL_DEBT.md.

Repository structure

backend/
  app/
    main.py              FastAPI app, middleware, route wiring
    config.py            pydantic-settings
    database.py          SQLAlchemy engine, session, Base
    models.py            Merchant, Product, PriceEvent
    schemas.py           Pydantic I/O models
    policy.py            MerchantPolicy
    observability.py     logging + Sentry init
    pricing/engine.py    PricingEngine + PricingInputs
    audit/service.py     AuditTrail (record, history, rollback)
    shopify/client.py    Stub + HMAC webhook verification
    api/                 health, pricing, audit routers
    tasks/               Celery app + pricing_tasks
  alembic/               migrations
  tests/
frontend/                React + TS operator console (stub)
docker-compose.yml

Roadmap

See ROADMAP.md.

License

MIT. See LICENSE.

Author

Mac McFall — m87studio.netgithub.com/MacFall7

About

FastAPI + Celery + Postgres + Redis SaaS skeleton for Shopify dynamic pricing with guardrails, rollback, and audit trail.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors