Step-by-step guide for customers submitting buylist orders through the customer portal.
Complete Submission Process
- Access Customer Portal: Navigate to the store's buylist customer portal (typically at a URL like buylist.[storename].com or embedded in store website)
- Search for Products: Use GET /api/buylist/search endpoint to find cards by name, set code, card number, or other filters
- Select Product: Click on a product to view details and available printings/conditions
- Get Pricing: System calls GET /api/buylist/get-price with productId, printing, condition, language, and storeId to fetch cash and credit prices for all conditions
- Add to Cart: Select condition, language, printing, quantity, and payment type (Cash, Credit, or Split)
- Review Cart: View all items with totals calculated based on payment types and split percentages
- Provide Customer Info: Enter customerName, customerEmail, customerPhone (optional), orderType (dropIn/delivery), paypalEmail (if delivery), customerAddress (if delivery), and orderNotes
- Submit Order: POST /api/buylist/submit-order with complete order data
- Receive Confirmation: Order created, orderId returned, confirmation email sent (if enabled)
Required Request Data
Required Fields:
• storeId: Store's unique identifier
• customerName: Customer's full name
• customerEmail: Customer's email address
• cart: Array of cart items (minimum 1 item required)
Optional Fields:
• customerPhone: Phone number
• orderType: 'dropIn' (default) or 'delivery'
• paypalEmail: Required if orderType='delivery'
• customerAddress: Required if orderType='delivery'
• orderNotes: Additional notes from customer
• totalCash: Pre-calculated total (system will recalculate)
• totalCredit: Pre-calculated total (system will recalculate)
Cart Item Structure
Required for Regular Items:
• productId: TCGPlayer product ID (number)
• condAbbr: Condition abbreviation (NM, LP, MP, HP, DM)
• langAbbr: Language abbreviation (EN, JP, FR, etc.)
• printing: Printing type (Normal, Foil, Holofoil, etc.)
• quantity: Number of copies (default: 1)
• paymentType: 'Cash', 'Credit', or 'Split'
• addedCashPrice: Price per unit for cash
• addedCreditPrice: Price per unit for credit
Optional Fields:
• splitPercentage: Percentage for cash (0-100) when paymentType='Split' (default: 50)
• notes: Item-specific notes
• isCustomItem: Boolean flag for custom items
• customItemData: Object with baseDescription, baseQuantity, userQuantity, baseCashPrice, baseCreditPrice (for custom items)
Server-Side Processing Steps
- Validation: Server validates storeId exists, customerName and customerEmail are present, cart is non-empty array
- Store Lookup: Finds UserModel by buylistConfig.storeId. Returns 404 if store not found or config missing
- Product Hydration: For regular items (not isCustomItem), fetches ProductModel records to populate cleanName, categoryId, groupId, number, groupName
- Split Normalization: For items with paymentType='Split', ensures splitPercentage is number (defaults to 50 if missing)
- Total Calculation: Computes computedTotalCash and computedTotalCredit by iterating cart:
- Cash items: addedCashPrice × quantity
- Credit items: addedCreditPrice × quantity
- Split items: (addedCashPrice × quantity × splitPercentage%) + (addedCreditPrice × quantity × (100-splitPercentage)%)
- Budget Validation: If budgetsEnabled in store config, validates totals against remaining cash/credit budgets. Auto-adjusts payment types if one budget exhausted but other has capacity
- CSV Generation: Creates CSV file with columns: ProductId, TCGplayer Id, Name, Set, Number, Condition, Language, Printing, Quantity, CashPrice, CreditPrice, Notes
- Status Determination: Sets initial status based on:
- POS buys: Uses req.body.status or defaults to 'approved'
- Customer orders: Uses buylistConfig.defaultOrderStatus if set, otherwise checks autoApprove flag (true = 'approved', false = 'pending_approval')
- Order Creation: Creates BuylistOrder document with all fields, initial statusHistory entry, and system message: "Buylist order created with X items"
- Auto-Approval Handling: If status='approved', adds "Order auto-approved" message and sends customer approval email with store address
- Email Notifications: Sends two emails (if emailsEnabled !== false):
- Store owner: HTML table with all items, CSV attachment, subject: "[StoreName] - New Buylist Order from [CustomerName]"
- Customer: HTML table confirmation, subject: "Buylist Confirmation - [StoreName]"
- Budget Update: If budgetsEnabled, increments cashBudgetUsed and creditBudgetUsed fields in UserModel
- Response: Returns JSON with success: true, message, and orderId
Getting Prices for Cart Items
Before adding items to cart, customers should fetch prices using GET /api/buylist/get-price with query parameters:
- productId: Required - TCGPlayer product ID
- printing: Required - Printing type (Normal, Foil, etc.)
- condition: Optional - Condition abbreviation (NM, LP, MP, HP, DM)
- language: Optional - Language abbreviation (default: EN)
- storeId: Optional - Store ID for store-specific pricing
Response includes:
• price.directLowPrice, lowPrice, midPrice, marketPrice, highPrice (raw TCGPlayer prices)
• price.NMFinalCash, NMFinalCredit (Near Mint prices)
• price.LPFinalCash, LPFinalCredit (Lightly Played prices)
• price.MPFinalCash, MPFinalCredit (Moderately Played prices)
• price.HPFinalCash, HPFinalCredit (Heavily Played prices)
• price.DMFinalCash, DMFinalCredit (Damaged prices)
• price.logs: Array of step-by-step pricing calculation logs (if debug mode)
Bulk Pricing: For multiple items, use POST /api/buylist/get-price/bulk with body containing array of {productId, printing, condition, language} objects. Returns array of price objects.
Getting Available Printings
Before displaying condition/printing options, fetch available printings using GET /api/buylist/available-printings?productId=[id]. Returns array of available printing objects with subTypeName and other metadata.
For bulk operations, use GET /api/buylist/available-printings/bulk?productIds=[id1,id2,id3] or POST /api/buylist/get-price/bulk to get both prices and printings together.
Error Handling
- 400 Bad Request: Missing storeId, customerName, customerEmail, or empty cart
- 404 Not Found: Store not found for storeId, or store configuration missing
- 400 Budget Error: If both cash and credit budgets exhausted, returns error with cashRemaining and creditRemaining values
- 500 Server Error: Product not found for productId, database errors, email sending failures
Successful Response
{
"success": true,
"message": "Buylist order submitted successfully!",
"orderId": "507f1f77bcf86cd799439011"
}
The orderId can be used to view order status via GET /api/buylist/public/orders/:orderId (no auth required, uses email verification).