Backend features: - Express.js API server - Supabase database integration - Stripe Checkout for payments ($249 kit + $9.99/mo premium) - Stripe webhooks for payment events - Admin panel with order management - Auth middleware with JWT - Email service via Brevo API endpoints: - /api/stripe/* - Payment processing - /api/webhook/stripe - Stripe webhooks - /api/admin/* - Admin operations - /function/well-api/api - Legacy API proxy Database migrations: - orders, subscriptions, push_tokens tables Schemes updated: - Removed updatedAt from all schemes - Updated credentials section with live values - Added Stripe configuration details 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
231 lines
5.7 KiB
JavaScript
231 lines
5.7 KiB
JavaScript
const { supabase } = require('../config/supabase');
|
|
|
|
// POST: device_list
|
|
exports.list = async (req, res) => {
|
|
const { user_name, token, first = 0, last = 100 } = req.body;
|
|
|
|
try {
|
|
const { data, error, count } = await supabase
|
|
.from('devices')
|
|
.select('*', { count: 'exact' })
|
|
.range(parseInt(first), parseInt(last) - 1)
|
|
.order('device_id', { ascending: true });
|
|
|
|
if (error) throw error;
|
|
|
|
return res.json({
|
|
devices: data,
|
|
total: count
|
|
});
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: device_list_4_gui
|
|
exports.listForGui = async (req, res) => {
|
|
// Same as list but may have different formatting
|
|
return exports.list(req, res);
|
|
};
|
|
|
|
// POST: device_list_by_deployment
|
|
exports.listByDeployment = async (req, res) => {
|
|
const { user_name, token, deployment_id, first = 0, last = 100 } = req.body;
|
|
|
|
try {
|
|
const { data, error } = await supabase
|
|
.from('devices')
|
|
.select('*')
|
|
.eq('deployment_id', deployment_id)
|
|
.range(parseInt(first), parseInt(last) - 1)
|
|
.order('device_id', { ascending: true });
|
|
|
|
if (error) throw error;
|
|
return res.json(data);
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: get_device
|
|
exports.get = async (req, res) => {
|
|
const { user_name, token, device_id, mac } = req.body;
|
|
|
|
try {
|
|
let query = supabase.from('devices').select('*');
|
|
|
|
if (device_id) {
|
|
query = query.eq('device_id', device_id);
|
|
} else if (mac) {
|
|
query = query.eq('mac', mac);
|
|
}
|
|
|
|
const { data, error } = await query.single();
|
|
|
|
if (error) throw error;
|
|
return res.json(data);
|
|
} catch (error) {
|
|
return res.status(404).json({ error: 'Device not found' });
|
|
}
|
|
};
|
|
|
|
// POST: device_form - create/update device
|
|
exports.form = async (req, res) => {
|
|
const {
|
|
user_name, token,
|
|
well_id, device_mac, description, location, close_to,
|
|
radar_threshold, temperature_calib, humidity_calib, group
|
|
} = req.body;
|
|
|
|
try {
|
|
const deviceData = {
|
|
well_id,
|
|
mac: device_mac,
|
|
description,
|
|
location,
|
|
close_to,
|
|
radar_threshold: parseFloat(radar_threshold) || null,
|
|
temperature_calib: parseFloat(temperature_calib) || null,
|
|
humidity_calib: parseFloat(humidity_calib) || null,
|
|
group_id: parseInt(group) || null,
|
|
time_edit: Date.now() / 1000
|
|
};
|
|
|
|
// Upsert by MAC address
|
|
const { data, error } = await supabase
|
|
.from('devices')
|
|
.upsert(deviceData, { onConflict: 'mac' })
|
|
.select()
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
return res.json({ success: true, device: data });
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: device_set_group
|
|
exports.setGroup = async (req, res) => {
|
|
const { user_name, token, device_id, group_id } = req.body;
|
|
|
|
try {
|
|
const { error } = await supabase
|
|
.from('devices')
|
|
.update({ group_id: parseInt(group_id) })
|
|
.eq('device_id', device_id);
|
|
|
|
if (error) throw error;
|
|
return res.json({ success: true });
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: device_get_live
|
|
exports.getLive = async (req, res) => {
|
|
const { user_name, token, device_id, mac } = req.body;
|
|
|
|
// TODO: Implement live data fetching from device
|
|
return res.json({
|
|
success: true,
|
|
live_data: null,
|
|
message: 'Live data not available'
|
|
});
|
|
};
|
|
|
|
// POST: device_reboot
|
|
exports.reboot = async (req, res) => {
|
|
const { user_name, token, device_id, mac } = req.body;
|
|
|
|
// TODO: Implement device reboot command
|
|
return res.json({
|
|
success: true,
|
|
message: 'Reboot command sent'
|
|
});
|
|
};
|
|
|
|
// POST: device_set_well_id
|
|
exports.setWellId = async (req, res) => {
|
|
const { user_name, token, device_id, well_id, mac } = req.body;
|
|
|
|
try {
|
|
let query = supabase.from('devices').update({ well_id });
|
|
|
|
if (device_id) {
|
|
query = query.eq('device_id', device_id);
|
|
} else if (mac) {
|
|
query = query.eq('mac', mac);
|
|
}
|
|
|
|
const { error } = await query;
|
|
|
|
if (error) throw error;
|
|
return res.json({ success: true });
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: device_set_network_id
|
|
exports.setNetworkId = async (req, res) => {
|
|
const { user_name, token, device_id, well_id } = req.body;
|
|
|
|
try {
|
|
const { error } = await supabase
|
|
.from('devices')
|
|
.update({ network_id: well_id })
|
|
.eq('device_id', device_id);
|
|
|
|
if (error) throw error;
|
|
return res.json({ success: true });
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: request_devices
|
|
exports.requestDevices = async (req, res) => {
|
|
const { user_name, token, group_id, deployment_id, location, fresh } = req.body;
|
|
|
|
try {
|
|
let query = supabase.from('devices').select('*');
|
|
|
|
if (deployment_id) {
|
|
query = query.eq('deployment_id', deployment_id);
|
|
}
|
|
if (group_id) {
|
|
query = query.eq('group_id', group_id);
|
|
}
|
|
if (location) {
|
|
query = query.eq('location', location);
|
|
}
|
|
|
|
const { data, error } = await query;
|
|
|
|
if (error) throw error;
|
|
return res.json(data);
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// POST: get_devices_locations
|
|
exports.getLocations = async (req, res) => {
|
|
const { user_name, token, well_ids } = req.body;
|
|
|
|
try {
|
|
const ids = well_ids.split(',').map(id => id.trim());
|
|
|
|
const { data, error } = await supabase
|
|
.from('devices')
|
|
.select('device_id, well_id, location, lat, lng')
|
|
.in('well_id', ids);
|
|
|
|
if (error) throw error;
|
|
return res.json(data);
|
|
} catch (error) {
|
|
return res.status(500).json({ error: error.message });
|
|
}
|
|
};
|