/** * NocoDB Order Mapper * Maps Stripe Checkout Session data to NocoDB OrderRecord format */ /** * Map Stripe session data to NocoDB OrderRecord format * @param {Object} session - Stripe checkout session object * @param {Object} order - Local database order object * @returns {Object} NocoDB-compatible order record */ export function mapStripeSessionToNocoDBOrder(session, order) { const metadata = session.metadata || {}; const customerDetails = session.customer_details || {}; const address = customerDetails.address || {}; const taxIds = customerDetails.tax_ids || []; return { // Order identification orderId: order.id, status: 'paid', // Will be updated to 'fulfilled' after Wren order source: determineOrderSource(session), // Payment information stripeSessionId: session.id, stripePaymentIntent: session.payment_intent || null, stripeCustomerId: session.customer || null, baseAmount: metadata.baseAmount || order.base_amount?.toString() || '0', processingFee: metadata.processingFee || order.processing_fee?.toString() || '0', totalAmount: session.amount_total?.toString() || order.total_amount?.toString() || '0', currency: session.currency?.toUpperCase() || order.currency || 'USD', amountUSD: calculateUSDAmount(session.amount_total, session.currency), paymentMethod: session.payment_method_types?.[0] || null, // Carbon offset details co2Tons: metadata.tons || order.tons?.toString() || '0', portfolioId: metadata.portfolioId || order.portfolio_id?.toString() || '', portfolioName: null, // Will be populated later from Wren API wrenOrderId: null, // Will be populated after fulfillment certificateUrl: null, // Will be populated after fulfillment fulfilledAt: null, // Will be set when order is fulfilled // Customer information customerName: customerDetails.name || 'Unknown', customerEmail: customerDetails.email || order.customer_email || '', customerPhone: customerDetails.phone || null, businessName: customerDetails.business_name || null, taxIdType: taxIds[0]?.type || null, taxIdValue: taxIds[0]?.value || null, // Billing address billingLine1: address.line1 || null, billingLine2: address.line2 || null, billingCity: address.city || null, billingState: address.state || null, billingPostalCode: address.postal_code || null, billingCountry: address.country || null, // Vessel information (from metadata or order, if available) vesselName: metadata.vesselName || order.vessel_name || null, imoNumber: metadata.imoNumber || order.imo_number || null, vesselType: metadata.vesselType || null, vesselLength: metadata.vesselLength || null, // Trip details (from metadata, if available) departurePort: metadata.departurePort || null, arrivalPort: metadata.arrivalPort || null, distance: metadata.distance || null, avgSpeed: metadata.avgSpeed || null, duration: metadata.duration || null, enginePower: metadata.enginePower || null, // Administrative notes: null, }; } /** * Determine order source from session data * @param {Object} session - Stripe checkout session object * @returns {string} Order source */ function determineOrderSource(session) { const metadata = session.metadata || {}; // Check if source is specified in metadata if (metadata.source) { return metadata.source; } // Check success URL for mobile app indicator if (session.success_url?.includes('mobile-app')) { return 'mobile-app'; } // Default to web return 'web'; } /** * Calculate USD amount for reporting * @param {number} amount - Amount in cents * @param {string} currency - Currency code * @returns {string} USD amount in cents */ function calculateUSDAmount(amount, currency) { if (!amount) return '0'; // If already USD, return as-is if (currency?.toLowerCase() === 'usd') { return amount.toString(); } // TODO: Implement currency conversion using real-time rates // For now, return the original amount // In production, fetch rates from an API or use a conversion service return amount.toString(); } /** * Update NocoDB order with Wren fulfillment data * @param {string} orderId - Order ID * @param {Object} wrenOrder - Wren API order response * @returns {Object} Update data for NocoDB */ export function mapWrenFulfillmentData(orderId, wrenOrder) { return { wrenOrderId: wrenOrder.id, certificateUrl: wrenOrder.certificate_url || null, fulfilledAt: new Date().toISOString(), status: 'fulfilled', }; }