From ea691536ac5bb9330d0ac2413a1dedfd5e6facef Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Jun 2025 18:49:25 +0300 Subject: [PATCH] add db api --- .../sber_mobile/additional_services.js | 56 ++++++++++++ .../kfu-m-24-1/sber_mobile/apartments.js | 14 +++ .../kfu-m-24-1/sber_mobile/buildings.js | 14 +++ .../routers/kfu-m-24-1/sber_mobile/cameras.js | 28 ++++++ .../routers/kfu-m-24-1/sber_mobile/chats.js | 28 ++++++ .../routers/kfu-m-24-1/sber_mobile/index.js | 26 +++++- .../kfu-m-24-1/sber_mobile/initiatives.js | 90 +++++++++++++++++++ .../kfu-m-24-1/sber_mobile/messages.js | 14 +++ .../routers/kfu-m-24-1/sber_mobile/profile.js | 14 +++ .../routers/kfu-m-24-1/sber_mobile/tickets.js | 14 +++ .../kfu-m-24-1/sber_mobile/user_apartments.js | 18 ++++ .../sber_mobile/utility_payments.js | 17 ++++ .../routers/kfu-m-24-1/sber_mobile/votes.js | 44 +++++++++ 13 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 server/routers/kfu-m-24-1/sber_mobile/additional_services.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/apartments.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/buildings.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/cameras.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/chats.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/initiatives.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/messages.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/tickets.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/user_apartments.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/utility_payments.js create mode 100644 server/routers/kfu-m-24-1/sber_mobile/votes.js diff --git a/server/routers/kfu-m-24-1/sber_mobile/additional_services.js b/server/routers/kfu-m-24-1/sber_mobile/additional_services.js new file mode 100644 index 0000000..1861a60 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/additional_services.js @@ -0,0 +1,56 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все дополнительные сервисы (по УК) +router.get('/additional-services', async (req, res) => { + const supabase = getSupabaseClient(); + const { management_company_id } = req.query; + let query = supabase.from('additional_services').select('*'); + if (management_company_id) query = query.eq('management_company_id', management_company_id); + const { data, error } = await query; + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить сервис по id +router.get('/additional-services/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { data, error } = await supabase.from('additional_services').select('*').eq('id', id).single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Создать сервис +router.post('/additional-services', async (req, res) => { + const supabase = getSupabaseClient(); + const { title, description, category, price, image_url } = req.body; + const { data, error } = await supabase.from('additional_services').insert([ + { title, description, category, price, image_url } + ]).select().single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Обновить сервис +router.put('/additional-services/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { title, description, category, price, image_url } = req.body; + const { data, error } = await supabase.from('additional_services').update({ + title, description, category, price, image_url + }).eq('id', id).select().single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Удалить сервис +router.delete('/additional-services/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { error } = await supabase.from('additional_services').delete().eq('id', id); + if (error) return res.status(400).json({ error: error.message }); + res.json({ success: true }); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/apartments.js b/server/routers/kfu-m-24-1/sber_mobile/apartments.js new file mode 100644 index 0000000..5182e78 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/apartments.js @@ -0,0 +1,14 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все квартиры по дому +router.get('/apartments', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + if (!building_id) return res.status(400).json({ error: 'building_id required' }); + const { data, error } = await supabase.from('apartments').select('*').eq('building_id', building_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/buildings.js b/server/routers/kfu-m-24-1/sber_mobile/buildings.js new file mode 100644 index 0000000..8230923 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/buildings.js @@ -0,0 +1,14 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все дома по УК +router.get('/buildings', async (req, res) => { + const supabase = getSupabaseClient(); + const { management_company_id } = req.query; + if (!management_company_id) return res.status(400).json({ error: 'management_company_id required' }); + const { data, error } = await supabase.from('buildings').select('*').eq('management_company_id', management_company_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/cameras.js b/server/routers/kfu-m-24-1/sber_mobile/cameras.js new file mode 100644 index 0000000..1425b9f --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/cameras.js @@ -0,0 +1,28 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все камеры по дому +router.get('/cameras', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + if (!building_id) return res.status(400).json({ error: 'building_id required' }); + const { data, error } = await supabase.from('cameras').select('*').eq('building_id', building_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить все камеры по квартире (через building_id) +router.get('/cameras/by-apartment', async (req, res) => { + const supabase = getSupabaseClient(); + const { apartment_id } = req.query; + if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' }); + // Получаем building_id квартиры и сразу камеры этого дома + const { data, error } = await supabase + .from('cameras') + .select('*, apartments!inner(id, building_id)') + .eq('apartments.id', apartment_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/chats.js b/server/routers/kfu-m-24-1/sber_mobile/chats.js new file mode 100644 index 0000000..983f0dd --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/chats.js @@ -0,0 +1,28 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все чаты по дому +router.get('/chats', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + if (!building_id) return res.status(400).json({ error: 'building_id required' }); + const { data, error } = await supabase.from('chats').select('*').eq('building_id', building_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить все чаты по квартире (через building_id) +router.get('/chats/by-apartment', async (req, res) => { + const supabase = getSupabaseClient(); + const { apartment_id } = req.query; + if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' }); + // Получаем building_id квартиры и сразу чаты этого дома + const { data, error } = await supabase + .from('chats') + .select('*, apartments!inner(id, building_id)') + .eq('apartments.id', apartment_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/index.js b/server/routers/kfu-m-24-1/sber_mobile/index.js index f8dd26f..5c4af66 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/index.js +++ b/server/routers/kfu-m-24-1/sber_mobile/index.js @@ -2,9 +2,33 @@ const router = require('express').Router(); const authRouter = require('./auth'); const { supabaseRouter } = require('./supabaseClient'); const profileRouter = require('./profile'); +const initiativesRouter = require('./initiatives'); +const votesRouter = require('./votes'); +const paymentServicesRouter = require('./payment_services'); +const additionalServicesRouter = require('./additional_services'); +const chatsRouter = require('./chats'); +const camerasRouter = require('./cameras'); +const ticketsRouter = require('./tickets'); +const messagesRouter = require('./messages'); +const utilityPaymentsRouter = require('./utility_payments'); +const apartmentsRouter = require('./apartments'); +const buildingsRouter = require('./buildings'); +const userApartmentsRouter = require('./user_apartments'); module.exports = router; router.use('/auth', authRouter); router.use('/supabase', supabaseRouter); -router.use('', profileRouter); \ No newline at end of file +router.use('', profileRouter); +router.use('', initiativesRouter); +router.use('', votesRouter); +router.use('', paymentServicesRouter); +router.use('', additionalServicesRouter); +router.use('', chatsRouter); +router.use('', camerasRouter); +router.use('', ticketsRouter); +router.use('', messagesRouter); +router.use('', utilityPaymentsRouter); +router.use('', apartmentsRouter); +router.use('', buildingsRouter); +router.use('', userApartmentsRouter); \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/initiatives.js b/server/routers/kfu-m-24-1/sber_mobile/initiatives.js new file mode 100644 index 0000000..4e0469b --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/initiatives.js @@ -0,0 +1,90 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все инициативы (по дому) +router.get('/initiatives', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + let query = supabase.from('initiatives').select('*'); + if (building_id) query = query.eq('building_id', building_id); + const { data, error } = await query; + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить инициативу по id (и optionally building_id) +router.get('/initiatives/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { building_id } = req.query; + let query = supabase.from('initiatives').select('*').eq('id', id); + if (building_id) query = query.eq('building_id', building_id); + const { data, error } = await query.single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Создать инициативу +router.post('/initiatives', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id, creator_id, title, description, status, target_amount, image_url } = req.body; + const { data, error } = await supabase.from('initiatives').insert([ + { building_id, creator_id, title, description, status, target_amount, image_url } + ]).select().single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Обновить инициативу +router.put('/initiatives/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { title, description, status, target_amount, current_amount, image_url } = req.body; + const { data, error } = await supabase.from('initiatives').update({ + title, description, status, target_amount, current_amount, image_url + }).eq('id', id).select().single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Удалить инициативу +router.delete('/initiatives/:id', async (req, res) => { + const supabase = getSupabaseClient(); + const { id } = req.params; + const { error } = await supabase.from('initiatives').delete().eq('id', id); + if (error) return res.status(400).json({ error: error.message }); + res.json({ success: true }); +}); + +// Получить все инициативы по квартире с голосами пользователя +router.get('/initiatives/by-apartment', async (req, res) => { + const supabase = getSupabaseClient(); + const { apartment_id, user_id } = req.query; + if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' }); + // Получаем building_id квартиры + const { data: apartments, error: err1 } = await supabase + .from('apartments') + .select('building_id') + .eq('id', apartment_id) + .single(); + if (err1) return res.status(400).json({ error: err1.message }); + const building_id = apartments.building_id; + // Получаем инициативы этого дома с голосами пользователя (если user_id передан) + let selectStr = '*, votes:initiatives(id, votes!left(user_id, vote_type))'; + if (!user_id) selectStr = '*'; + const { data, error } = await supabase + .from('initiatives') + .select(selectStr) + .eq('building_id', building_id); + if (error) return res.status(400).json({ error: error.message }); + // Если user_id передан, фильтруем только голос текущего пользователя + if (user_id && data) { + data.forEach(initiative => { + initiative.user_vote = (initiative.votes || []).find(v => v.user_id === user_id) || null; + delete initiative.votes; + }); + } + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/messages.js b/server/routers/kfu-m-24-1/sber_mobile/messages.js new file mode 100644 index 0000000..b1a8188 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/messages.js @@ -0,0 +1,14 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все сообщения в чате +router.get('/messages', async (req, res) => { + const supabase = getSupabaseClient(); + const { chat_id } = req.query; + if (!chat_id) return res.status(400).json({ error: 'chat_id required' }); + const { data, error } = await supabase.from('messages').select('*').eq('chat_id', chat_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/profile.js b/server/routers/kfu-m-24-1/sber_mobile/profile.js index cb4612a..09c97c6 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/profile.js +++ b/server/routers/kfu-m-24-1/sber_mobile/profile.js @@ -51,4 +51,18 @@ router.post('/profile', async (req, res) => { res.json({ success: true }); }); +// Получить управляющую компанию по квартире +router.get('/management-company', async (req, res) => { + const supabase = getSupabaseClient(); + const { apartment_id } = req.query; + if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' }); + const { data: apartment, error: err1 } = await supabase.from('apartments').select('building_id').eq('id', apartment_id).single(); + if (err1) return res.status(400).json({ error: err1.message }); + const { data: building, error: err2 } = await supabase.from('buildings').select('management_company_id').eq('id', apartment.building_id).single(); + if (err2) return res.status(400).json({ error: err2.message }); + const { data: company, error: err3 } = await supabase.from('management_companies').select('*').eq('id', building.management_company_id).single(); + if (err3) return res.status(400).json({ error: err3.message }); + res.json(company); +}); + module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/tickets.js b/server/routers/kfu-m-24-1/sber_mobile/tickets.js new file mode 100644 index 0000000..5ff082d --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/tickets.js @@ -0,0 +1,14 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все тикеты по дому +router.get('/tickets', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + if (!building_id) return res.status(400).json({ error: 'building_id required' }); + const { data, error } = await supabase.from('tickets').select('*').eq('building_id', building_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/user_apartments.js b/server/routers/kfu-m-24-1/sber_mobile/user_apartments.js new file mode 100644 index 0000000..e5421ba --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/user_apartments.js @@ -0,0 +1,18 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все квартиры пользователя +router.get('/user-apartments', async (req, res) => { + const supabase = getSupabaseClient(); + const { user_id } = req.query; + if (!user_id) return res.status(400).json({ error: 'user_id required' }); + const { data: links, error: err1 } = await supabase.from('apartment_residents').select('apartment_id').eq('user_id', user_id); + if (err1) return res.status(400).json({ error: err1.message }); + const apartmentIds = links.map(l => l.apartment_id); + if (!apartmentIds.length) return res.json([]); + const { data, error } = await supabase.from('apartments').select('*').in('id', apartmentIds); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js b/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js new file mode 100644 index 0000000..a6e8b98 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js @@ -0,0 +1,17 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все платежи по конкретной квартире с данными сервиса +router.get('/utility-payments', async (req, res) => { + const supabase = getSupabaseClient(); + const { apartment_id } = req.query; + if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' }); + const { data, error } = await supabase + .from('utility_payments') + .select('*, payment_services(*)') + .eq('apartment_id', apartment_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file diff --git a/server/routers/kfu-m-24-1/sber_mobile/votes.js b/server/routers/kfu-m-24-1/sber_mobile/votes.js new file mode 100644 index 0000000..d46df22 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/votes.js @@ -0,0 +1,44 @@ +const router = require('express').Router(); +const { getSupabaseClient } = require('./supabaseClient'); + +// Получить все голоса по инициативе +router.get('/votes/:initiative_id', async (req, res) => { + const supabase = getSupabaseClient(); + const { initiative_id } = req.params; + const { data, error } = await supabase.from('votes').select('*').eq('initiative_id', initiative_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить голос пользователя по инициативе +router.get('/votes/:initiative_id/:user_id', async (req, res) => { + const supabase = getSupabaseClient(); + const { initiative_id, user_id } = req.params; + const { data, error } = await supabase.from('votes').select('*').eq('initiative_id', initiative_id).eq('user_id', user_id).single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Получить все голоса по инициативе (через query) +router.get('/votes', async (req, res) => { + const supabase = getSupabaseClient(); + const { initiative_id } = req.query; + if (!initiative_id) return res.status(400).json({ error: 'initiative_id required' }); + const { data, error } = await supabase.from('votes').select('*').eq('initiative_id', initiative_id); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +// Проголосовать (создать или обновить голос) +router.post('/votes', async (req, res) => { + const supabase = getSupabaseClient(); + const { initiative_id, user_id, vote_type } = req.body; + // upsert: если голос уже есть, обновить, иначе создать + const { data, error } = await supabase.from('votes').upsert([ + { initiative_id, user_id, vote_type } + ], { onConflict: ['initiative_id', 'user_id'] }).select().single(); + if (error) return res.status(400).json({ error: error.message }); + res.json(data); +}); + +module.exports = router; \ No newline at end of file