Запрос на слияние 'sber_mobile' (#14) из sber_mobile в main
This commit is contained in:
@@ -77,16 +77,6 @@ CREATE TABLE building_management_services (
|
|||||||
PRIMARY KEY (building_id, service_id)
|
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. Дополнительные сервисы
|
-- 9. Дополнительные сервисы
|
||||||
CREATE TABLE additional_services (
|
CREATE TABLE additional_services (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
@@ -153,19 +143,30 @@ CREATE TABLE cameras (
|
|||||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
);
|
);
|
||||||
|
|
||||||
-- 15. Платежи ЖКХ (исправленная версия)
|
-- 15. Платежки по квартире (ЖКХ, Интернет и т.д.)
|
||||||
CREATE TABLE utility_payments (
|
CREATE TABLE payment_services (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
apartment_id UUID NOT NULL REFERENCES apartments(id),
|
apartment_id UUID NOT NULL REFERENCES apartments(id),
|
||||||
service_id UUID NOT NULL REFERENCES payment_services(id),
|
name TEXT NOT NULL, -- Например, "ЖКХ", "Интернет"
|
||||||
amount DECIMAL(10, 2) NOT NULL,
|
icon TEXT, -- Можно хранить название иконки или url
|
||||||
period DATE NOT NULL,
|
amount DECIMAL(10, 2) NOT NULL, -- Общая сумма по платежке
|
||||||
status TEXT NOT NULL CHECK (status IN ('paid', 'pending', 'overdue')),
|
is_paid BOOLEAN DEFAULT FALSE, -- Оплачен ли весь агрегатор
|
||||||
|
payment_method TEXT CHECK (payment_method IN ('card', 'sber')),
|
||||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
updated_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 (
|
CREATE TABLE tickets (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
user_id UUID NOT NULL REFERENCES auth.users(id),
|
user_id UUID NOT NULL REFERENCES auth.users(id),
|
||||||
@@ -178,6 +179,15 @@ CREATE TABLE tickets (
|
|||||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
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_buildings_management_company ON buildings(management_company_id);
|
||||||
CREATE INDEX idx_management_services_company ON management_services(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_apartments_building ON apartments(building_id);
|
||||||
CREATE INDEX idx_apartment_residents_apartment ON apartment_residents(apartment_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_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
|
-- Триггеры для обновления updated_at
|
||||||
CREATE OR REPLACE FUNCTION update_updated_at()
|
CREATE OR REPLACE FUNCTION update_updated_at()
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const apartmentsRouter = require('./apartments');
|
|||||||
const buildingsRouter = require('./buildings');
|
const buildingsRouter = require('./buildings');
|
||||||
const userApartmentsRouter = require('./user_apartments');
|
const userApartmentsRouter = require('./user_apartments');
|
||||||
const avatarRouter = require('./media');
|
const avatarRouter = require('./media');
|
||||||
|
const supportRouter = require('./supportApi');
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
@@ -31,4 +32,5 @@ router.use('', utilityPaymentsRouter);
|
|||||||
router.use('', apartmentsRouter);
|
router.use('', apartmentsRouter);
|
||||||
router.use('', buildingsRouter);
|
router.use('', buildingsRouter);
|
||||||
router.use('', userApartmentsRouter);
|
router.use('', userApartmentsRouter);
|
||||||
router.use('', avatarRouter);
|
router.use('', avatarRouter);
|
||||||
|
router.use('', supportRouter);
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
const { getSupabaseClient } = require('./supabaseClient');
|
const { getSupabaseClient } = require('./supabaseClient');
|
||||||
|
|
||||||
// Получить все инициативы (по дому)
|
// Получить все предложения, инициативы status=review (по дому)
|
||||||
router.get('/initiatives', async (req, res) => {
|
router.get('/initiatives-review', async (req, res) => {
|
||||||
const supabase = getSupabaseClient();
|
const supabase = getSupabaseClient();
|
||||||
const { building_id } = req.query;
|
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);
|
if (building_id) query = query.eq('building_id', building_id);
|
||||||
const { data, error } = await query;
|
const { data, error } = await query;
|
||||||
if (error) return res.status(400).json({ error: error.message });
|
if (error) return res.status(400).json({ error: error.message });
|
||||||
|
|||||||
22
server/routers/kfu-m-24-1/sber_mobile/supportApi.js
Normal file
22
server/routers/kfu-m-24-1/sber_mobile/supportApi.js
Normal file
@@ -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;
|
||||||
@@ -1,17 +1,50 @@
|
|||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
const { getSupabaseClient } = require('./supabaseClient');
|
const { getSupabaseClient } = require('./supabaseClient');
|
||||||
|
|
||||||
// Получить все платежи по конкретной квартире с данными сервиса
|
// Получить платежки с деталями для квартиры
|
||||||
router.get('/utility-payments', async (req, res) => {
|
router.get('/payment-services', async (req, res) => {
|
||||||
const supabase = getSupabaseClient();
|
const supabase = getSupabaseClient();
|
||||||
const { apartment_id } = req.query;
|
const { apartment_id } = req.query;
|
||||||
if (!apartment_id) return res.status(400).json({ error: 'apartment_id required' });
|
if (!apartment_id) return res.status(400).json({ error: 'apartment_id обязателен' });
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('utility_payments')
|
// Получаем все платежки по квартире
|
||||||
.select('*, payment_services(*)')
|
const { data: services, error: servicesError } = await supabase
|
||||||
|
.from('payment_services')
|
||||||
|
.select('id, name, icon, amount, is_paid, payment_method')
|
||||||
.eq('apartment_id', apartment_id);
|
.eq('apartment_id', apartment_id);
|
||||||
if (error) return res.status(400).json({ error: error.message });
|
if (servicesError) return res.status(400).json({ error: servicesError.message });
|
||||||
res.json(data);
|
|
||||||
|
// Получаем детализацию по всем платежкам
|
||||||
|
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;
|
module.exports = router;
|
||||||
Reference in New Issue
Block a user