E-Commerce-Module/backend/src/routes/shipping.js
2025-04-27 13:22:18 -05:00

179 lines
No EOL
4.6 KiB
JavaScript

const express = require('express');
const router = express.Router();
const shippingService = require('../services/shippingService.js');
const config = require('../config');
module.exports = (pool, query, authMiddleware) => {
// Apply authentication middleware to all routes
router.use(authMiddleware);
/**
* Get shipping rates
* POST /api/shipping/rates
*
* Request Body:
* {
* address: {
* name: string,
* street: string,
* city: string,
* state: string,
* zip: string,
* country: string,
* email: string
* },
* parcel: {
* length: number,
* width: number,
* height: number,
* weight: number,
* order_total: number
* },
* items: [{ id, quantity, weight_grams }] // Optional cart items for weight calculation
* }
*/
router.post('/rates', async (req, res, next) => {
try {
const { address, parcel, items } = req.body;
// Shipping must be enabled
if (!config.shipping.enabled) {
return res.status(400).json({
error: true,
message: 'Shipping is currently disabled'
});
}
// Validate required fields
if (!address || !parcel) {
return res.status(400).json({
error: true,
message: 'Address and parcel information are required'
});
}
// If address is a string, parse it
const parsedAddress = typeof address === 'string'
? shippingService.parseAddressString(address)
: address;
// Calculate total weight if items are provided
if (items && items.length > 0) {
parcel.weight = shippingService.calculateTotalWeight(items);
}
// Get shipping rates
const rates = await shippingService.getShippingRates(
null, // Use default from config
parsedAddress,
{
...parcel,
order_total: parcel.order_total || 0
}
);
res.json({
success: true,
rates
});
} catch (error) {
console.error('Error getting shipping rates:', error);
next(error);
}
});
/**
* Validate shipping address
* POST /api/shipping/validate-address
*
* Request Body:
* {
* address: {
* name: string,
* street: string,
* city: string,
* state: string,
* zip: string,
* country: string,
* email: string
* }
* }
*/
router.post('/validate-address', async (req, res, next) => {
try {
const { address } = req.body;
// Shipping must be enabled
if (!config.shipping.enabled) {
return res.status(400).json({
error: true,
message: 'Shipping is currently disabled'
});
}
// Validate required fields
if (!address) {
return res.status(400).json({
error: true,
message: 'Address information is required'
});
}
// If EasyPost is not enabled, just perform basic validation
if (!config.shipping.easypostEnabled || !config.shipping.easypostApiKey) {
const isValid = validateAddressFormat(address);
return res.json({
success: true,
valid: isValid,
original_address: address,
verified_address: address
});
}
// If address is a string, parse it
const parsedAddress = typeof address === 'string'
? shippingService.parseAddressString(address)
: address;
// TODO: Implement EasyPost address verification
// This would require making a call to EasyPost's API
// For now, we'll return the original address
res.json({
success: true,
valid: true,
original_address: parsedAddress,
verified_address: parsedAddress
});
} catch (error) {
console.error('Error validating address:', error);
next(error);
}
});
return router;
};
/**
* Basic address format validation
* @param {Object} address - Address to validate
* @returns {boolean} Whether the address has valid format
*/
function validateAddressFormat(address) {
// Check required fields
if (!address.street || !address.city || !address.zip || !address.country) {
return false;
}
// Check zip code format - just basic validation
if (address.country === 'US' && !/^\d{5}(-\d{4})?$/.test(address.zip)) {
return false;
}
if (address.country === 'CA' && !/^[A-Za-z]\d[A-Za-z] \d[A-Za-z]\d$/.test(address.zip)) {
return false;
}
return true;
}