api-v1/routes/locationRoutes.js

201 lines
5.6 KiB
JavaScript

import express from "express";
import { insert, select, update, execute } from "../db/queryHelper/index.js";
const router = express.Router();
// 1. CREATE Location
router.post("/", async (req, res) => {
try {
const {
user_id,
lat,
lng,
source_type,
source_confidence,
selected_location,
is_saved_address,
location_type,
country,
state,
district,
city_village,
pincode,
} = req.body;
// Validate user exists if this is a saved address
let finalUserId = user_id;
if (is_saved_address && user_id) {
const userCheck = await select({
table: 'users',
columns: ['id'],
where: { id: user_id, deleted: false },
limit: 1
});
if (userCheck.length === 0) {
return res.status(400).json({
error: `User with id ${user_id} does not exist. Cannot create saved address for non-existent user.`
});
}
} else if (!is_saved_address) {
// For captured locations (not saved addresses), user_id can be NULL
finalUserId = null;
} else if (is_saved_address && !user_id) {
return res.status(400).json({
error: "user_id is required when is_saved_address is true"
});
}
// Insert into locations
const locationData = {
user_id: finalUserId,
lat,
lng,
source_type: source_type || "manual",
source_confidence: source_confidence || "low",
selected_location: selected_location || false,
is_saved_address: is_saved_address || false,
location_type: location_type || "other",
country,
state,
district,
city_village,
pincode,
};
const locationResult = await insert({
table: 'locations',
data: locationData,
returning: '*'
});
res.status(201).json(locationResult);
} catch (err) {
console.error("Error creating location:", err);
// Provide more specific error messages
if (err.code === '23503') { // Foreign key violation
return res.status(400).json({
error: `Foreign key constraint violation: ${err.detail || 'The provided user_id does not exist in the users table.'}`
});
}
res.status(500).json({ error: err.message || "Internal server error" });
}
});
// 2. GET User Locations
router.get("/user/:userId", async (req, res) => {
try {
const { userId } = req.params;
const result = await select({
table: 'locations',
where: { user_id: userId, deleted: false },
orderBy: { column: 'created_at', direction: 'desc' }
});
res.json(result);
} catch (err) {
console.error("Error fetching user locations:", err);
res.status(500).json({ error: "Internal server error" });
}
});
// 3. GET Single Location
router.get("/:id", async (req, res) => {
try {
const { id } = req.params;
const result = await select({
table: 'locations',
where: { id, deleted: false },
limit: 1
});
if (result.length === 0) {
return res.status(404).json({ error: "Location not found" });
}
res.json(result[0]);
} catch (err) {
console.error("Error fetching location:", err);
res.status(500).json({ error: "Internal server error" });
}
});
// 4. UPDATE Location
router.put("/:id", async (req, res) => {
try {
const { id } = req.params;
const {
lat,
lng,
source_type,
source_confidence,
selected_location,
is_saved_address,
location_type,
country,
state,
district,
city_village,
pincode,
} = req.body;
// Use raw builder for COALESCE functionality
const result = await execute({
type: 'raw-builder',
handler: async (knex) => {
const updates = {};
if (lat !== undefined) updates.lat = knex.raw('COALESCE(?, lat)', [lat]);
if (lng !== undefined) updates.lng = knex.raw('COALESCE(?, lng)', [lng]);
if (source_type !== undefined) updates.source_type = knex.raw('COALESCE(?, source_type)', [source_type]);
if (source_confidence !== undefined) updates.source_confidence = knex.raw('COALESCE(?, source_confidence)', [source_confidence]);
if (selected_location !== undefined) updates.selected_location = knex.raw('COALESCE(?, selected_location)', [selected_location]);
if (is_saved_address !== undefined) updates.is_saved_address = knex.raw('COALESCE(?, is_saved_address)', [is_saved_address]);
if (location_type !== undefined) updates.location_type = knex.raw('COALESCE(?, location_type)', [location_type]);
if (country !== undefined) updates.country = knex.raw('COALESCE(?, country)', [country]);
if (state !== undefined) updates.state = knex.raw('COALESCE(?, state)', [state]);
if (district !== undefined) updates.district = knex.raw('COALESCE(?, district)', [district]);
if (city_village !== undefined) updates.city_village = knex.raw('COALESCE(?, city_village)', [city_village]);
if (pincode !== undefined) updates.pincode = knex.raw('COALESCE(?, pincode)', [pincode]);
return await knex('locations')
.where({ id, deleted: false })
.update(updates)
.returning('*');
}
});
if (result.length === 0) {
return res.status(404).json({ error: "Location not found" });
}
res.json(result[0]);
} catch (err) {
console.error("Error updating location:", err);
res.status(500).json({ error: "Internal server error" });
}
});
// 5. DELETE Location
router.delete("/:id", async (req, res) => {
try {
const { id } = req.params;
const result = await update({
table: 'locations',
data: { deleted: true },
where: { id },
returning: ['id']
});
if (result.length === 0) {
return res.status(404).json({ error: "Location not found" });
}
res.json({ message: "Location deleted successfully" });
} catch (err) {
console.error("Error deleting location:", err);
res.status(500).json({ error: "Internal server error" });
}
});
export default router;