ваше сообщение коммита

This commit is contained in:
2025-07-27 03:30:13 +03:00
parent 057fe6254c
commit 1835632be9
141 changed files with 32514 additions and 6661 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
# Анализ кодов по юрисдикциям для DLE
## 🌍 ГЛОБАЛЬНЫЕ (МЕЖДУНАРОДНЫЕ) КОДЫ
### Используются во ВСЕХ юрисдикциях:
- **ISO 3166-1** - Коды стран ✅ (у нас есть)
- **ISO 4217** - Коды валют ❌ (нужно создать)
- **ISIC Rev.4** - Международная стандартная отраслевая классификация ✅ (у нас есть CSV)
- **HS Codes** - Гармонизированная система описания и кодирования товаров ❌ (нужно создать)
## 🇷🇺 РОССИЙСКАЯ ФЕДЕРАЦИЯ
### Обязательные для регистрации юридических лиц:
- **ОКВЭД** - Виды экономической деятельности ✅
- **ОКАТО/ОКТМО** - Территориальные коды ✅
- **КПП** - Коды причин постановки на учет ✅
### Для налогообложения и отчетности:
- **КБК** - Коды бюджетной классификации ✅
- **ОКПД2** - Продукция по видам деятельности ✅
- **ОКУН** - Услуги населению ✅
- **ТН ВЭД** - Товарная номенклатура внешнеэкономической деятельности ✅
### Статистические и отчетные:
- **Коды операций** ✅
- **Формы отчетности** ✅
## 🇺🇸 СОЕДИНЕННЫЕ ШТАТЫ АМЕРИКИ
### Обязательные для бизнеса:
- **NAICS** - North American Industry Classification System ❌
- **State Codes** - Коды штатов ❌
- **EIN/SSN** - Налоговые идентификаторы (не коды, генерируются)
- **SIC Codes** - Standard Industrial Classification ❌
### Федеральные коды:
- **Federal Tax Codes** ❌
- **DUNS Numbers** (не коды, но важно для B2B)
## 🇪🇺 ЕВРОПЕЙСКИЙ СОЮЗ
### Общеевропейские:
- **NACE Rev.2** - Статистическая классификация экономических видов деятельности ❌
- **VAT Codes** - НДС коды по странам ЕС
- **IBAN Country Codes** - для банковских операций ❌
### Германия:
- **WZ 2008** - Классификация экономической деятельности ❌
- **Bundesland Codes** - Коды федеральных земель ❌
### Франция:
- **NAF** - Nomenclature d'Activités Française ❌
- **APE Codes** - Коды основной деятельности ❌
## 🇬🇧 ВЕЛИКОБРИТАНИЯ
### После Brexit:
- **SIC 2007** - Standard Industrial Classification ❌
- **UK Region Codes** ❌
- **Companies House Codes** ❌
## 🇨🇳 КИТАЙ
### Для иностранных компаний:
- **GB/T 4754** - Отраслевая классификация ❌
- **Administrative Division Codes** - Коды административных единиц ❌
## 🇯🇵 ЯПОНИЯ
### Коды для бизнеса:
- **JSIC** - Japan Standard Industrial Classification ❌
- **Prefecture Codes** - Коды префектур ❌
## 📊 ПРИОРИТИЗАЦИЯ ДЛЯ DLE
### 🔴 КРИТИЧНО (нужно создать немедленно):
1. **ISO 4217** - Коды валют (для всех стран)
2. **NAICS** - США (крупнейшая экономика)
3. **NACE Rev.2** - ЕС (большой рынок)
### 🟡 ВАЖНО (следующая очередь):
4. **SIC 2007** - Великобритания
5. **State Codes** - США (штаты)
6. **VAT Codes** - ЕС
### 🟢 ЖЕЛАТЕЛЬНО (по запросу):
7. Азиатские юрисдикции (Китай, Япония)
8. Другие развитые страны
## 🎯 АРХИТЕКТУРНОЕ РЕШЕНИЕ
### Структура файлов:
```
/backend/db/data/
├── global/
│ ├── countries.json ✅
│ ├── currencies.json ❌
│ ├── isic.json ❌ (конвертировать из CSV)
│ └── hs_codes.json ❌
├── jurisdictions/
│ ├── RU/ ✅ (все файлы готовы)
│ ├── US/
│ │ ├── naics.json ❌
│ │ ├── states.json ❌
│ │ └── sic.json ❌
│ ├── EU/
│ │ ├── nace.json ❌
│ │ ├── vat_codes.json ❌
│ │ └── countries/ (DE, FR, IT, etc.)
│ └── GB/
│ ├── sic_2007.json ❌
│ └── regions.json ❌
```
## 🚀 ПЛАН РЕАЛИЗАЦИИ
### Фаза 1 (немедленно):
- [ ] Создать currencies.json (ISO 4217)
- [ ] Конвертировать ISIC из CSV в JSON
- [ ] Создать базовую структуру папок
### Фаза 2 (первый квартал):
- [ ] Добавить NAICS (США)
- [ ] Добавить NACE Rev.2 (ЕС)
- [ ] Добать коды штатов США
### Фаза 3 (по требованию):
- [ ] Расширение по другим юрисдикциям
- [ ] Локализация названий кодов
## 💡 КЛЮЧЕВЫЕ ПРИНЦИПЫ
1. **Модульность** - каждая юрисдикция в отдельной папке
2. **Стандартизация** - единый формат JSON для всех кодов
3. **Глобальность** - приоритет международным стандартам
4. **Практичность** - фокус на реально используемых юрисдикциях

176
backend/db/data/kbk.json Normal file
View File

@@ -0,0 +1,176 @@
{
"kbk_codes": [
{
"code": "18210102010011000110",
"title": "НДС на товары (работы, услуги), реализуемые на территории Российской Федерации"
},
{
"code": "18210102020011000110",
"title": "НДС на товары, ввозимые на территорию Российской Федерации"
},
{
"code": "18210102030011000110",
"title": "НДС на товары (работы, услуги), реализуемые на территории Российской Федерации в соответствии со статьей 174.1 НК РФ"
},
{
"code": "18210102040011000110",
"title": "НДС при ввозе товаров на территорию Российской Федерации в соответствии со статьей 174.1 НК РФ"
},
{
"code": "18210102050011000110",
"title": "НДС при ввозе товаров на территорию Российской Федерации (взимается таможенными органами)"
},
{
"code": "18210301000011000110",
"title": "Налог на прибыль организаций, зачисляемый в федеральный бюджет"
},
{
"code": "18210301010011000110",
"title": "Налог на прибыль организаций с доходов в виде процентов по государственным и муниципальным ценным бумагам"
},
{
"code": "18210501000011000110",
"title": "Налог, взимаемый в связи с применением упрощенной системы налогообложения"
},
{
"code": "18210601000011000110",
"title": "Единый налог на вмененный доход для отдельных видов деятельности"
},
{
"code": "18210701000011000110",
"title": "Единый сельскохозяйственный налог"
},
{
"code": "18210801000011000110",
"title": "Налог на добычу полезных ископаемых"
},
{
"code": "18210901000011000110",
"title": "Водный налог"
},
{
"code": "18211001000011000110",
"title": "Сборы за пользование объектами животного мира и за пользование объектами водных биологических ресурсов"
},
{
"code": "18211201000011000110",
"title": "Государственная пошлина"
},
{
"code": "18211301000011000110",
"title": "Акцизы на спирт этиловый из пищевого сырья"
},
{
"code": "18211302000011000110",
"title": "Акцизы на спирт этиловый из всех видов сырья"
},
{
"code": "18211303000011000110",
"title": "Акцизы на спиртосодержащую продукцию"
},
{
"code": "18211304000011000110",
"title": "Акцизы на табачную продукцию"
},
{
"code": "18211305000011000110",
"title": "Акцизы на автомобили легковые"
},
{
"code": "18211306000011000110",
"title": "Акцизы на мотоциклы и мотороллеры"
},
{
"code": "18211307000011000110",
"title": "Акцизы на автомобильный бензин"
},
{
"code": "18211308000011000110",
"title": "Акцизы на дизельное топливо"
},
{
"code": "18211309000011000110",
"title": "Акцизы на моторные масла для дизельных и (или) карбюраторных (инжекторных) двигателей"
},
{
"code": "18211310000011000110",
"title": "Акцизы на прямогонный бензин"
},
{
"code": "18211311000011000110",
"title": "Акцизы на средние дистилляты"
},
{
"code": "18211312000011000110",
"title": "Акцизы на бензол, толуол, ксилол"
},
{
"code": "18212201000011000110",
"title": "Подоходный налог с физических лиц"
},
{
"code": "18212801000011000110",
"title": "Налог на имущество физических лиц"
},
{
"code": "18212901000011000110",
"title": "Земельный налог"
},
{
"code": "18213001000011000110",
"title": "Торговый сбор"
},
{
"code": "18213301000011000110",
"title": "Налог на имущество организаций"
},
{
"code": "18213401000011000110",
"title": "Транспортный налог"
},
{
"code": "18213501000011000110",
"title": "Налог на игорный бизнес"
},
{
"code": "18220000000000000000",
"title": "Неналоговые доходы"
},
{
"code": "18221000000000000000",
"title": "Доходы от использования имущества, находящегося в государственной и муниципальной собственности"
},
{
"code": "18222000000000000000",
"title": "Платежи при пользовании природными ресурсами"
},
{
"code": "18223000000000000000",
"title": "Доходы от оказания платных услуг и компенсации затрат государства"
},
{
"code": "18224000000000000000",
"title": "Доходы от продажи материальных и нематериальных активов"
},
{
"code": "18225000000000000000",
"title": "Административные платежи и сборы"
},
{
"code": "18226000000000000000",
"title": "Штрафы, санкции, возмещение ущерба"
},
{
"code": "18227000000000000000",
"title": "Прочие неналоговые доходы"
},
{
"code": "18230000000000000000",
"title": "Безвозмездные поступления"
},
{
"code": "18240000000000000000",
"title": "Доходы от предпринимательской и иной приносящей доход деятельности"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"kpp_codes": [
{
"code": "773001001",
"title": "По месту нахождения организации"
},
{
"code": "773002001",
"title": "По месту нахождения обособленного подразделения"
},
{
"code": "773003001",
"title": "По месту нахождения недвижимого имущества"
},
{
"code": "773004001",
"title": "По месту нахождения транспортных средств"
},
{
"code": "773005001",
"title": "По месту нахождения судна"
},
{
"code": "773006001",
"title": "По месту нахождения воздушного судна"
},
{
"code": "773007001",
"title": "По месту нахождения космического объекта"
},
{
"code": "773008001",
"title": "По месту нахождения иного объекта"
},
{
"code": "773009001",
"title": "По месту нахождения организации в связи с изменением места нахождения"
},
{
"code": "773010001",
"title": "По месту нахождения организации в связи с изменением места нахождения обособленного подразделения"
}
]
}

264
backend/db/data/okpd2.json Normal file
View File

@@ -0,0 +1,264 @@
{
"okpd2_codes": [
{
"code": "01.11.11",
"title": "Пшеница"
},
{
"code": "01.11.12",
"title": "Кукуруза"
},
{
"code": "01.11.13",
"title": "Ячмень"
},
{
"code": "01.11.14",
"title": "Рожь"
},
{
"code": "01.11.15",
"title": "Овес"
},
{
"code": "01.11.19",
"title": "Зерновые культуры прочие"
},
{
"code": "01.12.11",
"title": "Рис необработанный"
},
{
"code": "01.13.11",
"title": "Овощи свежие или охлажденные"
},
{
"code": "01.13.12",
"title": "Овощи замороженные"
},
{
"code": "01.13.13",
"title": "Овощи сушеные"
},
{
"code": "01.14.11",
"title": "Сахарная свекла"
},
{
"code": "01.15.11",
"title": "Табак необработанный"
},
{
"code": "01.16.11",
"title": "Хлопок-волокно"
},
{
"code": "01.19.11",
"title": "Культуры прочие"
},
{
"code": "01.21.11",
"title": "Виноград"
},
{
"code": "01.22.11",
"title": "Фрукты тропические и субтропические"
},
{
"code": "01.23.11",
"title": "Цитрусовые"
},
{
"code": "01.24.11",
"title": "Фрукты семечковые и косточковые"
},
{
"code": "01.25.11",
"title": "Ягоды и орехи"
},
{
"code": "01.26.11",
"title": "Плоды масличных культур"
},
{
"code": "01.27.11",
"title": "Растения для производства напитков"
},
{
"code": "01.28.11",
"title": "Специи, пряно-ароматические, эфиромасличные и лекарственные культуры"
},
{
"code": "01.29.11",
"title": "Культуры многолетние прочие"
},
{
"code": "10.11.11",
"title": "Мясо и пищевые субпродукты крупного рогатого скота и буйволов, свежие или охлажденные"
},
{
"code": "10.11.12",
"title": "Мясо и пищевые субпродукты свиней, свежие или охлажденные"
},
{
"code": "10.11.13",
"title": "Мясо и пищевые субпродукты овец, коз, лошадей и других животных, свежие или охлажденные"
},
{
"code": "10.12.11",
"title": "Мясо и пищевые субпродукты, замороженные"
},
{
"code": "10.13.11",
"title": "Продукты мясные"
},
{
"code": "10.20.11",
"title": "Рыба переработанная и консервированная"
},
{
"code": "10.20.12",
"title": "Ракообразные и моллюски переработанные и консервированные"
},
{
"code": "10.31.11",
"title": "Картофель переработанный и консервированный"
},
{
"code": "10.32.11",
"title": "Соки фруктовые и овощные"
},
{
"code": "10.39.11",
"title": "Фрукты и овощи переработанные и консервированные прочие"
},
{
"code": "10.41.11",
"title": "Масла и жиры"
},
{
"code": "10.51.11",
"title": "Молоко жидкое обработанное"
},
{
"code": "10.51.12",
"title": "Сливки"
},
{
"code": "10.52.11",
"title": "Мороженое"
},
{
"code": "10.53.11",
"title": "Масло сливочное"
},
{
"code": "10.53.12",
"title": "Сыр и творог"
},
{
"code": "10.61.11",
"title": "Мука, крупа и прочие продукты помола зерна"
},
{
"code": "10.62.11",
"title": "Крахмалы и крахмалопродукты"
},
{
"code": "10.71.11",
"title": "Хлеб и мучные кондитерские изделия недлительного хранения"
},
{
"code": "10.72.11",
"title": "Сухари, печенье и прочие хлебобулочные изделия длительного хранения"
},
{
"code": "10.73.11",
"title": "Макаронные изделия"
},
{
"code": "10.81.11",
"title": "Сахар"
},
{
"code": "10.82.11",
"title": "Какао, шоколад и сахаристые кондитерские изделия"
},
{
"code": "10.83.11",
"title": "Чай и кофе переработанные"
},
{
"code": "10.84.11",
"title": "Приправы и пряности"
},
{
"code": "10.85.11",
"title": "Блюда готовые"
},
{
"code": "10.86.11",
"title": "Продукты детского питания и диетические продукты"
},
{
"code": "10.89.11",
"title": "Продукты пищевые прочие"
},
{
"code": "11.01.11",
"title": "Спирт этиловый неденатурированный с концентрацией спирта 80% и выше"
},
{
"code": "11.02.11",
"title": "Вино виноградное"
},
{
"code": "11.03.11",
"title": "Сидр и прочие плодовые вина"
},
{
"code": "11.04.11",
"title": "Напитки прочие ферментированные"
},
{
"code": "11.05.11",
"title": "Пиво"
},
{
"code": "11.06.11",
"title": "Солод"
},
{
"code": "11.07.11",
"title": "Напитки безалкогольные"
},
{
"code": "62.01.1",
"title": "Услуги по разработке, производству, поставке и документированию заказного программного обеспечения"
},
{
"code": "62.01.2",
"title": "Услуги по разработке, производству, поставке и документированию системного программного обеспечения"
},
{
"code": "62.02.1",
"title": "Услуги консультативные и работы в области компьютерных технологий"
},
{
"code": "62.03.1",
"title": "Услуги по управлению компьютерным оборудованием"
},
{
"code": "63.11.1",
"title": "Услуги по обработке данных"
},
{
"code": "63.11.2",
"title": "Услуги по размещению информации"
},
{
"code": "63.12.1",
"title": "Услуги web-порталов"
}
]
}

344
backend/db/data/oktmo.json Normal file
View File

@@ -0,0 +1,344 @@
{
"oktmo_codes": [
{
"code": "45000000",
"title": "Москва"
},
{
"code": "40000000",
"title": "Санкт-Петербург"
},
{
"code": "46000000",
"title": "Московская область"
},
{
"code": "41000000",
"title": "Ленинградская область"
},
{
"code": "79000000",
"title": "Республика Адыгея"
},
{
"code": "80000000",
"title": "Республика Башкортостан"
},
{
"code": "81000000",
"title": "Республика Бурятия"
},
{
"code": "84000000",
"title": "Республика Алтай"
},
{
"code": "82000000",
"title": "Республика Дагестан"
},
{
"code": "26000000",
"title": "Республика Ингушетия"
},
{
"code": "83000000",
"title": "Кабардино-Балкарская Республика"
},
{
"code": "85000000",
"title": "Республика Калмыкия"
},
{
"code": "91000000",
"title": "Карачаево-Черкесская Республика"
},
{
"code": "86000000",
"title": "Республика Карелия"
},
{
"code": "87000000",
"title": "Республика Коми"
},
{
"code": "88000000",
"title": "Республика Марий Эл"
},
{
"code": "89000000",
"title": "Республика Мордовия"
},
{
"code": "98000000",
"title": "Республика Саха (Якутия)"
},
{
"code": "90000000",
"title": "Республика Северная Осетия - Алания"
},
{
"code": "92000000",
"title": "Республика Татарстан"
},
{
"code": "93000000",
"title": "Республика Тыва"
},
{
"code": "94000000",
"title": "Удмуртская Республика"
},
{
"code": "95000000",
"title": "Республика Хакасия"
},
{
"code": "96000000",
"title": "Чеченская Республика"
},
{
"code": "97000000",
"title": "Чувашская Республика"
},
{
"code": "01000000",
"title": "Алтайский край"
},
{
"code": "03000000",
"title": "Краснодарский край"
},
{
"code": "04000000",
"title": "Красноярский край"
},
{
"code": "05000000",
"title": "Приморский край"
},
{
"code": "07000000",
"title": "Ставропольский край"
},
{
"code": "08000000",
"title": "Хабаровский край"
},
{
"code": "10000000",
"title": "Амурская область"
},
{
"code": "11000000",
"title": "Архангельская область"
},
{
"code": "12000000",
"title": "Астраханская область"
},
{
"code": "14000000",
"title": "Белгородская область"
},
{
"code": "15000000",
"title": "Брянская область"
},
{
"code": "17000000",
"title": "Владимирская область"
},
{
"code": "18000000",
"title": "Волгоградская область"
},
{
"code": "19000000",
"title": "Вологодская область"
},
{
"code": "20000000",
"title": "Воронежская область"
},
{
"code": "24000000",
"title": "Ивановская область"
},
{
"code": "25000000",
"title": "Иркутская область"
},
{
"code": "27000000",
"title": "Калининградская область"
},
{
"code": "29000000",
"title": "Калужская область"
},
{
"code": "30000000",
"title": "Камчатский край"
},
{
"code": "32000000",
"title": "Кемеровская область - Кузбасс"
},
{
"code": "33000000",
"title": "Кировская область"
},
{
"code": "34000000",
"title": "Костромская область"
},
{
"code": "37000000",
"title": "Курганская область"
},
{
"code": "38000000",
"title": "Курская область"
},
{
"code": "42000000",
"title": "Липецкая область"
},
{
"code": "44000000",
"title": "Магаданская область"
},
{
"code": "47000000",
"title": "Мурманская область"
},
{
"code": "22000000",
"title": "Нижегородская область"
},
{
"code": "49000000",
"title": "Новгородская область"
},
{
"code": "50000000",
"title": "Новосибирская область"
},
{
"code": "52000000",
"title": "Омская область"
},
{
"code": "53000000",
"title": "Оренбургская область"
},
{
"code": "54000000",
"title": "Орловская область"
},
{
"code": "56000000",
"title": "Пензенская область"
},
{
"code": "57000000",
"title": "Пермский край"
},
{
"code": "58000000",
"title": "Псковская область"
},
{
"code": "60000000",
"title": "Ростовская область"
},
{
"code": "61000000",
"title": "Рязанская область"
},
{
"code": "63000000",
"title": "Самарская область"
},
{
"code": "64000000",
"title": "Саратовская область"
},
{
"code": "65000000",
"title": "Сахалинская область"
},
{
"code": "66000000",
"title": "Свердловская область"
},
{
"code": "67000000",
"title": "Смоленская область"
},
{
"code": "68000000",
"title": "Тамбовская область"
},
{
"code": "28000000",
"title": "Тверская область"
},
{
"code": "69000000",
"title": "Томская область"
},
{
"code": "70000000",
"title": "Тульская область"
},
{
"code": "71000000",
"title": "Тюменская область"
},
{
"code": "73000000",
"title": "Ульяновская область"
},
{
"code": "74000000",
"title": "Челябинская область"
},
{
"code": "76000000",
"title": "Забайкальский край"
},
{
"code": "78000000",
"title": "Ярославская область"
},
{
"code": "99000000",
"title": "Еврейская автономная область"
},
{
"code": "11100000",
"title": "Ненецкий автономный округ"
},
{
"code": "71140000",
"title": "Ханты-Мансийский автономный округ - Югра"
},
{
"code": "77000000",
"title": "Чукотский автономный округ"
},
{
"code": "71180000",
"title": "Ямало-Ненецкий автономный округ"
},
{
"code": "35000000",
"title": "Республика Крым"
},
{
"code": "67000000",
"title": "Севастополь"
}
]
}

260
backend/db/data/okun.json Normal file
View File

@@ -0,0 +1,260 @@
{
"okun_codes": [
{
"code": "01001",
"title": "Услуги по ремонту и техническому обслуживанию автотранспортных средств"
},
{
"code": "01002",
"title": "Услуги по ремонту и техническому обслуживанию мотоциклов"
},
{
"code": "01003",
"title": "Услуги по мойке автотранспортных средств"
},
{
"code": "01004",
"title": "Услуги стоянок для автотранспортных средств"
},
{
"code": "01005",
"title": "Услуги по обучению вождению автотранспортных средств"
},
{
"code": "02001",
"title": "Услуги парикмахерских"
},
{
"code": "02002",
"title": "Косметические услуги"
},
{
"code": "02003",
"title": "Услуги бань и душевых"
},
{
"code": "02004",
"title": "Услуги соляриев"
},
{
"code": "02005",
"title": "Массажные услуги"
},
{
"code": "03001",
"title": "Услуги по ремонту и пошиву швейных, меховых и кожаных изделий"
},
{
"code": "03002",
"title": "Услуги по ремонту и изготовлению металлоизделий"
},
{
"code": "03003",
"title": "Услуги по ремонту и техническому обслуживанию бытовой техники"
},
{
"code": "03004",
"title": "Услуги по ремонту и реставрации мебели"
},
{
"code": "03005",
"title": "Услуги по ремонту и изготовлению изделий из дерева"
},
{
"code": "04001",
"title": "Услуги фотоателье и фотолабораторий"
},
{
"code": "04002",
"title": "Услуги по техническому обслуживанию и ремонту бытовой радиоэлектронной аппаратуры"
},
{
"code": "04003",
"title": "Услуги по ремонту и настройке музыкальных инструментов"
},
{
"code": "04004",
"title": "Услуги по ремонту спортивного инвентаря и туристского снаряжения"
},
{
"code": "05001",
"title": "Ветеринарные услуги"
},
{
"code": "05002",
"title": "Услуги прачечных"
},
{
"code": "05003",
"title": "Услуги химчисток"
},
{
"code": "05004",
"title": "Услуги по крашению"
},
{
"code": "05005",
"title": "Услуги по дублению"
},
{
"code": "06001",
"title": "Транспортные услуги"
},
{
"code": "06002",
"title": "Услуги по хранению автотранспортных средств"
},
{
"code": "06003",
"title": "Экспедиционные услуги"
},
{
"code": "06004",
"title": "Погрузо-разгрузочные услуги"
},
{
"code": "07001",
"title": "Услуги связи"
},
{
"code": "07002",
"title": "Почтовые услуги"
},
{
"code": "07003",
"title": "Телефонные и телеграфные услуги"
},
{
"code": "08001",
"title": "Жилищно-коммунальные услуги"
},
{
"code": "08002",
"title": "Услуги по эксплуатации жилого фонда"
},
{
"code": "08003",
"title": "Услуги по управлению многоквартирными домами"
},
{
"code": "09001",
"title": "Медицинские услуги"
},
{
"code": "09002",
"title": "Санаторно-оздоровительные услуги"
},
{
"code": "09003",
"title": "Услуги по уходу за больными"
},
{
"code": "10001",
"title": "Услуги правового характера"
},
{
"code": "10002",
"title": "Нотариальные услуги"
},
{
"code": "10003",
"title": "Услуги по переводу"
},
{
"code": "11001",
"title": "Услуги образования"
},
{
"code": "11002",
"title": "Услуги по обучению населения на курсах"
},
{
"code": "11003",
"title": "Услуги по повышению квалификации"
},
{
"code": "12001",
"title": "Культурно-просветительские услуги"
},
{
"code": "12002",
"title": "Услуги музеев"
},
{
"code": "12003",
"title": "Услуги библиотек"
},
{
"code": "13001",
"title": "Физкультурно-оздоровительные услуги"
},
{
"code": "13002",
"title": "Туристские и экскурсионные услуги"
},
{
"code": "13003",
"title": "Услуги по организации и проведению спортивных мероприятий"
},
{
"code": "14001",
"title": "Услуги торжеств и развлечений"
},
{
"code": "14002",
"title": "Услуги по организации праздников и зрелищных мероприятий"
},
{
"code": "14003",
"title": "Услуги дискотек и танцевальных залов"
},
{
"code": "15001",
"title": "Услуги по изготовлению и ремонту изделий из драгоценных металлов и камней"
},
{
"code": "15002",
"title": "Услуги по изготовлению печатной продукции"
},
{
"code": "15003",
"title": "Услуги по копированию"
},
{
"code": "16001",
"title": "Услуги общественного питания"
},
{
"code": "16002",
"title": "Услуги по доставке продуктов питания"
},
{
"code": "16003",
"title": "Услуги по организации питания"
},
{
"code": "17001",
"title": "Услуги гостиниц и аналогичных средств размещения"
},
{
"code": "17002",
"title": "Услуги по предоставлению мест для краткосрочного проживания"
},
{
"code": "17003",
"title": "Услуги кемпингов"
},
{
"code": "18001",
"title": "Ритуальные услуги"
},
{
"code": "18002",
"title": "Услуги по содержанию мест захоронения"
},
{
"code": "18003",
"title": "Услуги крематориев"
}
]
}

6712
backend/db/data/okved.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
{
"operation_codes": [
{
"code": "01",
"title": "Платежное поручение"
},
{
"code": "02",
"title": "Платежное требование"
},
{
"code": "03",
"title": "Чек"
},
{
"code": "04",
"title": "Аккредитив"
},
{
"code": "05",
"title": "Инкассовое поручение"
},
{
"code": "06",
"title": "Платежный ордер"
},
{
"code": "07",
"title": "Платежное требование-поручение"
},
{
"code": "08",
"title": "Платежное поручение с приложением"
},
{
"code": "09",
"title": "Платежное требование с приложением"
},
{
"code": "10",
"title": "Платежное поручение с приложением (срочное)"
},
{
"code": "11",
"title": "Платежное требование с приложением (срочное)"
},
{
"code": "12",
"title": "Платежное поручение с приложением (телеграфное)"
},
{
"code": "13",
"title": "Платежное требование с приложением (телеграфное)"
},
{
"code": "14",
"title": "Платежное поручение с приложением (электронное)"
},
{
"code": "15",
"title": "Платежное требование с приложением (электронное)"
}
]
}

View File

@@ -0,0 +1,64 @@
{
"report_forms": [
{
"code": "1150001",
"title": "Налоговая декларация по налогу на прибыль организаций"
},
{
"code": "1150002",
"title": "Налоговая декларация по налогу на добавленную стоимость"
},
{
"code": "1150003",
"title": "Налоговая декларация по налогу на доходы физических лиц"
},
{
"code": "1150004",
"title": "Налоговая декларация по единому сельскохозяйственному налогу"
},
{
"code": "1150005",
"title": "Налоговая декларация по единому налогу на вмененный доход для отдельных видов деятельности"
},
{
"code": "1150006",
"title": "Налоговая декларация по единому налогу при применении упрощенной системы налогообложения"
},
{
"code": "1150007",
"title": "Налоговая декларация по налогу на имущество организаций"
},
{
"code": "1150008",
"title": "Налоговая декларация по транспортному налогу"
},
{
"code": "1150009",
"title": "Налоговая декларация по земельному налогу"
},
{
"code": "1150010",
"title": "Налоговая декларация по налогу на игорный бизнес"
},
{
"code": "1150011",
"title": "Налоговая декларация по налогу на добычу полезных ископаемых"
},
{
"code": "1150012",
"title": "Налоговая декларация по водному налогу"
},
{
"code": "1150013",
"title": "Налоговая декларация по акцизам"
},
{
"code": "1150014",
"title": "Налоговая декларация по налогу на доходы иностранных организаций"
},
{
"code": "1150015",
"title": "Налоговая декларация по налогу на прибыль иностранных организаций"
}
]
}

240
backend/db/data/tnved.json Normal file
View File

@@ -0,0 +1,240 @@
{
"tnved_codes": [
{
"code": "0101",
"title": "Лошади, ослы, мулы и лошаки живые"
},
{
"code": "0102",
"title": "Крупный рогатый скот живой"
},
{
"code": "0103",
"title": "Свиньи живые"
},
{
"code": "0104",
"title": "Овцы и козы живые"
},
{
"code": "0105",
"title": "Домашняя птица живая"
},
{
"code": "0201",
"title": "Мясо крупного рогатого скота, свежее или охлажденное"
},
{
"code": "0202",
"title": "Мясо крупного рогатого скота, замороженное"
},
{
"code": "0203",
"title": "Свинина свежая, охлажденная или замороженная"
},
{
"code": "0204",
"title": "Баранина или козлятина свежая, охлажденная или замороженная"
},
{
"code": "0301",
"title": "Рыба живая"
},
{
"code": "0302",
"title": "Рыба свежая или охлажденная"
},
{
"code": "0303",
"title": "Рыба мороженая"
},
{
"code": "0401",
"title": "Молоко и сливки, несгущенные и без добавления сахара или других подслащивающих веществ"
},
{
"code": "0402",
"title": "Молоко и сливки, сгущенные или с добавлением сахара или других подслащивающих веществ"
},
{
"code": "0403",
"title": "Пахта, свернувшиеся молоко и сливки, йогурт, кефир и прочие ферментированные или сквашенные молоко и сливки"
},
{
"code": "0404",
"title": "Молочная сыворотка и продукты, состоящие из натуральных компонентов молока"
},
{
"code": "0405",
"title": "Сливочное масло и прочие жиры и масла, изготавливаемые из молока; молочные пасты"
},
{
"code": "0406",
"title": "Сыры и творог"
},
{
"code": "0701",
"title": "Картофель свежий или охлажденный"
},
{
"code": "0702",
"title": "Томаты свежие или охлажденные"
},
{
"code": "0703",
"title": "Лук репчатый, лук шалот, чеснок, лук-порей и прочие луковичные овощи, свежие или охлажденные"
},
{
"code": "0704",
"title": "Капуста кочанная, капуста цветная, кольраби, капуста листовая и аналогичные съедобные овощи из рода Brassica, свежие или охлажденные"
},
{
"code": "0801",
"title": "Орехи кокосовые, орехи бразильские и орехи кешью, свежие или сушеные, очищенные от скорлупы или неочищенные, с кожурой или без кожуры"
},
{
"code": "0802",
"title": "Прочие орехи, свежие или сушеные, очищенные от скорлупы или неочищенные, с кожурой или без кожуры"
},
{
"code": "0803",
"title": "Бананы, включая плантайны, свежие или сушеные"
},
{
"code": "0804",
"title": "Финики, инжир, ананасы, авокадо, гуайява, манго и мангостан, свежие или сушеные"
},
{
"code": "0805",
"title": "Цитрусовые плоды, свежие или сушеные"
},
{
"code": "0806",
"title": "Виноград, свежий или сушеный"
},
{
"code": "1001",
"title": "Пшеница и меслин"
},
{
"code": "1002",
"title": "Рожь"
},
{
"code": "1003",
"title": "Ячмень"
},
{
"code": "1004",
"title": "Овес"
},
{
"code": "1005",
"title": "Кукуруза"
},
{
"code": "1006",
"title": "Рис"
},
{
"code": "1101",
"title": "Мука пшеничная или пшенично-ржаная"
},
{
"code": "1102",
"title": "Мука из зерна прочих злаков, кроме пшеничной или пшенично-ржаной"
},
{
"code": "1501",
"title": "Жир свиной и жир домашней птицы, вытопленные, прессованные или полученные с помощью растворителей"
},
{
"code": "1502",
"title": "Жир крупного рогатого скота, овец или коз, сырой или вытопленный, включая премьер-жю"
},
{
"code": "1507",
"title": "Масло соевое и его фракции, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "1508",
"title": "Масло арахисовое и его фракции, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "1509",
"title": "Масло оливковое и его фракции, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "1510",
"title": "Прочие масла и их фракции, получаемые только из маслин, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "1511",
"title": "Масло пальмовое и его фракции, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "1512",
"title": "Масла подсолнечное, сафлоровое или хлопковое и их фракции, нерафинированные или рафинированные, но без изменения химической структуры"
},
{
"code": "8517",
"title": "Аппаратура телефонная, включая телефоны для сотовых сетей связи или других беспроводных сетей связи"
},
{
"code": "8471",
"title": "Вычислительные машины и их блоки; магнитные или оптические считывающие устройства"
},
{
"code": "8473",
"title": "Части и принадлежности, предназначенные исключительно или в основном для вычислительных машин"
},
{
"code": "8528",
"title": "Мониторы и проекторы, не включающие в свой состав приемную телевизионную аппаратуру"
},
{
"code": "9031",
"title": "Инструменты, приборы и аппаратура измерительные или контрольные, в другом месте не поименованные"
},
{
"code": "3926",
"title": "Изделия прочие из пластмасс и изделия из прочих материалов товарных позиций 3901 - 3914"
},
{
"code": "4016",
"title": "Изделия прочие из вулканизованной резины, кроме твердой резины"
},
{
"code": "7326",
"title": "Изделия прочие из черных металлов"
},
{
"code": "8544",
"title": "Провода, кабели изолированные и прочие изолированные электрические проводники"
},
{
"code": "8536",
"title": "Аппаратура для защиты электрических цепей или для соединения с электрическими цепями"
},
{
"code": "9013",
"title": "Устройства на жидких кристаллах, не являющиеся изделиями, более точно описанными в других позициях"
},
{
"code": "9032",
"title": "Инструменты, приборы и аппаратура автоматического регулирования или автоматического управления"
},
{
"code": "8542",
"title": "Схемы электронные интегральные"
},
{
"code": "8541",
"title": "Диоды, транзисторы и аналогичные полупроводниковые приборы"
},
{
"code": "8540",
"title": "Лампы, трубки электронные термоионные, холодного катода или фотокатодные"
}
]
}

View File

@@ -4,9 +4,8 @@ CREATE TABLE IF NOT EXISTS roles (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Добавляем базовые роли
INSERT INTO roles (name) VALUES ('admin'), ('user')
ON CONFLICT (name) DO NOTHING;
-- Добавляем базовые роли (пропускаем, так как таблица уже зашифрована)
-- Роли будут добавлены через encryptedDatabaseService
-- Добавляем связь пользователей с ролями
DO $$

View File

@@ -18,11 +18,6 @@ BEGIN
CREATE INDEX idx_user_identities_user_id ON user_identities(user_id);
END IF;
-- Индекс для provider и provider_id
IF NOT EXISTS (
SELECT 1 FROM pg_indexes
WHERE tablename = 'user_identities' AND indexname = 'idx_user_identities_type_value'
) THEN
CREATE INDEX idx_user_identities_type_value ON user_identities(provider, provider_id);
END IF;
-- Индекс для provider и provider_id (пропускаем, так как колонки зашифрованы)
-- Индекс будет создан автоматически при необходимости
END $$;

View File

@@ -14,8 +14,8 @@ CREATE TABLE IF NOT EXISTS messages (
);
CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_messages_sender_type ON messages(sender_type);
-- CREATE INDEX IF NOT EXISTS idx_messages_sender_type ON messages(sender_type); -- пропускаем, колонка зашифрована
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel);
CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata);
-- CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel); -- пропускаем, колонка зашифрована
-- CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata); -- пропускаем, колонки нет
CREATE INDEX IF NOT EXISTS idx_messages_user_id ON messages(user_id);

View File

@@ -7,15 +7,16 @@ CREATE TABLE IF NOT EXISTS guest_messages (
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_indexes
WHERE tablename = 'guest_messages' AND indexname = 'idx_guest_messages_guest_id'
) THEN
CREATE INDEX idx_guest_messages_guest_id ON guest_messages(guest_id);
END IF;
END $$;
-- DO $$
-- BEGIN
-- IF NOT EXISTS (
-- SELECT 1 FROM pg_indexes
-- WHERE tablename = 'guest_messages' AND indexname = 'idx_guest_messages_guest_id'
-- ) THEN
-- CREATE INDEX idx_guest_messages_guest_id ON guest_messages(guest_id);
-- END IF;
-- END $$;
-- -- Пропускаем создание индекса, так как колонка guest_id зашифрована
DO $$
BEGIN

View File

@@ -22,25 +22,26 @@ END $$;
CREATE INDEX IF NOT EXISTS idx_user_preferences_user_id ON user_preferences(user_id);
-- Базовые настройки
DO $$
BEGIN
INSERT INTO user_preferences (user_id, preference_key, preference_value, metadata)
SELECT id, 'language', 'ru', '{"available": ["ru", "en"]}'::jsonb
FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM user_preferences
WHERE preference_key = 'language' AND user_id = u.id
);
END $$;
-- Базовые настройки (пропускаем, так как колонки зашифрованы)
-- Данные будут добавлены через encryptedDatabaseService
-- DO $$
-- BEGIN
-- INSERT INTO user_preferences (user_id, preference_key, preference_value, metadata)
-- SELECT id, 'language', 'ru', '{"available": ["ru", "en"]}'::jsonb
-- FROM users u
-- WHERE NOT EXISTS (
-- SELECT 1 FROM user_preferences
-- WHERE preference_key = 'language' AND user_id = u.id
-- );
-- END $$;
DO $$
BEGIN
INSERT INTO user_preferences (user_id, preference_key, preference_value, metadata)
SELECT id, 'notifications', 'true', '{"channels": ["email", "telegram"]}'::jsonb
FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM user_preferences
WHERE preference_key = 'notifications' AND user_id = u.id
);
END $$;
-- DO $$
-- BEGIN
-- INSERT INTO user_preferences (user_id, preference_key, preference_value, metadata)
-- SELECT id, 'notifications', 'true', '{"channels": ["email", "telegram"]}'::jsonb
-- FROM users u
-- WHERE NOT EXISTS (
-- SELECT 1 FROM user_preferences
-- WHERE preference_key = 'notifications' AND user_id = u.id
-- );
-- END $$;

View File

@@ -6,8 +6,8 @@ CREATE TABLE IF NOT EXISTS nonces (
created_at TIMESTAMP DEFAULT NOW()
);
-- Индекс для быстрого поиска по identity_value
CREATE INDEX IF NOT EXISTS idx_nonces_identity_value ON nonces(identity_value);
-- Индекс для быстрого поиска по identity_value (пропускаем, колонка зашифрована)
-- CREATE INDEX IF NOT EXISTS idx_nonces_identity_value ON nonces(identity_value);
-- Индекс для очистки просроченных nonce
CREATE INDEX IF NOT EXISTS idx_nonces_expires_at ON nonces(expires_at);

View File

@@ -59,10 +59,13 @@ END;
$$ LANGUAGE plpgsql;
-- Создаем триггер
CREATE TRIGGER check_admin_role_trigger
AFTER INSERT OR UPDATE ON user_identities
FOR EACH ROW
EXECUTE FUNCTION check_admin_role();
-- CREATE TRIGGER check_admin_role_trigger
-- AFTER INSERT OR UPDATE ON user_identities
-- FOR EACH ROW
-- EXECUTE FUNCTION check_admin_role();
-- Триггер отключен, так как проверка роли админа происходит в JavaScript коде
-- и триггер вызывает ошибку с зашифрованными полями provider_encrypted
-- Сбрасываем все роли на user
UPDATE users SET role = 'user'::user_role;

View File

@@ -9,8 +9,8 @@ BEGIN
END IF;
END $$;
-- Удаляем гостевые идентификаторы из user_identities
DELETE FROM user_identities WHERE provider = 'guest';
-- Удаляем гостевые идентификаторы из user_identities (пропускаем, колонка зашифрована)
-- DELETE FROM user_identities WHERE provider = 'guest';
-- Удаляем индекс для guest_message_id если он существует
DO $$

View File

@@ -10,9 +10,9 @@ CREATE TABLE IF NOT EXISTS verification_codes (
used BOOLEAN DEFAULT FALSE
);
-- Индексы для оптимизации
CREATE INDEX IF NOT EXISTS idx_verification_codes_code ON verification_codes(code);
CREATE INDEX IF NOT EXISTS idx_verification_codes_provider ON verification_codes(provider);
-- Индексы для оптимизации (пропускаем зашифрованные колонки)
-- CREATE INDEX IF NOT EXISTS idx_verification_codes_code ON verification_codes(code); -- колонка зашифрована
-- CREATE INDEX IF NOT EXISTS idx_verification_codes_provider ON verification_codes(provider); -- колонка зашифрована
CREATE INDEX IF NOT EXISTS idx_verification_codes_expires ON verification_codes(expires_at);
-- Удаляем старую таблицу email_auth_tokens

View File

@@ -12,24 +12,24 @@ CREATE TABLE IF NOT EXISTS guest_user_mapping (
);
-- 2. Создание индексов для guest_user_mapping
CREATE INDEX IF NOT EXISTS idx_guest_user_mapping_guest_id ON guest_user_mapping(guest_id);
-- CREATE INDEX IF NOT EXISTS idx_guest_user_mapping_guest_id ON guest_user_mapping(guest_id); -- колонка зашифрована
CREATE INDEX IF NOT EXISTS idx_guest_user_mapping_user_id ON guest_user_mapping(user_id);
-- 3. Перенос гостевых идентификаторов из user_identities в guest_user_mapping
DO $$
BEGIN
-- Выполняем только если есть гостевые идентификаторы в user_identities
IF EXISTS (SELECT 1 FROM user_identities WHERE provider = 'guest') THEN
INSERT INTO guest_user_mapping (user_id, guest_id, processed)
SELECT user_id, provider_id, true
FROM user_identities
WHERE provider = 'guest'
ON CONFLICT (guest_id) DO NOTHING;
-- Удаляем перенесенные идентификаторы
DELETE FROM user_identities WHERE provider = 'guest';
END IF;
END $$;
-- 3. Перенос гостевых идентификаторов из user_identities в guest_user_mapping (пропускаем, колонки зашифрованы)
-- DO $$
-- BEGIN
-- -- Выполняем только если есть гостевые идентификаторы в user_identities
-- IF EXISTS (SELECT 1 FROM user_identities WHERE provider = 'guest') THEN
-- INSERT INTO guest_user_mapping (user_id, guest_id, processed)
-- SELECT user_id, provider_id, true
-- FROM user_identities
-- WHERE provider = 'guest'
-- ON CONFLICT (guest_id) DO NOTHING;
--
-- -- Удаляем перенесенные идентификаторы
-- DELETE FROM user_identities WHERE provider = 'guest';
-- END IF;
-- END $$;
-- 4. Добавление/обновление поля user_id в таблице messages
DO $$
@@ -71,74 +71,74 @@ BEFORE INSERT ON messages
FOR EACH ROW
EXECUTE FUNCTION set_message_user_id();
-- 7. Перенос идентификаторов из полей users в user_identities
DO $$
DECLARE
user_rec RECORD;
BEGIN
-- Обрабатываем email
FOR user_rec IN
SELECT id, email FROM users
WHERE email IS NOT NULL AND email != ''
LOOP
-- Проверяем, существует ли такой email в user_identities
IF NOT EXISTS (
SELECT 1 FROM user_identities
WHERE user_id = user_rec.id AND provider = 'email' AND provider_id = user_rec.email
) THEN
-- Если нет, добавляем его
INSERT INTO user_identities (user_id, provider, provider_id)
VALUES (user_rec.id, 'email', LOWER(user_rec.email));
END IF;
END LOOP;
-- Обрабатываем address (wallet)
FOR user_rec IN
SELECT id, address FROM users
WHERE address IS NOT NULL AND address != ''
LOOP
-- Проверяем, существует ли такой адрес в user_identities
IF NOT EXISTS (
SELECT 1 FROM user_identities
WHERE user_id = user_rec.id AND provider = 'wallet' AND provider_id = LOWER(user_rec.address)
) THEN
-- Если нет, добавляем его
INSERT INTO user_identities (user_id, provider, provider_id)
VALUES (user_rec.id, 'wallet', LOWER(user_rec.address));
END IF;
END LOOP;
END $$;
-- 7. Перенос идентификаторов из полей users в user_identities (пропускаем, колонки зашифрованы)
-- DO $$
-- DECLARE
-- user_rec RECORD;
-- BEGIN
-- -- Обрабатываем email
-- FOR user_rec IN
-- SELECT id, email FROM users
-- WHERE email IS NOT NULL AND email != ''
-- LOOP
-- -- Проверяем, существует ли такой email в user_identities
-- IF NOT EXISTS (
-- SELECT 1 FROM user_identities
-- WHERE user_id = user_rec.id AND provider = 'email' AND provider_id = user_rec.email
-- ) THEN
-- -- Если нет, добавляем его
-- INSERT INTO user_identities (user_id, provider, provider_id)
-- VALUES (user_rec.id, 'email', LOWER(user_rec.email));
-- END IF;
-- END LOOP;
--
-- -- Обрабатываем address (wallet)
-- FOR user_rec IN
-- SELECT id, address FROM users
-- WHERE address IS NOT NULL AND address != ''
-- LOOP
-- -- Проверяем, существует ли такой адрес в user_identities
-- IF NOT EXISTS (
-- SELECT 1 FROM user_identities
-- WHERE user_id = user_rec.id AND provider = 'wallet' AND provider_id = LOWER(user_rec.address)
-- ) THEN
-- -- Если нет, добавляем его
-- INSERT INTO user_identities (user_id, provider, provider_id)
-- VALUES (user_rec.id, 'wallet', LOWER(user_rec.address));
-- END IF;
-- END LOOP;
-- END $$;
-- 8. Очистка устаревших полей в таблице users
UPDATE users
SET
email = NULL,
address = NULL,
username = NULL
WHERE
email IS NOT NULL OR address IS NOT NULL OR username IS NOT NULL;
-- 8. Очистка устаревших полей в таблице users (пропускаем, колонки зашифрованы)
-- UPDATE users
-- SET
-- email = NULL,
-- address = NULL,
-- username = NULL
-- WHERE
-- email IS NOT NULL OR address IS NOT NULL OR username IS NOT NULL;
-- 9. Нормализация регистра для email и wallet идентификаторов
UPDATE user_identities
SET provider_id = LOWER(provider_id)
WHERE (provider = 'wallet' OR provider = 'email') AND provider_id != LOWER(provider_id);
-- 9. Нормализация регистра для email и wallet идентификаторов (пропускаем, колонки зашифрованы)
-- UPDATE user_identities
-- SET provider_id = LOWER(provider_id)
-- WHERE (provider = 'wallet' OR provider = 'email') AND provider_id != LOWER(provider_id);
-- 10. Ограничения для предотвращения использования guest в user_identities
ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS check_provider_not_guest;
ALTER TABLE user_identities ADD CONSTRAINT check_provider_not_guest
CHECK (provider != 'guest');
-- 10. Ограничения для предотвращения использования guest в user_identities (пропускаем, колонки зашифрованы)
-- ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS check_provider_not_guest;
-- ALTER TABLE user_identities ADD CONSTRAINT check_provider_not_guest
-- CHECK (provider != 'guest');
-- 11. Ограничение на допустимые типы идентификаторов
ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS check_provider_allowed;
ALTER TABLE user_identities ADD CONSTRAINT check_provider_allowed
CHECK (provider IN ('email', 'wallet', 'telegram'));
-- 11. Ограничение на допустимые типы идентификаторов (пропускаем, колонки зашифрованы)
-- ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS check_provider_allowed;
-- ALTER TABLE user_identities ADD CONSTRAINT check_provider_allowed
-- CHECK (provider IN ('email', 'wallet', 'telegram'));
-- 12. Помечаем обработанные гостевые идентификаторы
UPDATE guest_user_mapping
SET processed = true
WHERE processed = false AND NOT EXISTS (
SELECT 1 FROM guest_messages WHERE guest_id = guest_user_mapping.guest_id
);
-- 12. Помечаем обработанные гостевые идентификаторы (пропускаем, колонки зашифрованы)
-- UPDATE guest_user_mapping
-- SET processed = true
-- WHERE processed = false AND NOT EXISTS (
-- SELECT 1 FROM guest_messages WHERE guest_id = guest_user_mapping.guest_id
-- );
-- 13. Добавляем комментарии к таблицам и полям
COMMENT ON TABLE users IS 'Основная таблица пользователей системы';
@@ -149,16 +149,16 @@ COMMENT ON TABLE messages IS 'Сообщения пользователей и
COMMENT ON TABLE guest_messages IS 'Временное хранилище сообщений от неавторизованных пользователей';
COMMENT ON COLUMN users.id IS 'Уникальный идентификатор пользователя';
COMMENT ON COLUMN users.username IS 'Имя пользователя (устарело, используется user_identities)';
COMMENT ON COLUMN users.email IS 'Email пользователя (устарело, используется user_identities)';
COMMENT ON COLUMN users.address IS 'Адрес кошелька (устарело, используется user_identities)';
COMMENT ON COLUMN users.status IS 'Статус пользователя (active, blocked)';
-- COMMENT ON COLUMN users.username IS 'Имя пользователя (устарело, используется user_identities)'; -- колонка зашифрована
-- COMMENT ON COLUMN users.email IS 'Email пользователя (устарело, используется user_identities)'; -- колонка зашифрована
-- COMMENT ON COLUMN users.address IS 'Адрес кошелька (устарело, используется user_identities)'; -- колонка зашифрована
-- COMMENT ON COLUMN users.status IS 'Статус пользователя (active, blocked)'; -- колонка зашифрована
COMMENT ON COLUMN users.role IS 'Роль пользователя (user, admin)';
COMMENT ON COLUMN user_identities.provider IS 'Тип идентификатора (email, wallet, telegram, username)';
COMMENT ON COLUMN user_identities.provider_id IS 'Значение идентификатора';
-- COMMENT ON COLUMN user_identities.provider IS 'Тип идентификатора (email, wallet, telegram, username)'; -- колонка зашифрована
-- COMMENT ON COLUMN user_identities.provider_id IS 'Значение идентификатора'; -- колонка зашифрована
COMMENT ON COLUMN guest_user_mapping.guest_id IS 'Идентификатор гостя из localStorage';
-- COMMENT ON COLUMN guest_user_mapping.guest_id IS 'Идентификатор гостя из localStorage'; -- колонка зашифрована
COMMENT ON COLUMN guest_user_mapping.processed IS 'Флаг, показывающий, были ли обработаны гостевые сообщения';
-- 14. Создаем диагностическую функцию

View File

@@ -0,0 +1,11 @@
-- Отключаем триггер check_admin_role_trigger, который вызывает ошибку с зашифрованными полями
-- Проверка роли админа теперь происходит в JavaScript коде
-- Удаляем триггер
DROP TRIGGER IF EXISTS check_admin_role_trigger ON user_identities;
-- Удаляем функцию, так как она больше не нужна
DROP FUNCTION IF EXISTS check_admin_role() CASCADE;
-- Комментарий: Проверка роли админа теперь происходит в JavaScript коде
-- в файлах auth-service.js, admin-role.js и других сервисах

View File

@@ -1,52 +1,10 @@
-- Миграция для изменения структуры таблицы users
-- Переносим данные из email и address в user_identities, затем преобразуем эти поля в first_name и last_name
-- Сначала проверяем, что все email и address уже существуют в user_identities
DO $$
BEGIN
-- Переносим email в user_identities, если еще не перенесены
INSERT INTO user_identities (user_id, provider, provider_id)
SELECT id, 'email', email
FROM users
WHERE email IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM user_identities
WHERE user_id = users.id AND provider = 'email' AND provider_id = users.email
);
-- Переносим address в user_identities, если еще не перенесены
INSERT INTO user_identities (user_id, provider, provider_id)
SELECT id, 'wallet', address
FROM users
WHERE address IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM user_identities
WHERE user_id = users.id AND provider = 'wallet' AND provider_id = users.address
);
-- Логируем результаты миграции
RAISE NOTICE 'Данные из колонок email и address перенесены в таблицу user_identities';
END $$;
-- Теперь изменяем структуру таблицы users
ALTER TABLE users
DROP CONSTRAINT IF EXISTS users_email_key,
DROP CONSTRAINT IF EXISTS users_address_key;
-- Добавляем поля first_name и last_name (колонки email и address уже зашифрованы)
-- Добавляем временные колонки
ALTER TABLE users
ADD COLUMN first_name VARCHAR(255),
ADD COLUMN last_name VARCHAR(255);
-- Убираем уникальность и переименовываем колонки email и address
ALTER TABLE users
ALTER COLUMN email DROP NOT NULL,
ALTER COLUMN address DROP NOT NULL;
-- Удаляем колонки email и address
ALTER TABLE users
DROP COLUMN email,
DROP COLUMN address;
ADD COLUMN IF NOT EXISTS first_name VARCHAR(255),
ADD COLUMN IF NOT EXISTS last_name VARCHAR(255);
-- Добавляем комментарии к столбцам
COMMENT ON COLUMN users.first_name IS 'Имя пользователя';

View File

@@ -1,93 +1,8 @@
-- Миграция для исправления дублирующихся записей в user_identities из-за разного регистра букв
-- Исправляем записи для провайдеров wallet и email
-- Сначала удаляем существующее ограничение уникальности
ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS user_identities_provider_provider_id_key;
-- Создаем временную таблицу для хранения идентификаторов, которые нужно обработать
CREATE TEMP TABLE duplicate_identities AS
SELECT
provider,
LOWER(provider_id) as normalized_provider_id,
array_agg(id) as id_list,
array_agg(user_id) as user_id_list
FROM user_identities
WHERE provider IN ('wallet', 'email')
GROUP BY provider, LOWER(provider_id)
HAVING COUNT(*) > 1;
-- Логируем количество найденных дубликатов
DO $$
DECLARE
duplicate_count INTEGER;
BEGIN
SELECT COUNT(*) INTO duplicate_count FROM duplicate_identities;
RAISE NOTICE 'Найдено % групп дублирующихся идентификаторов', duplicate_count;
END $$;
-- Обновляем все записи, приводя provider_id к нижнему регистру
UPDATE user_identities
SET provider_id = LOWER(provider_id)
WHERE provider IN ('wallet', 'email');
-- Удаляем дублирующиеся записи, оставляя только одну для каждой комбинации (provider, provider_id)
WITH
duplicates AS (
SELECT
id,
provider,
provider_id,
ROW_NUMBER() OVER (
PARTITION BY provider, provider_id
ORDER BY id
) as row_num
FROM user_identities
WHERE provider IN ('wallet', 'email')
)
DELETE FROM user_identities
WHERE id IN (
SELECT id FROM duplicates WHERE row_num > 1
);
-- Удаляем дублирующиеся записи для одного пользователя
WITH
user_duplicates AS (
SELECT
id,
user_id,
provider,
provider_id,
ROW_NUMBER() OVER (
PARTITION BY user_id, provider, provider_id
ORDER BY id
) as row_num
FROM user_identities
WHERE provider IN ('wallet', 'email')
)
DELETE FROM user_identities
WHERE id IN (
SELECT id FROM user_duplicates WHERE row_num > 1
);
-- Добавляем обратно ограничение уникальности
ALTER TABLE user_identities
ADD CONSTRAINT user_identities_provider_provider_id_key
UNIQUE (provider, provider_id);
-- Добавляем уникальный индекс для пользователей
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_indexes
WHERE tablename = 'user_identities' AND indexname = 'unique_idx_user_identities_user_provider_provider_id'
) THEN
CREATE UNIQUE INDEX unique_idx_user_identities_user_provider_provider_id
ON user_identities(user_id, provider, provider_id);
END IF;
END $$;
-- Миграция для исправления дублирующихся записей в user_identities
-- Пропускаем операции с зашифрованными колонками
-- Логируем завершение миграции
DO $$
BEGIN
RAISE NOTICE 'Миграция для исправления дублирующихся идентификаторов завершена';
RAISE NOTICE 'Миграция для исправления дублирующихся идентификаторов пропущена (колонки зашифрованы)';
END $$;

View File

@@ -4,18 +4,44 @@
BEGIN;
-- Добавляем колонки для хранения файла и его метаданных в таблицу messages
ALTER TABLE messages
ADD COLUMN attachment_filename TEXT NULL,
ADD COLUMN attachment_mimetype TEXT NULL,
ADD COLUMN attachment_size BIGINT NULL,
ADD COLUMN attachment_data BYTEA NULL;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'messages' AND column_name = 'attachment_filename') THEN
ALTER TABLE messages ADD COLUMN attachment_filename TEXT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'messages' AND column_name = 'attachment_mimetype') THEN
ALTER TABLE messages ADD COLUMN attachment_mimetype TEXT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'messages' AND column_name = 'attachment_size') THEN
ALTER TABLE messages ADD COLUMN attachment_size BIGINT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'messages' AND column_name = 'attachment_data') THEN
ALTER TABLE messages ADD COLUMN attachment_data BYTEA NULL;
END IF;
END $$;
-- Добавляем колонки для хранения файла и его метаданных в таблицу guest_messages
ALTER TABLE guest_messages
ADD COLUMN attachment_filename TEXT NULL,
ADD COLUMN attachment_mimetype TEXT NULL,
ADD COLUMN attachment_size BIGINT NULL,
ADD COLUMN attachment_data BYTEA NULL;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'guest_messages' AND column_name = 'attachment_filename') THEN
ALTER TABLE guest_messages ADD COLUMN attachment_filename TEXT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'guest_messages' AND column_name = 'attachment_mimetype') THEN
ALTER TABLE guest_messages ADD COLUMN attachment_mimetype TEXT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'guest_messages' AND column_name = 'attachment_size') THEN
ALTER TABLE guest_messages ADD COLUMN attachment_size BIGINT NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'guest_messages' AND column_name = 'attachment_data') THEN
ALTER TABLE guest_messages ADD COLUMN attachment_data BYTEA NULL;
END IF;
END $$;
-- Удаляем старую колонку attachments из таблицы messages, если она существует
ALTER TABLE messages DROP COLUMN IF EXISTS attachments;
@@ -36,7 +62,7 @@ DROP COLUMN IF EXISTS attachment_size,
DROP COLUMN IF EXISTS attachment_data;
-- Пытаемся вернуть старую колонку (данные будут потеряны при откате)
-- Возможно, потребуется указать правильный тип (TEXT или JSONB), который был раньше
ALTER TABLE messages ADD COLUMN attachments TEXT NULL;
ALTER TABLE messages ADD COLUMN IF NOT EXISTS attachments TEXT NULL;
ALTER TABLE guest_messages
DROP COLUMN IF EXISTS attachment_filename,
@@ -45,6 +71,6 @@ DROP COLUMN IF EXISTS attachment_size,
DROP COLUMN IF EXISTS attachment_data;
-- Пытаемся вернуть старую колонку (данные будут потеряны при откате)
-- Возможно, потребуется указать правильный тип (TEXT или JSONB), который был раньше
ALTER TABLE guest_messages ADD COLUMN attachments TEXT NULL;
ALTER TABLE guest_messages ADD COLUMN IF NOT EXISTS attachments TEXT NULL;
COMMIT;

View File

@@ -3,13 +3,13 @@
BEGIN;
-- 1. Создаем таблицу для названий уровней ISIC
-- 1. Создаем таблицу для названий уровней ISIC (если не существует)
CREATE TABLE IF NOT EXISTS isic_rev4_level_names (
code_level INTEGER PRIMARY KEY,
level_name_en TEXT
level_name_en_encrypted TEXT
);
-- 2. Создаем основную таблицу для кодов ISIC
-- 2. Создаем основную таблицу для кодов ISIC (если не существует)
CREATE TABLE IF NOT EXISTS isic_rev4_codes (
sort_order INTEGER,
code VARCHAR(10) PRIMARY KEY,
@@ -23,83 +23,98 @@ CREATE TABLE IF NOT EXISTS isic_rev4_codes (
level4 VARCHAR(10),
level5 VARCHAR(10),
level6 VARCHAR(10),
CONSTRAINT fk_code_level FOREIGN KEY (code_level) REFERENCES isic_rev4_level_names (code_level) -- Добавляем внешний ключ
CONSTRAINT fk_code_level FOREIGN KEY (code_level) REFERENCES isic_rev4_level_names (code_level)
);
-- 3. Загружаем данные в isic_rev4_level_names
-- ВАЖНО: Укажите АБСОЛЮТНЫЙ ПУТЬ к CSV файлу ВНУТРИ Docker-контейнера backend,
-- где запущен PostgreSQL или откуда скрипт миграции имеет доступ к файлам.
-- Если CSV лежат в backend/db/data/isic/ и ваш Dockerfile копирует всю директорию backend
-- то путь может быть что-то вроде '/app/db/data/isic/isic_level_names.csv'
-- (где /app - это WORKDIR в вашем Dockerfile для backend сервиса)
-- Уточните этот путь!
COPY isic_rev4_level_names (code_level, level_name_en)
FROM '/mnt/isic_csv_data/isic_level_names.csv' -- <--- ПУТЬ СООТВЕТСТВУЕТ ТОМУ, ЧТО В volumes
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
-- 3. Загружаем данные в isic_rev4_level_names только если таблица пустая
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM isic_rev4_level_names LIMIT 1) THEN
-- Создаем временную таблицу для импорта
CREATE TEMP TABLE tmp_isic_level_names (
code_level_tmp INTEGER,
level_name_en_tmp TEXT
) ON COMMIT DROP;
-- Загружаем данные во временную таблицу
COPY tmp_isic_level_names (code_level_tmp, level_name_en_tmp)
FROM '/app/db/data/isic_level_names.csv'
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
-- Вставляем данные в основную таблицу
INSERT INTO isic_rev4_level_names (code_level, level_name_en_encrypted)
SELECT code_level_tmp, level_name_en_tmp FROM tmp_isic_level_names;
END IF;
END $$;
-- 4. Создаем временные таблицы для импорта основных данных ISIC
CREATE TEMP TABLE tmp_isic_titles (
sort_order_tmp INTEGER,
code_tmp VARCHAR(10),
description_tmp TEXT,
inclusion_tmp TEXT,
exclusion_tmp TEXT
) ON COMMIT DROP; -- Временная таблица удалится после коммита
-- 4. Загружаем данные в isic_rev4_codes только если таблица пустая
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM isic_rev4_codes LIMIT 1) THEN
-- Создаем временные таблицы для импорта основных данных ISIC
CREATE TEMP TABLE tmp_isic_titles (
sort_order_tmp INTEGER,
code_tmp VARCHAR(10),
description_tmp TEXT,
inclusion_tmp TEXT,
exclusion_tmp TEXT
) ON COMMIT DROP;
CREATE TEMP TABLE tmp_isic_structure (
sort_order_tmp INTEGER,
code_tmp VARCHAR(10),
code_level_tmp INTEGER,
level1_tmp VARCHAR(10),
level2_tmp VARCHAR(10),
level3_tmp VARCHAR(10),
level4_tmp VARCHAR(10),
level5_tmp VARCHAR(10),
level6_tmp VARCHAR(10)
) ON COMMIT DROP; -- Временная таблица удалится после коммита
CREATE TEMP TABLE tmp_isic_structure (
sort_order_tmp INTEGER,
code_tmp VARCHAR(10),
code_level_tmp INTEGER,
level1_tmp VARCHAR(10),
level2_tmp VARCHAR(10),
level3_tmp VARCHAR(10),
level4_tmp VARCHAR(10),
level5_tmp VARCHAR(10),
level6_tmp VARCHAR(10)
) ON COMMIT DROP;
-- 5. Загружаем данные во временные таблицы
-- Опять же, укажите правильные АБСОЛЮТНЫЕ ПУТИ внутри контейнера
COPY tmp_isic_titles (sort_order_tmp, code_tmp, description_tmp, inclusion_tmp, exclusion_tmp)
FROM '/mnt/isic_csv_data/isic_titles.csv' -- <--- ПУТЬ СООТВЕТСТВУЕТ ТОМУ, ЧТО В volumes
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
-- Загружаем данные во временные таблицы
COPY tmp_isic_titles (sort_order_tmp, code_tmp, description_tmp, inclusion_tmp, exclusion_tmp)
FROM '/app/db/data/isic_titles.csv'
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
COPY tmp_isic_structure (sort_order_tmp, code_tmp, code_level_tmp, level1_tmp, level2_tmp, level3_tmp, level4_tmp, level5_tmp, level6_tmp)
FROM '/mnt/isic_csv_data/isic_structure.csv' -- <--- ПУТЬ СООТВЕТСТВУЕТ ТОМУ, ЧТО В volumes
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
COPY tmp_isic_structure (sort_order_tmp, code_tmp, code_level_tmp, level1_tmp, level2_tmp, level3_tmp, level4_tmp, level5_tmp, level6_tmp)
FROM '/app/db/data/isic_structure.csv'
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
-- 6. Переносим и объединяем данные из временных таблиц в основную таблицу isic_rev4_codes
INSERT INTO isic_rev4_codes (
sort_order,
code,
description,
explanatory_note_inclusion,
explanatory_note_exclusion,
code_level,
level1,
level2,
level3,
level4,
level5,
level6
)
SELECT
COALESCE(t.sort_order_tmp, s.sort_order_tmp),
s.code_tmp,
t.description_tmp,
t.inclusion_tmp,
t.exclusion_tmp,
s.code_level_tmp,
s.level1_tmp,
s.level2_tmp,
s.level3_tmp,
s.level4_tmp,
s.level5_tmp,
s.level6_tmp
FROM
tmp_isic_structure s
LEFT JOIN
tmp_isic_titles t ON s.code_tmp = t.code_tmp;
-- Переносим и объединяем данные из временных таблиц в основную таблицу isic_rev4_codes
INSERT INTO isic_rev4_codes (
sort_order,
code,
description,
explanatory_note_inclusion,
explanatory_note_exclusion,
code_level,
level1,
level2,
level3,
level4,
level5,
level6
)
SELECT
COALESCE(t.sort_order_tmp, s.sort_order_tmp),
s.code_tmp,
t.description_tmp,
t.inclusion_tmp,
t.exclusion_tmp,
s.code_level_tmp,
s.level1_tmp,
s.level2_tmp,
s.level3_tmp,
s.level4_tmp,
s.level5_tmp,
s.level6_tmp
FROM
tmp_isic_structure s
LEFT JOIN
tmp_isic_titles t ON s.code_tmp = t.code_tmp;
END IF;
END $$;
COMMIT;

View File

@@ -1,17 +1,18 @@
-- Создаем таблицу email_settings если она не существует
CREATE TABLE IF NOT EXISTS email_settings (
id SERIAL PRIMARY KEY,
smtp_host VARCHAR(255) NOT NULL,
smtp_host_encrypted TEXT,
smtp_port INTEGER NOT NULL,
smtp_user VARCHAR(255) NOT NULL,
smtp_password VARCHAR(255) NOT NULL,
imap_host VARCHAR(255),
smtp_user_encrypted TEXT,
smtp_password_encrypted TEXT,
imap_host_encrypted TEXT,
imap_port INTEGER,
from_email VARCHAR(255) NOT NULL,
from_email_encrypted TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Для простоты предполагаем, что настройки всегда одни (id=1)
INSERT INTO email_settings (smtp_host, smtp_port, smtp_user, smtp_password, imap_host, imap_port, from_email)
VALUES ('smtp.example.com', 465, 'user@example.com', 'password', 'imap.example.com', 993, 'noreply@example.com')
ON CONFLICT DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO email_settings (smtp_host, smtp_port, smtp_user, smtp_password, imap_host, imap_port, from_email)
-- VALUES ('smtp.example.com', 465, 'user@example.com', 'password', 'imap.example.com', 993, 'noreply@example.com')
-- ON CONFLICT DO NOTHING;

View File

@@ -1,12 +1,13 @@
-- Создаем таблицу telegram_settings если она не существует
CREATE TABLE IF NOT EXISTS telegram_settings (
id SERIAL PRIMARY KEY,
bot_token VARCHAR(255) NOT NULL,
bot_username VARCHAR(255) NOT NULL,
bot_token_encrypted TEXT,
bot_username_encrypted TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Для простоты предполагаем, что настройки всегда одни (id=1)
INSERT INTO telegram_settings (bot_token, bot_username)
VALUES ('your-telegram-bot-token', 'your_bot_username')
ON CONFLICT DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO telegram_settings (bot_token, bot_username)
-- VALUES ('your-telegram-bot-token', 'your_bot_username')
-- ON CONFLICT DO NOTHING;

View File

@@ -1,15 +1,16 @@
-- Создаем таблицу db_settings если она не существует
CREATE TABLE IF NOT EXISTS db_settings (
id SERIAL PRIMARY KEY,
db_host VARCHAR(255) NOT NULL,
db_host_encrypted TEXT,
db_port INTEGER NOT NULL,
db_name VARCHAR(255) NOT NULL,
db_user VARCHAR(255) NOT NULL,
db_password VARCHAR(255) NOT NULL,
db_name_encrypted TEXT,
db_user_encrypted TEXT,
db_password_encrypted TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Для простоты предполагаем, что настройки всегда одни (id=1)
INSERT INTO db_settings (db_host, db_port, db_name, db_user, db_password)
VALUES ('postgres', 5432, 'dapp_db', 'dapp_user', 'dapp_password')
ON CONFLICT DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO db_settings (db_host, db_port, db_name, db_user, db_password)
-- VALUES ('postgres', 5432, 'dapp_db', 'dapp_user', 'dapp_password')
-- ON CONFLICT DO NOTHING;

View File

@@ -1,14 +1,16 @@
-- Создаем таблицу ai_providers_settings если она не существует
CREATE TABLE IF NOT EXISTS ai_providers_settings (
id SERIAL PRIMARY KEY,
provider VARCHAR(32) NOT NULL UNIQUE, -- openai, anthropic, google, ollama
api_key VARCHAR(255),
base_url VARCHAR(255),
selected_model VARCHAR(128),
provider_encrypted TEXT,
api_key_encrypted TEXT,
base_url_encrypted TEXT,
selected_model_encrypted TEXT,
embedding_model_encrypted TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Пример заполнения для Ollama (без ключа)
INSERT INTO ai_providers_settings (provider, base_url, selected_model)
VALUES ('ollama', 'http://localhost:11434', 'qwen2.5')
ON CONFLICT (provider) DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO ai_providers_settings (provider, base_url, selected_model)
-- VALUES ('ollama', 'http://localhost:11434', 'qwen2.5')
-- ON CONFLICT (provider) DO NOTHING;

View File

@@ -1,21 +1,22 @@
-- Создаем таблицу ai_assistant_settings если она не существует
CREATE TABLE IF NOT EXISTS ai_assistant_settings (
id SERIAL PRIMARY KEY,
system_prompt TEXT,
system_prompt_encrypted TEXT,
selected_rag_tables INTEGER[],
languages TEXT[],
model TEXT,
model_encrypted TEXT,
rules JSONB,
updated_at TIMESTAMP DEFAULT NOW(),
updated_by INTEGER
);
-- Вставить дефолтную строку (глобальные настройки)
INSERT INTO ai_assistant_settings (system_prompt, selected_rag_tables, languages, model, rules)
VALUES (
'Вы — полезный ассистент. Отвечайте на русском языке.',
ARRAY[]::INTEGER[],
ARRAY['ru'],
'qwen2.5',
'{"checkUserTags": true, "searchRagFirst": true, "generateIfNoRag": true, "requireAdminApproval": true}'
)
ON CONFLICT DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO ai_assistant_settings (system_prompt, selected_rag_tables, languages, model, rules)
-- VALUES (
-- 'Вы — полезный ассистент. Отвечайте на русском языке.',
-- ARRAY[]::INTEGER[],
-- ARRAY['ru'],
-- 'qwen2.5',
-- '{"checkUserTags": true, "searchRagFirst": true, "generateIfNoRag": true, "requireAdminApproval": true}'
-- )
-- ON CONFLICT DO NOTHING;

View File

@@ -1,11 +1,11 @@
-- Создание справочной таблицы is_rag_source
CREATE TABLE IF NOT EXISTS is_rag_source (
id SERIAL PRIMARY KEY,
name VARCHAR(64) NOT NULL UNIQUE
name_encrypted TEXT
);
-- Заполнение начальными значениями
INSERT INTO is_rag_source (name) VALUES
('Да'),
('Нет')
ON CONFLICT (name) DO NOTHING;
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- INSERT INTO is_rag_source (name) VALUES
-- ('Да'),
-- ('Нет')
-- ON CONFLICT (name) DO NOTHING;

View File

@@ -1,2 +1,11 @@
ALTER TABLE user_tables
ADD COLUMN is_rag_source_id INTEGER REFERENCES is_rag_source(id) DEFAULT 2; -- 2 = 'Нет'
-- Добавляем колонку is_rag_source_id если она не существует
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'user_tables' AND column_name = 'is_rag_source_id'
) THEN
ALTER TABLE user_tables
ADD COLUMN is_rag_source_id INTEGER REFERENCES is_rag_source(id) DEFAULT 2; -- 2 = 'Нет'
END IF;
END $$;

View File

@@ -0,0 +1,5 @@
-- Добавляем колонку options в таблицу user_columns
ALTER TABLE user_columns ADD COLUMN IF NOT EXISTS options JSONB DEFAULT '{}'::jsonb;
-- Создаем индекс для быстрого поиска по options
CREATE INDEX IF NOT EXISTS idx_user_columns_options ON user_columns USING GIN (options);

View File

@@ -1,21 +1,22 @@
-- Миграция: наполнение таблиц rpc_providers и auth_tokens начальными значениями
-- Пропускаем INSERT, так как данные должны быть зашифрованы
-- Добавление RPC-провайдеров
INSERT INTO rpc_providers (network_id, rpc_url, chain_id)
VALUES
('bsc', 'https://bsc-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 56),
('ethereum', 'https://eth-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 1),
('arbitrum', 'https://arb1.arbitrum.io/rpc', 42161),
('polygon', 'https://polygon.drpc.org', 137),
('sepolia', 'https://eth-sepolia.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 11155111)
ON CONFLICT (network_id) DO NOTHING;
-- Добавление RPC-провайдеров (пропускаем, данные должны быть зашифрованы)
-- INSERT INTO rpc_providers (network_id, rpc_url, chain_id)
-- VALUES
-- ('bsc', 'https://bsc-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 56),
-- ('ethereum', 'https://eth-mainnet.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 1),
-- ('arbitrum', 'https://arb1.arbitrum.io/rpc', 42161),
-- ('polygon', 'https://polygon.drpc.org', 137),
-- ('sepolia', 'https://eth-sepolia.nodereal.io/v1/56dec8028bae4f26b76099a42dae2b52', 11155111)
-- ON CONFLICT (network_id) DO NOTHING;
-- Добавление токенов для аутентификации админа
INSERT INTO auth_tokens (name, address, network, min_balance)
VALUES
('HB3A', '0x4b294265720b09ca39bfba18c7e368413c0f68eb', 'bsc', 10.0),
('HB3A', '0xd95a45fc46a7300e6022885afec3d618d7d3f27c', 'ethereum', 10.0),
('test2', '0xef49261169B454f191678D2aFC5E91Ad2e85dfD8', 'sepolia', 50.0),
('HB3A', '0x351f59de4fedbdf7601f5592b93db3b9330c1c1d', 'polygon', 10.0),
('HB3A', '0xdCe769b847a0a697239777D0B1C7dd33b6012ba0', 'arbitrum', 100.0)
ON CONFLICT (address, network) DO NOTHING;
-- Добавление токенов для аутентификации админа (пропускаем, данные должны быть зашифрованы)
-- INSERT INTO auth_tokens (name, address, network, min_balance)
-- VALUES
-- ('HB3A', '0x4b294265720b09ca39bfba18c7e368413c0f68eb', 'bsc', 10.0),
-- ('HB3A', '0xd95a45fc46a7300e6022885afec3d618d7d3f27c', 'ethereum', 10.0),
-- ('test2', '0xef49261169B454f191678D2aFC5E91Ad2e85dfD8', 'sepolia', 50.0),
-- ('HB3A', '0x351f59de4fedbdf7601f5592b93db3b9330c1c1d', 'polygon', 10.0),
-- ('HB3A', '0xdCe769b847a0a697239777D0B1C7dd33b6012ba0', 'arbitrum', 100.0)
-- ON CONFLICT (address, network) DO NOTHING;

View File

@@ -1,16 +1,24 @@
-- 048_add_order_to_user_rows.sql
-- Добавляет поле order в user_rows для поддержки сортировки строк
ALTER TABLE user_rows ADD COLUMN "order" INTEGER DEFAULT 0;
-- Проставить уникальные значения order для существующих строк (по id)
-- Добавляем колонку order если она не существует
DO $$
DECLARE
r RECORD;
idx INTEGER := 1;
BEGIN
FOR r IN SELECT id FROM user_rows ORDER BY id LOOP
UPDATE user_rows SET "order" = idx WHERE id = r.id;
idx := idx + 1;
END LOOP;
END$$;
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'user_rows' AND column_name = 'order'
) THEN
ALTER TABLE user_rows ADD COLUMN "order" INTEGER DEFAULT 0;
-- Проставить уникальные значения order для существующих строк (по id)
DECLARE
r RECORD;
idx INTEGER := 1;
BEGIN
FOR r IN SELECT id FROM user_rows ORDER BY id LOOP
UPDATE user_rows SET "order" = idx WHERE id = r.id;
idx := idx + 1;
END LOOP;
END;
END IF;
END $$;

View File

@@ -1,40 +1,8 @@
-- Скрипт для ручного исправления дублирующихся записей в базе данных
-- Пропускаем операции с зашифрованными колонками
-- 1. Удаляем существующее ограничение уникальности
ALTER TABLE user_identities DROP CONSTRAINT IF EXISTS user_identities_provider_provider_id_key;
-- 2. Получаем список идентификаторов с дублирующимися записями
SELECT
provider,
LOWER(provider_id) as normalized_provider_id,
array_agg(id) as id_list
FROM user_identities
WHERE provider IN ('wallet', 'email')
GROUP BY provider, LOWER(provider_id)
HAVING COUNT(*) > 1;
-- 3. Удаляем конкретные дублирующиеся записи по ID (например, ID=2)
DELETE FROM user_identities WHERE id = 2;
-- 4. Обновляем все записи email и wallet к нижнему регистру
UPDATE user_identities
SET provider_id = LOWER(provider_id)
WHERE provider IN ('wallet', 'email');
-- 5. Проверяем, что дубликаты удалены
SELECT
provider,
provider_id,
COUNT(*) as count
FROM user_identities
GROUP BY provider, provider_id
HAVING COUNT(*) > 1;
-- 6. Добавляем обратно ограничение уникальности
ALTER TABLE user_identities
ADD CONSTRAINT user_identities_provider_provider_id_key
UNIQUE (provider, provider_id);
-- 7. Создаем дополнительный индекс для (user_id, provider, provider_id)
CREATE UNIQUE INDEX IF NOT EXISTS unique_idx_user_identities_user_provider_provider_id
ON user_identities(user_id, provider, provider_id);
-- Логируем завершение миграции
DO $$
BEGIN
RAISE NOTICE 'Миграция fix_duplicates_manual.sql пропущена (колонки зашифрованы)';
END $$;