diff --git a/server/routers/kfu-m-24-1/sber_mobile/DB_Scheme.txt b/server/routers/kfu-m-24-1/sber_mobile/DB_Scheme.txt index 81dade2..0a7b25a 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/DB_Scheme.txt +++ b/server/routers/kfu-m-24-1/sber_mobile/DB_Scheme.txt @@ -77,16 +77,6 @@ CREATE TABLE building_management_services ( PRIMARY KEY (building_id, service_id) ); --- 8. Платежные сервисы -CREATE TABLE payment_services ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - name TEXT NOT NULL, - logo_url TEXT, - provider_name TEXT, - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() -); - -- 9. Дополнительные сервисы CREATE TABLE additional_services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), @@ -153,19 +143,30 @@ CREATE TABLE cameras ( updated_at TIMESTAMPTZ DEFAULT NOW() ); --- 15. Платежи ЖКХ (исправленная версия) -CREATE TABLE utility_payments ( +-- 15. Платежки по квартире (ЖКХ, Интернет и т.д.) +CREATE TABLE payment_services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), apartment_id UUID NOT NULL REFERENCES apartments(id), - service_id UUID NOT NULL REFERENCES payment_services(id), - amount DECIMAL(10, 2) NOT NULL, - period DATE NOT NULL, - status TEXT NOT NULL CHECK (status IN ('paid', 'pending', 'overdue')), + name TEXT NOT NULL, -- Например, "ЖКХ", "Интернет" + icon TEXT, -- Можно хранить название иконки или url + amount DECIMAL(10, 2) NOT NULL, -- Общая сумма по платежке + is_paid BOOLEAN DEFAULT FALSE, -- Оплачен ли весь агрегатор + payment_method TEXT CHECK (payment_method IN ('card', 'sber')), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); --- 16. Заявки +-- 16. Детализация по платежке (например, отопление, вода и т.д.) +CREATE TABLE payment_service_details ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + payment_service_id UUID NOT NULL REFERENCES payment_services(id) ON DELETE CASCADE, + name TEXT NOT NULL, -- Например, "Отопление" + amount DECIMAL(10, 2) NOT NULL, -- Сумма по детализации + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); + +-- 17. Заявки CREATE TABLE tickets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth.users(id), @@ -178,6 +179,15 @@ CREATE TABLE tickets ( updated_at TIMESTAMPTZ DEFAULT NOW() ); +-- 18. Сообщения в службу поддержки +CREATE TABLE support ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES auth.users(id), + message TEXT NOT NULL, + is_from_user BOOLEAN NOT NULL, + created_at TIMESTAMPTZ DEFAULT NOW() +); + -- Индексы CREATE INDEX idx_buildings_management_company ON buildings(management_company_id); CREATE INDEX idx_management_services_company ON management_services(management_company_id); @@ -190,8 +200,6 @@ CREATE INDEX idx_tickets_user ON tickets(user_id); CREATE INDEX idx_apartments_building ON apartments(building_id); CREATE INDEX idx_apartment_residents_apartment ON apartment_residents(apartment_id); CREATE INDEX idx_apartment_residents_user ON apartment_residents(user_id); -CREATE INDEX idx_payments_apartment ON utility_payments(apartment_id); -CREATE INDEX idx_payments_service ON utility_payments(service_id); -- Триггеры для обновления updated_at CREATE OR REPLACE FUNCTION update_updated_at() 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 3a655bc..e419be7 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/index.js +++ b/server/routers/kfu-m-24-1/sber_mobile/index.js @@ -14,6 +14,7 @@ const apartmentsRouter = require('./apartments'); const buildingsRouter = require('./buildings'); const userApartmentsRouter = require('./user_apartments'); const avatarRouter = require('./media'); +const supportRouter = require('./supportApi'); module.exports = router; @@ -31,4 +32,5 @@ router.use('', utilityPaymentsRouter); router.use('', apartmentsRouter); router.use('', buildingsRouter); router.use('', userApartmentsRouter); -router.use('', avatarRouter); \ No newline at end of file +router.use('', avatarRouter); +router.use('', supportRouter); \ 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 index 4e0469b..3ca0562 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/initiatives.js +++ b/server/routers/kfu-m-24-1/sber_mobile/initiatives.js @@ -1,11 +1,22 @@ const router = require('express').Router(); const { getSupabaseClient } = require('./supabaseClient'); -// Получить все инициативы (по дому) -router.get('/initiatives', async (req, res) => { +// Получить все предложения, инициативы status=review (по дому) +router.get('/initiatives-review', async (req, res) => { const supabase = getSupabaseClient(); const { building_id } = req.query; - let query = supabase.from('initiatives').select('*'); + let query = supabase.from('initiatives').select('*').eq('status', 'review'); + 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); +}); + +// Получить все сборы, инициативы status=fundraising (по дому) +router.get('/initiatives-fundraising', async (req, res) => { + const supabase = getSupabaseClient(); + const { building_id } = req.query; + let query = supabase.from('initiatives').select('*').eq('status', 'fundraising'); 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 }); diff --git a/server/routers/kfu-m-24-1/sber_mobile/supportApi.js b/server/routers/kfu-m-24-1/sber_mobile/supportApi.js new file mode 100644 index 0000000..a741e89 --- /dev/null +++ b/server/routers/kfu-m-24-1/sber_mobile/supportApi.js @@ -0,0 +1,22 @@ +const express = require('express'); +const router = express.Router(); +const { supabase } = require('./supabaseClient'); + +// POST /api/support +router.post('/support', async (req, res) => { + const { user_id, message } = req.body; + if (!user_id || !message) { + return res.status(400).json({ error: 'user_id и message обязательны' }); + } + try { + const { data, error } = await supabase + .from('support') + .insert([{ user_id, message, is_from_user: true }]); + if (error) throw error; + return res.json({ reply: 'Спасибо за ваше сообщение! Служба поддержки свяжется с вами в ближайшее время.' }); + } catch (err) { + return res.status(500).json({ error: 'Ошибка при сохранении сообщения' }); + } +}); + +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 index a6e8b98..b5082b6 100644 --- a/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js +++ b/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js @@ -1,17 +1,50 @@ const router = require('express').Router(); const { getSupabaseClient } = require('./supabaseClient'); -// Получить все платежи по конкретной квартире с данными сервиса -router.get('/utility-payments', async (req, res) => { +// Получить платежки с деталями для квартиры +router.get('/payment-services', 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(*)') + if (!apartment_id) return res.status(400).json({ error: 'apartment_id обязателен' }); + + // Получаем все платежки по квартире + const { data: services, error: servicesError } = await supabase + .from('payment_services') + .select('id, name, icon, amount, is_paid, payment_method') .eq('apartment_id', apartment_id); - if (error) return res.status(400).json({ error: error.message }); - res.json(data); + if (servicesError) return res.status(400).json({ error: servicesError.message }); + + // Получаем детализацию по всем платежкам + const serviceIds = services.map(s => s.id); + let details = []; + if (serviceIds.length > 0) { + const { data: detailsData, error: detailsError } = await supabase + .from('payment_service_details') + .select('id, payment_service_id, name, amount') + .in('payment_service_id', serviceIds); + if (detailsError) return res.status(400).json({ error: detailsError.message }); + details = detailsData; + } + + // Формируем структуру для фронта + const result = services.map(service => { + const serviceDetails = details.filter(d => d.payment_service_id === service.id).map(detail => ({ + id: detail.id, + name: detail.name, + amount: detail.amount + })); + return { + id: service.id, + title: service.name, + icon: service.icon, + amount: service.amount, + isPaid: service.is_paid, + paymentMethod: service.payment_method, + details: serviceDetails + }; + }); + + res.json(result); }); -module.exports = router; \ No newline at end of file +module.exports = router; \ No newline at end of file