feat(33-04): add community price service, API routes, and setup currency metadata

- Create community-price.service.ts with ownership validation, upsert, median aggregation
- Create community-prices route (GET stats public, POST requires auth + ownership)
- Register community-prices route with public GET access
- Add priceCurrency to both getSetupWithItems and getSetupWithItemsById
- Aggregation uses PERCENTILE_CONT(0.5) with 3-report minimum threshold

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 18:06:48 +02:00
parent 7d6c548811
commit 3df9eece83
4 changed files with 165 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ import { createRateLimit } from "./middleware/rateLimit.ts";
import { accountRoutes } from "./routes/account.ts";
import { authRoutes } from "./routes/auth.ts";
import { categoryRoutes } from "./routes/categories.ts";
import { communityPriceRoutes } from "./routes/community-prices.ts";
import { discoveryRoutes } from "./routes/discovery.ts";
import { exchangeRateRoutes } from "./routes/exchange-rates.ts";
import { globalItemRoutes } from "./routes/global-items.ts";
@@ -219,6 +220,9 @@ app.use("/api/*", async (c, next) => {
// Skip public market prices read endpoint (GET /api/market-prices)
if (c.req.path.startsWith("/api/market-prices") && c.req.method === "GET")
return next();
// Skip public community prices read endpoint (GET /api/community-prices)
if (c.req.path.startsWith("/api/community-prices") && c.req.method === "GET")
return next();
// All other methods require auth for userId resolution
return requireAuth(c, next);
});
@@ -240,6 +244,7 @@ app.route("/api/onboarding", onboardingRoutes);
app.route("/api/tags", tagRoutes);
app.route("/api/exchange-rates", exchangeRateRoutes);
app.route("/api/market-prices", marketPriceRoutes);
app.route("/api/community-prices", communityPriceRoutes);
// MCP server (conditionally mounted)
if (process.env.GEARBOX_MCP !== "false") {