feat(33-01): add market_prices, community_prices tables and currency columns

- Add marketPrices table with unique(globalItemId, market, currency) constraint
- Add communityPrices table with unique(globalItemId, userId, sourceType) constraint
- Add priceCurrency column to items table (default EUR)
- Add foundPriceCents, foundPriceCurrency, foundPriceDate to threadCandidates
- Add Zod schemas for market price upsert and community price submission
- Export new types from shared/types.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 18:02:00 +02:00
parent 1d15d4b336
commit 298fa6d586
3 changed files with 77 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ export const createItemSchema = z.object({
quantity: z.number().int().positive().optional(),
globalItemId: z.number().int().positive().optional(),
purchasePriceCents: z.number().int().nonnegative().optional(),
priceCurrency: z.string().max(3).optional(),
brand: z.string().optional(),
dominantColor: z.string().nullable().optional(),
cropZoom: z.number().nullable().optional(),
@@ -70,6 +71,9 @@ export const createCandidateSchema = z.object({
cropZoom: z.number().nullable().optional(),
cropX: z.number().nullable().optional(),
cropY: z.number().nullable().optional(),
foundPriceCents: z.number().int().nonnegative().optional(),
foundPriceCurrency: z.string().max(3).optional(),
foundPriceDate: z.string().optional(),
});
export const updateCandidateSchema = createCandidateSchema.partial();
@@ -167,3 +171,21 @@ export const deleteAccountSchema = z.object({
export const completeOnboardingSchema = z.object({
globalItemIds: z.array(z.number().int().positive()).max(50),
});
// Market price schemas
export const upsertMarketPriceSchema = z.object({
market: z.string().min(1).max(10),
currency: z.string().min(1).max(3),
priceCents: z.number().int().nonnegative(),
source: z.string().optional(),
});
// Community price schemas
export const submitCommunityPriceSchema = z.object({
globalItemId: z.number().int().positive(),
market: z.string().min(1).max(10),
currency: z.string().min(1).max(3),
priceCents: z.number().int().nonnegative(),
priceDate: z.string().optional(),
sourceType: z.enum(["purchased", "researched"]),
});

View File

@@ -1,9 +1,11 @@
import type { z } from "zod";
import type {
categories,
communityPrices,
globalItems,
globalItemTags,
items,
marketPrices,
setupItems,
setups,
tags,
@@ -21,6 +23,8 @@ import type {
createThreadSchema,
deleteAccountSchema,
reorderCandidatesSchema,
submitCommunityPriceSchema,
upsertMarketPriceSchema,
resolveThreadSchema,
searchGlobalItemsSchema,
syncSetupItemsSchema,
@@ -75,3 +79,9 @@ export type GlobalItemTag = typeof globalItemTags.$inferSelect;
export type ChangePassword = z.infer<typeof changePasswordSchema>;
export type ChangeEmail = z.infer<typeof changeEmailSchema>;
export type DeleteAccount = z.infer<typeof deleteAccountSchema>;
// Market & community price types
export type MarketPrice = typeof marketPrices.$inferSelect;
export type CommunityPrice = typeof communityPrices.$inferSelect;
export type UpsertMarketPrice = z.infer<typeof upsertMarketPriceSchema>;
export type SubmitCommunityPrice = z.infer<typeof submitCommunityPriceSchema>;