134 lines
4.5 KiB
JavaScript
134 lines
4.5 KiB
JavaScript
|
|
/**
|
||
|
|
* 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',
|
||
|
|
};
|
||
|
|
}
|