import type { APIRoute } from 'astro'; import { db } from '../../db/index'; import { inventory, priceHistory } from '../../db/schema'; import { client } from '../../db/typesense'; import { eq } from 'drizzle-orm'; const GainLoss = (purchasePrice: any, marketPrice: any) => { if (!purchasePrice || !marketPrice) return '
N/A
'; const pp = Number(purchasePrice); const mp = Number(marketPrice); if (pp === mp) return '
-
'; if (pp > mp) return `
-$${(pp - mp).toFixed(2)}
`; return `
+$${(mp - pp).toFixed(2)}
`; } const DollarToInt = (dollar: any) => { if (dollar === null) return null; return Math.round(dollar * 100); } const getInventory = async (userId: string, cardId: number) => { const card = await db.query.cards.findFirst({ where: { cardId: cardId, }, with : { prices: { with: { inventories: { where: { userId: userId } }, } }, }, }); const invHtml = card?.prices?.flatMap(price => price.inventories.map(inv => { const marketPrice = price.marketPrice; const marketPriceDisplay = marketPrice ? `$${marketPrice}` : '—'; const purchasePriceDisplay = inv.purchasePrice ? `$${Number(inv.purchasePrice).toFixed(2)}` : '—'; return `
${price.condition}
Added: ${inv.createdAt ? new Date(inv.createdAt).toLocaleDateString() : '—'}
Purchase price
${purchasePriceDisplay}
Market price
${marketPriceDisplay}
Gain / loss
${GainLoss(inv.purchasePrice, marketPrice)}
Qty
`; })) || []; return new Response( invHtml.join(''), { status: 200, headers: { 'Content-Type': 'text/html' }, } ); } const addToInventory = async (userId: string, cardId: number, skuId: number, purchasePrice: number, quantity: number, note: string, catalogName: string) => { // First add to database const inv = await db.insert(inventory).values({ userId: userId, skuId: skuId, catalogName: catalogName, purchasePrice: purchasePrice.toFixed(2), quantity: quantity, note: note, }).returning(); // Get card details from the database to add to Typesense const card = await db.query.cards.findFirst({ where: { cardId: cardId }, with: { set: true }, }); try { // And then add to Typesense for searching await client.collections('inventories').documents().import(inv.map(i => ({ id: i.inventoryId, userId: i.userId, catalogName: i.catalogName, sku_id: i.skuId.toString(), purchasePrice: DollarToInt(i.purchasePrice), productLineName: card?.productLineName, rarityName: card?.rarityName, setName: card?.set?.setName || "", cardType: card?.cardType || "", energyType: card?.energyType || "", card_id: card?.cardId.toString() || "", content: [ card?.productName, card?.productLineName, card?.set?.setName || "", card?.number, card?.rarityName, card?.artist || "" ].join(' '), }))); } catch (error) { console.error('Error adding inventory to Typesense:', error); } } const removeFromInventory = async (inventoryId: string) => { await db.delete(inventory).where(eq(inventory.inventoryId, inventoryId)); await client.collections('inventories').documents(inventoryId).delete(); } const updateInventory = async (inventoryId: string, quantity: number, purchasePrice: number, note: string) => { // Update the database await db.update(inventory).set({ quantity: quantity, purchasePrice: purchasePrice.toFixed(2), note: note, }).where(eq(inventory.inventoryId, inventoryId)); // No need to update Typesense since we don't search by quantity or price } export const POST: APIRoute = async ({ request, locals }) => { // Access form data from the request body const formData = await request.formData(); const action = formData.get('action'); const cardId = Number(formData.get('cardId')) || 0; const { userId } = locals.auth(); switch (action) { case 'add': const purchasePrice = Number(formData.get('purchasePrice')) || 0; const quantity = Number(formData.get('quantity')) || 1; const note = formData.get('note')?.toString() || ''; const catalogName = formData.get('catalogName')?.toString() || 'Default'; const condition = formData.get('condition')?.toString() || 'Near Mint'; const skuId = await db.query.skus.findFirst({ where: { cardId: cardId, condition: condition }, columns: { skuId: true }, }).then(sku => sku?.skuId); if (!skuId) { return new Response('SKU not found for card', { status: 404 }); } await addToInventory(userId!, cardId, skuId, purchasePrice, quantity, note, catalogName); break; case 'remove': const inventoryId = formData.get('inventoryId')?.toString() || ''; await removeFromInventory(inventoryId); break; case 'update': const invId = formData.get('inventoryId')?.toString() || ''; const qty = Number(formData.get('quantity')) || 1; const price = Number(formData.get('purchasePrice')) || 0; const invNote = formData.get('note')?.toString() || ''; await updateInventory(invId, qty, price, invNote); break; default: // No action = list inventory for this card return getInventory(userId!, cardId); } // Always return current inventory after a mutation return getInventory(userId!, cardId); };