From e4e00184a59d70c497e9169094eca50744c96643 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 8 Jun 2025 19:46:23 +0300 Subject: [PATCH 1/5] change services api --- .../kfu-m-24-1/sber_mobile/DB_Scheme.txt | 47 ++++++++------ .../sber_mobile/utility_payments.js | 61 +++++++++++++++---- 2 files changed, 79 insertions(+), 29 deletions(-) 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..ef5844a 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,40 @@ 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 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(), + service_id UUID NOT NULL REFERENCES payment_services(id), + name TEXT NOT NULL, -- Например, "Отопление" + description TEXT, -- Описание услуги + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); + +-- 17. Платежи пользователя по деталям услуг +CREATE TABLE payments ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES auth.users(id), + apartment_id UUID REFERENCES apartments(id), + detail_id UUID NOT NULL REFERENCES payment_service_details(id), + amount DECIMAL(10, 2) NOT NULL, + period DATE NOT NULL, + status TEXT NOT NULL CHECK (status IN ('paid', 'pending', 'overdue')), + payment_method TEXT CHECK (payment_method IN ('card', 'sber')), + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW() +); + +-- 18. Заявки CREATE TABLE tickets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth.users(id), 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..2675059 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,56 @@ 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(*)') - .eq('apartment_id', apartment_id); - if (error) return res.status(400).json({ error: error.message }); - res.json(data); + const { apartment_id, user_id } = req.query; + if (!apartment_id || !user_id) return res.status(400).json({ error: 'apartment_id и user_id обязательны' }); + + // Получаем все агрегаторы + const { data: services, error: servicesError } = await supabase + .from('payment_services') + .select('id, name, icon'); + if (servicesError) return res.status(400).json({ error: servicesError.message }); + + // Получаем детали по агрегаторам + const { data: details, error: detailsError } = await supabase + .from('payment_service_details') + .select('id, service_id, name, description'); + if (detailsError) return res.status(400).json({ error: detailsError.message }); + + // Получаем платежи пользователя по деталям + const { data: payments, error: paymentsError } = await supabase + .from('payments') + .select('id, detail_id, amount, period, status, payment_method') + .eq('apartment_id', apartment_id) + .eq('user_id', user_id); + if (paymentsError) return res.status(400).json({ error: paymentsError.message }); + + // Формируем структуру для фронта + const result = services.map(service => { + const serviceDetails = details.filter(d => d.service_id === service.id).map(detail => { + const payment = payments.find(p => p.detail_id === detail.id) || {}; + return { + id: detail.id, + name: detail.name, + description: detail.description, + amount: payment.amount || null, + period: payment.period || null, + status: payment.status || 'pending', + paymentMethod: payment.payment_method || null, + paymentId: payment.id || null, + }; + }); + return { + id: service.id, + name: service.name, + icon: service.icon, + details: serviceDetails, + }; + }); + + res.json(result); }); -module.exports = router; \ No newline at end of file +module.exports = router; \ No newline at end of file From 18b33ae10a4b92a79dd760120f4bf840cda694cb Mon Sep 17 00:00:00 2001 From: DenAntonov Date: Sun, 8 Jun 2025 21:36:08 +0300 Subject: [PATCH 2/5] add initiatives --- .../kfu-m-24-1/sber_mobile/initiatives.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) 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 }); From 46ad6ea9f3bccea49e0242ae08f592846b1cfe42 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 8 Jun 2025 22:24:19 +0300 Subject: [PATCH 3/5] change services in db --- .../kfu-m-24-1/sber_mobile/DB_Scheme.txt | 42 +++++--------- .../sber_mobile/utility_payments.js | 58 +++++++++---------- 2 files changed, 41 insertions(+), 59 deletions(-) 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 ef5844a..fa55eb6 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 @@ -143,40 +143,30 @@ CREATE TABLE cameras ( updated_at TIMESTAMPTZ DEFAULT NOW() ); --- 15. Агрегаторы платежных сервисов (ЖКХ, Интернет и т.д.) +-- 15. Платежки по квартире (ЖКХ, Интернет и т.д.) CREATE TABLE payment_services ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + apartment_id UUID NOT NULL REFERENCES apartments(id), name TEXT NOT NULL, -- Например, "ЖКХ", "Интернет" icon TEXT, -- Можно хранить название иконки или url - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() -); - --- 16. Детализация услуг внутри агрегатора (отопление, вода и т.д.) -CREATE TABLE payment_service_details ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - service_id UUID NOT NULL REFERENCES payment_services(id), - name TEXT NOT NULL, -- Например, "Отопление" - description TEXT, -- Описание услуги - created_at TIMESTAMPTZ DEFAULT NOW(), - updated_at TIMESTAMPTZ DEFAULT NOW() -); - --- 17. Платежи пользователя по деталям услуг -CREATE TABLE payments ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - user_id UUID NOT NULL REFERENCES auth.users(id), - apartment_id UUID REFERENCES apartments(id), - detail_id UUID NOT NULL REFERENCES payment_service_details(id), - amount DECIMAL(10, 2) NOT NULL, - period DATE NOT NULL, - status TEXT NOT NULL CHECK (status IN ('paid', 'pending', 'overdue')), + 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() ); --- 18. Заявки +-- 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), @@ -201,8 +191,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/utility_payments.js b/server/routers/kfu-m-24-1/sber_mobile/utility_payments.js index 2675059..61b2ae4 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,52 +1,46 @@ const router = require('express').Router(); const { getSupabaseClient } = require('./supabaseClient'); -// Получить агрегированные сервисы с деталями и статусами оплаты для квартиры +// Получить платежки с деталями для квартиры router.get('/payment-services', async (req, res) => { const supabase = getSupabaseClient(); - const { apartment_id, user_id } = req.query; - if (!apartment_id || !user_id) return res.status(400).json({ error: 'apartment_id и user_id обязательны' }); + const { apartment_id } = req.query; + 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'); + .select('id, name, icon, amount, is_paid, payment_method') + .eq('apartment_id', apartment_id); if (servicesError) return res.status(400).json({ error: servicesError.message }); - // Получаем детали по агрегаторам - const { data: details, error: detailsError } = await supabase - .from('payment_service_details') - .select('id, service_id, name, description'); - if (detailsError) return res.status(400).json({ error: detailsError.message }); - - // Получаем платежи пользователя по деталям - const { data: payments, error: paymentsError } = await supabase - .from('payments') - .select('id, detail_id, amount, period, status, payment_method') - .eq('apartment_id', apartment_id) - .eq('user_id', user_id); - if (paymentsError) return res.status(400).json({ error: paymentsError.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.service_id === service.id).map(detail => { - const payment = payments.find(p => p.detail_id === detail.id) || {}; - return { - id: detail.id, - name: detail.name, - description: detail.description, - amount: payment.amount || null, - period: payment.period || null, - status: payment.status || 'pending', - paymentMethod: payment.payment_method || null, - paymentId: payment.id || null, - }; - }); + 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, name: service.name, icon: service.icon, - details: serviceDetails, + amount: service.amount, + isPaid: service.is_paid, + paymentMethod: service.payment_method, + details: serviceDetails }; }); From b9f6e4d7aac9d18b12ff238daf82d9f51a3c2fdc Mon Sep 17 00:00:00 2001 From: DenAntonov Date: Tue, 10 Jun 2025 21:45:57 +0300 Subject: [PATCH 4/5] fix outgoing json --- server/routers/kfu-m-24-1/sber_mobile/utility_payments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 61b2ae4..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 @@ -35,7 +35,7 @@ router.get('/payment-services', async (req, res) => { })); return { id: service.id, - name: service.name, + title: service.name, icon: service.icon, amount: service.amount, isPaid: service.is_paid, From da7e25d33929574afb3bab2f21fb6a88abe713b3 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 10 Jun 2025 23:25:51 +0300 Subject: [PATCH 5/5] add support table and api --- .../kfu-m-24-1/sber_mobile/DB_Scheme.txt | 9 ++++++++ .../routers/kfu-m-24-1/sber_mobile/index.js | 4 +++- .../kfu-m-24-1/sber_mobile/supportApi.js | 22 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 server/routers/kfu-m-24-1/sber_mobile/supportApi.js 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 fa55eb6..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 @@ -179,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); 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/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