161 lines
4.6 KiB
JavaScript

const geocoding = require('../services/geocoding');
const db = require('../models/db');
const logger = require('../utils/logger');
async function geocodeAddress(req, res) {
try {
const { address } = req.query;
if (!address) {
return res.status(400).json({ error: 'Address parameter required' });
}
const result = await geocoding.forwardGeocode(address);
res.json({
success: true,
result: {
latitude: result.latitude,
longitude: result.longitude,
formattedAddress: result.formattedAddress,
provider: result.provider,
confidence: result.confidence
}
});
} catch (error) {
logger.error('Geocoding failed', { error: error.message });
res.status(500).json({
success: false,
error: error.message
});
}
}
async function reverseGeocode(req, res) {
try {
const { lat, lng } = req.query;
if (!lat || !lng) {
return res.status(400).json({ error: 'lat and lng parameters required' });
}
const latitude = parseFloat(lat);
const longitude = parseFloat(lng);
if (isNaN(latitude) || isNaN(longitude)) {
return res.status(400).json({ error: 'Invalid coordinates' });
}
const result = await geocoding.reverseGeocode(latitude, longitude);
res.json({
success: true,
result: {
formattedAddress: result.formattedAddress,
components: result.components,
latitude: result.latitude,
longitude: result.longitude
}
});
} catch (error) {
logger.error('Reverse geocoding failed', { error: error.message });
res.status(500).json({
success: false,
error: error.message
});
}
}
async function regeocodeResource(req, res) {
try {
const { id } = req.params;
// Get the resource
const resourceResult = await db.query(
'SELECT id, name, address, city, postal_code FROM food_resources WHERE id = $1',
[id]
);
if (resourceResult.rows.length === 0) {
return res.status(404).json({ success: false, error: 'Resource not found' });
}
const resource = resourceResult.rows[0];
// Build address string
let addressToGeocode;
let hasStreetAddress = false;
if (resource.address && !resource.address.startsWith('PO Box') && resource.address.trim() !== '') {
addressToGeocode = `${resource.address}, ${resource.city}, Alberta, Canada`;
hasStreetAddress = true;
} else if (resource.postal_code && resource.postal_code.trim() !== '') {
addressToGeocode = `${resource.city}, ${resource.postal_code}, Alberta, Canada`;
} else if (resource.city) {
addressToGeocode = `${resource.city}, Alberta, Canada`;
} else {
return res.status(400).json({ success: false, error: 'Resource has no address or city to geocode' });
}
logger.info(`Re-geocoding resource ${id}: ${resource.name}`, { address: addressToGeocode });
const geocodeResult = await geocoding.forwardGeocode(addressToGeocode);
if (!geocodeResult || !geocodeResult.latitude || !geocodeResult.longitude) {
return res.status(400).json({ success: false, error: 'Could not geocode address' });
}
const confidence = geocodeResult.combinedConfidence || geocodeResult.confidence || 50;
const provider = geocodeResult.provider || 'unknown';
const warnings = geocodeResult.validation?.warnings || [];
// Adjust confidence if no street address was provided
const adjustedConfidence = hasStreetAddress ? confidence : Math.min(confidence, 40);
// Update the database
await db.query(`
UPDATE food_resources
SET latitude = $1,
longitude = $2,
geocode_confidence = $3,
geocode_provider = $4,
updated_at = NOW()
WHERE id = $5
`, [geocodeResult.latitude, geocodeResult.longitude, adjustedConfidence, provider, id]);
logger.info(`Re-geocoded resource ${id} successfully`, {
latitude: geocodeResult.latitude,
longitude: geocodeResult.longitude,
confidence: adjustedConfidence,
provider
});
res.json({
success: true,
result: {
latitude: geocodeResult.latitude,
longitude: geocodeResult.longitude,
confidence: adjustedConfidence,
provider,
warnings,
formattedAddress: geocodeResult.formattedAddress
}
});
} catch (error) {
logger.error('Re-geocoding failed', { error: error.message, id: req.params.id });
res.status(500).json({
success: false,
error: error.message
});
}
}
module.exports = {
geocodeAddress,
reverseGeocode,
regeocodeResource
};