161 lines
4.6 KiB
JavaScript
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
|
|
};
|