Go service: catalog (Postgres) + cart + pricing / quotes. Folders: cmd/ (binaries), internal/ (app code).
- Create a Postgres database.
- Copy
env.example→.env(repo root) and setECOMMERCE_DATABASE_URL(orECOMMERCE_DB_*) andECOMMERCE_AUTH_SECRET(used to sign login tokens). - Run the API (migrations apply on startup):
go run ./cmd/catalog-serverDefault listen address: :8787 (override with ECOMMERCE_HTTP_ADDR).
Base URL: http://localhost:8787 (or your ECOMMERCE_HTTP_ADDR).
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/products |
List (limit, offset, category, status) |
| GET | /v1/products/{id} |
One product |
| POST | /v1/products |
Create (sku, name, description, category, base_price, optional status) |
| PATCH | /v1/products/{id} |
Partial update |
| DELETE | /v1/products/{id} |
Archive |
Categories: electronics, apparel. Status: draft, active, archived.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/carts/add |
Add line; omit cart_id to create a cart, then reuse that id |
| GET | /v1/carts/{id} |
Cart snapshot (lines + discount fields) |
| POST | /v1/carts/{id}/discount |
Set discount (catalog offer or inline JSON; see models) |
| POST | /v1/carts/{id}/quote |
Price this cart (read-only; returns totals) |
| POST | /v1/carts/{id}/checkout |
Clear lines + discounts; same cart_id for next order |
Add to cart body (internal/models/cart/types.go):
{ "cart_id": "", "product_id": "1", "qty": 2 }Omit cart_id (or use "") on the first request; store the returned cart_id for later calls.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/users/register |
Body: email, password, name |
| POST | /v1/users/login |
Body: email, password → { "access_token", "user" } |
| GET | /v1/users/me |
Current user (header Authorization: Bearer <token>) |
| PATCH | /v1/users/me |
Update name and/or password (same header) |
Passwords are stored with bcrypt. Tokens are HMAC-signed (not JWT); set a strong ECOMMERCE_AUTH_SECRET in production.
All routes require Authorization: Bearer <token> from login.
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/me/cart |
Get or create the user’s cart; snapshot includes user_id |
| POST | /v1/me/cart/add |
Body: product_id, qty (same as guest add, no cart_id) |
| POST | /v1/me/cart/discount |
Same body as POST /v1/carts/{id}/discount |
| POST | /v1/me/cart/quote |
Same body as POST /v1/carts/{id}/quote |
| POST | /v1/me/cart/checkout |
Clear that user’s cart (same cart row next time) |
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/discount-offers |
List (active_only, code, limit, offset) |
Rows live in discount_offers; carts can reference them via discount_offer_id.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/checkout/quote |
Quote from JSON lines + tax/shipping/rules/promos in one request |
Response shape: subtotal, discount, shipping, tax, total (see internal/models/checkout/types.go).
Pricing demo (no DB):
go run ./cmd/pricing-demoMigrations only:
go run ./cmd/migrate up
go run ./cmd/migrate downUses the same DB env vars as catalog-server.
internal/db/migrations/— SQL (001products,002carts,003discount offers,004users +carts.user_id)internal/repository/— Postgres: products, carts, discount offersinternal/service/—product,cart,discount_offerinternal/handlers/— HTTPinternal/pricing/— rules, promos, quote computation