|
|
@@ -1,270 +1,246 @@
|
|
|
-#!/usr/bin/env coffee
|
|
|
-
|
|
|
-# Скрипт для добавления тестовых мероприятий в CouchDB
|
|
|
-
|
|
|
+# Подключение необходимых модулей
|
|
|
+CouchDB = require '../vue/app/core/CouchdbClass.coffee'
|
|
|
+debug = require('../../../utils/coffee/debug.coffee').default
|
|
|
class EventSeeder
|
|
|
- constructor: ->
|
|
|
- @baseUrl = 'http://localhost:5984'
|
|
|
- @dbName = 'kohi_borbad_events'
|
|
|
- @headers =
|
|
|
- 'Content-Type': 'application/json'
|
|
|
- 'Authorization': 'Basic ' + Buffer.from('oleg:631074').toString('base64')
|
|
|
+ constructor: ->
|
|
|
+ @dbName = 'borbad_events'
|
|
|
+ @baseUrl = 'http://oleg:631074@localhost:5984'
|
|
|
+ @couch = new CouchDB(@baseUrl, @dbName)
|
|
|
+ @designDoc =
|
|
|
+ _id: '_design/app'
|
|
|
+ views: {}
|
|
|
+ lists: {}
|
|
|
+ shows: {}
|
|
|
+
|
|
|
+ # Версия design документа для контроля обновлений
|
|
|
+ @designVersion = '1.0'
|
|
|
|
|
|
- # Тестовые мероприятия
|
|
|
- @testEvents = [
|
|
|
- {
|
|
|
- _id: 'event_classical_001'
|
|
|
- title: 'Концерт симфонического оркестра'
|
|
|
- date: '2025-10-15'
|
|
|
- time: '19:00'
|
|
|
- description: 'Произведения Чайковского и Рахманинова в исполнении Национального симфонического оркестра под руководством маэстро Фирдавса Абдурахмонова. Незабываемый вечер классической музыки в акустике мирового уровня.'
|
|
|
- shortDescription: 'Шедевры классической музыки в исполнении Национального симфонического оркестра'
|
|
|
- image: '/images/event-classical.jpg'
|
|
|
- category: 'classical'
|
|
|
- price: 50
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 30 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 45
|
|
|
- isFeatured: true
|
|
|
- inSlider: true
|
|
|
- cta: 'Купить билеты'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_folk_001'
|
|
|
- title: 'Вечер таджикской народной музыки'
|
|
|
- date: '2025-10-20'
|
|
|
- time: '18:30'
|
|
|
- description: 'Выступление фольклорного ансамбля "Шашмаком" с программой традиционных мелодий и танцев. Погрузитесь в богатую культурную традицию Таджикистана через музыку, песни и танцы.'
|
|
|
- shortDescription: 'Традиционные мелодии и танцы Таджикистана'
|
|
|
- image: '/images/event-folk.jpg'
|
|
|
- category: 'folk'
|
|
|
- price: 30
|
|
|
- venue: 'Малый зал'
|
|
|
- duration: '2 часа'
|
|
|
- ageRestriction: '6+'
|
|
|
- availableTickets: 28
|
|
|
- isFeatured: true
|
|
|
- inSlider: true
|
|
|
- cta: 'Узнать больше'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_jazz_001'
|
|
|
- title: 'Джазовый фестиваль "Borbad Jazz"'
|
|
|
- date: '2025-10-25'
|
|
|
- time: '20:00'
|
|
|
- description: 'Международные джазовые коллективы из Европы и Азии в уникальной акустике зала. Три дня незабываемой музыки от лучших джазменов мира. От традиционного джаза до современных экспериментов.'
|
|
|
- shortDescription: 'Международные джазовые коллективы'
|
|
|
- image: '/images/event-jazz.jpg'
|
|
|
- category: 'jazz'
|
|
|
- price: 70
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '3 часа'
|
|
|
- ageRestriction: '16+'
|
|
|
- availableTickets: 15
|
|
|
- isFeatured: true
|
|
|
- inSlider: true
|
|
|
- cta: 'Смотреть расписание'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_pop_001'
|
|
|
- title: 'Концерт популярной музыки'
|
|
|
- date: '2025-10-28'
|
|
|
- time: '19:30'
|
|
|
- description: 'Лучшие поп-исполнители Таджикистана представят новые хиты и классические композиции. Энергичное шоу с современной хореографией и световыми эффектами.'
|
|
|
- shortDescription: 'Лучшие поп-исполнители страны'
|
|
|
- image: '/images/event-pop.jpg'
|
|
|
- category: 'pop'
|
|
|
- price: 45
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 15 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 67
|
|
|
- isFeatured: true
|
|
|
- inSlider: false
|
|
|
- cta: 'Купить билеты'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_opera_001'
|
|
|
- title: 'Оперный гала-концерт'
|
|
|
- date: '2025-11-02'
|
|
|
- time: '18:00'
|
|
|
- description: 'Известные оперные певцы исполнят арии из мировых шедевров оперного искусства. Вечер великой музыки в исполнении мастеров оперной сцены.'
|
|
|
- shortDescription: 'Арии из мировых оперных шедевров'
|
|
|
- image: '/images/event-opera.jpg'
|
|
|
- category: 'classical'
|
|
|
- price: 80
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 45 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 23
|
|
|
- isFeatured: false
|
|
|
- inSlider: false
|
|
|
- cta: 'Забронировать места'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_dance_001'
|
|
|
- title: 'Танцевальное шоу "Восточные ритмы"'
|
|
|
- date: '2025-11-05'
|
|
|
- time: '19:00'
|
|
|
- description: 'Традиционные и современные танцевальные коллективы представят красочное шоу. Яркие костюмы, зажигательная музыка и мастерство танцовщиков со всего Таджикистана.'
|
|
|
- shortDescription: 'Традиционные и современные танцы'
|
|
|
- image: '/images/event-dance.jpg'
|
|
|
- category: 'dance'
|
|
|
- price: 35
|
|
|
- venue: 'Большой зал'
|
|
|
- duration: '2 часа 30 минут'
|
|
|
- ageRestriction: '6+'
|
|
|
- availableTickets: 89
|
|
|
- isFeatured: true
|
|
|
- inSlider: true
|
|
|
- cta: 'Посмотреть программу'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_chamber_001'
|
|
|
- title: 'Камерная музыка: Струнный квартет'
|
|
|
- date: '2025-11-08'
|
|
|
- time: '17:00'
|
|
|
- description: 'Изысканная программа камерной музыки в исполнении ведущего струнного квартета страны. Интимная атмосфера и тонкое звучание в акустике камерного зала.'
|
|
|
- shortDescription: 'Изысканная камерная музыка'
|
|
|
- image: '/images/event-chamber.jpg'
|
|
|
- category: 'classical'
|
|
|
- price: 40
|
|
|
- venue: 'Камерный зал'
|
|
|
- duration: '1 час 45 минут'
|
|
|
- ageRestriction: '12+'
|
|
|
- availableTickets: 34
|
|
|
- isFeatured: false
|
|
|
- inSlider: false
|
|
|
- cta: 'Приобрести билеты'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- {
|
|
|
- _id: 'event_experimental_001'
|
|
|
- title: 'Фестиваль современной музыки'
|
|
|
- date: '2025-11-12'
|
|
|
- time: '20:30'
|
|
|
- description: 'Экспериментальные проекты и инновационные музыкальные направления. Откройте для себя новые грани музыкального искусства от молодых композиторов и исполнителей.'
|
|
|
- shortDescription: 'Экспериментальные музыкальные проекты'
|
|
|
- image: '/images/event-modern.jpg'
|
|
|
- category: 'experimental'
|
|
|
- price: 55
|
|
|
- venue: 'Малый зал'
|
|
|
- duration: '3 часа'
|
|
|
- ageRestriction: '18+'
|
|
|
- availableTickets: 18
|
|
|
- isFeatured: false
|
|
|
- inSlider: true
|
|
|
- cta: 'Исследовать программу'
|
|
|
- createdAt: new Date().toISOString()
|
|
|
- updatedAt: new Date().toISOString()
|
|
|
- }
|
|
|
- ]
|
|
|
-
|
|
|
- # Проверить существование базы данных
|
|
|
- checkDatabase: ->
|
|
|
- try
|
|
|
- response = await fetch("#{@baseUrl}/#{@dbName}", {
|
|
|
- method: 'GET'
|
|
|
- headers: @headers
|
|
|
- })
|
|
|
-
|
|
|
- if response.ok
|
|
|
- console.log '✅ База данных существует'
|
|
|
- return true
|
|
|
- else if response.status == 404
|
|
|
- console.log '📁 База данных не существует, создаем...'
|
|
|
- return await this.createDatabase()
|
|
|
- else
|
|
|
- console.error '❌ Ошибка проверки базы данных:', response.statusText
|
|
|
- return false
|
|
|
- catch error
|
|
|
- console.error '❌ Ошибка подключения к CouchDB:', error.message
|
|
|
- return false
|
|
|
-
|
|
|
- # Создать базу данных
|
|
|
- createDatabase: ->
|
|
|
- try
|
|
|
- response = await fetch("#{@baseUrl}/#{@dbName}", {
|
|
|
- method: 'PUT'
|
|
|
- headers: @headers
|
|
|
- })
|
|
|
-
|
|
|
- if response.ok
|
|
|
- console.log '✅ База данных создана успешно'
|
|
|
- return true
|
|
|
- else
|
|
|
- console.error '❌ Ошибка создания базы данных:', response.statusText
|
|
|
- return false
|
|
|
- catch error
|
|
|
- console.error '❌ Ошибка создания базы данных:', error.message
|
|
|
- return false
|
|
|
-
|
|
|
- # Добавить мероприятие
|
|
|
- addEvent: (event) ->
|
|
|
- try
|
|
|
- response = await fetch("#{@baseUrl}/#{@dbName}/#{event._id}", {
|
|
|
- method: 'PUT'
|
|
|
- headers: @headers
|
|
|
- body: JSON.stringify(event)
|
|
|
- })
|
|
|
-
|
|
|
- if response.ok
|
|
|
- result = await response.json()
|
|
|
- console.log "✅ Мероприятие добавлено: #{event.title}"
|
|
|
- return { success: true, id: result.id }
|
|
|
- else
|
|
|
- console.error "❌ Ошибка добавления мероприятия #{event.title}:", response.statusText
|
|
|
- return { success: false, error: response.statusText }
|
|
|
- catch error
|
|
|
- console.error "❌ Ошибка добавления мероприятия #{event.title}:", error.message
|
|
|
- return { success: false, error: error.message }
|
|
|
-
|
|
|
- # Основная функция заполнения базы
|
|
|
- seed: ->
|
|
|
- console.log '🎭 Начало заполнения базы данных мероприятиями...'
|
|
|
+ # Проверка существования базы данных
|
|
|
+ checkDatabase: ->
|
|
|
+ try
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName)
|
|
|
+ if response.status == 404
|
|
|
+ debug.log "База данных не найдена, создаем новую"
|
|
|
+ await this.createDatabase()
|
|
|
+ else if response.status == 200
|
|
|
+ debug.log "База данных найдена"
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при проверке базы: "+response.status
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при проверке базы данных: "+error
|
|
|
+
|
|
|
+ # Создание базы данных
|
|
|
+ createDatabase: ->
|
|
|
+ try
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName,
|
|
|
+ method: 'PUT'
|
|
|
+ headers:
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ )
|
|
|
+ if response.status == 201
|
|
|
+ debug.log "База данных успешно создана"
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при создании базы: "+response.status
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при создании базы данных: "+error
|
|
|
|
|
|
- # Проверяем базу данных
|
|
|
- databaseExists = await this.checkDatabase()
|
|
|
- if not databaseExists
|
|
|
- console.log '❌ Не удалось подключиться к базе данных'
|
|
|
- process.exit(1)
|
|
|
+ # Проверка и создание/обновление design документов
|
|
|
+ setupDesignDocuments: ->
|
|
|
+ try
|
|
|
+ # Получаем текущий design документ
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName+"/_design/app")
|
|
|
+
|
|
|
+ if response.status == 200
|
|
|
+ existingDoc = await response.json()
|
|
|
+ # Проверяем версию
|
|
|
+ if existingDoc.version != @designVersion
|
|
|
+ debug.log "Обновляем design документ до версии "+@designVersion
|
|
|
+ @designDoc._rev = existingDoc._rev
|
|
|
+ @designDoc.version = @designVersion
|
|
|
+ await this.updateDesignDoc()
|
|
|
+ else
|
|
|
+ debug.log "Design документ актуален"
|
|
|
+ else if response.status == 404
|
|
|
+ debug.log "Design документ не найден, создаем новый"
|
|
|
+ @designDoc.version = @designVersion
|
|
|
+ await this.createDesignDoc()
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при проверке design документа: "+response.status
|
|
|
+
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при настройке design документов: "+error
|
|
|
|
|
|
- # Добавляем мероприятия
|
|
|
- successCount = 0
|
|
|
- for event in @testEvents
|
|
|
- result = await this.addEvent(event)
|
|
|
- if result.success
|
|
|
- successCount += 1
|
|
|
- # Небольшая задержка между запросами
|
|
|
- await new Promise (resolve) -> setTimeout resolve, 100
|
|
|
+ # Создание design документа
|
|
|
+ createDesignDoc: ->
|
|
|
+ try
|
|
|
+ # Определяем views
|
|
|
+ @designDoc.views =
|
|
|
+ # Все записи блога
|
|
|
+ all_blog_posts:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.type === 'blog_post' || doc.type === 'slide' || doc.type === 'event') {
|
|
|
+ emit(doc.created_at, doc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # Только мероприятия
|
|
|
+ events_only:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.type === 'event') {
|
|
|
+ emit(doc.event_date, doc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # Только слайды
|
|
|
+ slides_only:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.type === 'slide') {
|
|
|
+ emit(doc.order, doc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # Поиск по заголовку
|
|
|
+ by_title:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.title) {
|
|
|
+ emit(doc.title.toLowerCase(), doc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # Поиск по тегам
|
|
|
+ by_tags:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.tags && Array.isArray(doc.tags)) {
|
|
|
+ doc.tags.forEach(function(tag) {
|
|
|
+ emit(tag.toLowerCase(), doc);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ # Активные мероприятия (будущие)
|
|
|
+ active_events:
|
|
|
+ map: """
|
|
|
+ function(doc) {
|
|
|
+ if (doc.type === 'event' && doc.event_date) {
|
|
|
+ var eventDate = new Date(doc.event_date);
|
|
|
+ var now = new Date();
|
|
|
+ if (eventDate >= now) {
|
|
|
+ emit(doc.event_date, doc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """
|
|
|
+
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName+"/_design/app",
|
|
|
+ method: 'PUT'
|
|
|
+ headers:
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ body: JSON.stringify(@designDoc)
|
|
|
+ )
|
|
|
+
|
|
|
+ if response.status == 201
|
|
|
+ debug.log "Design документ успешно создан"
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при создании design документа: "+response.status
|
|
|
+
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при создании design документа: "+error
|
|
|
|
|
|
- console.log "\n🎉 Заполнение завершено!"
|
|
|
- console.log "✅ Успешно добавлено: #{successCount} из #{@testEvents.length} мероприятий"
|
|
|
+ # Обновление design документа
|
|
|
+ updateDesignDoc: ->
|
|
|
+ try
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName+"/_design/app",
|
|
|
+ method: 'PUT'
|
|
|
+ headers:
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ body: JSON.stringify(@designDoc)
|
|
|
+ )
|
|
|
+
|
|
|
+ if response.status == 201
|
|
|
+ debug.log "Design документ успешно обновлен"
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при обновлении design документа: "+response.status
|
|
|
+
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при обновлении design документа: "+error
|
|
|
|
|
|
- if successCount == @testEvents.length
|
|
|
- console.log '🎊 Все мероприятия успешно добавлены в базу данных!'
|
|
|
- else
|
|
|
- console.log '⚠️ Некоторые мероприятия не были добавлены'
|
|
|
+ # Добавление тестовых данных
|
|
|
+ seedTestData: ->
|
|
|
+ testData = [
|
|
|
+ {
|
|
|
+ _id: 'slide_welcome'
|
|
|
+ type: 'slide'
|
|
|
+ title: 'Добро пожаловать в Кохи Борбад'
|
|
|
+ content: '# Концертный зал Борбад\n\nПриветствуем вас в самом современном концертном зале Душанбе!'
|
|
|
+ image: '/assets/borbad.s5l.ru/welcome-slide.jpg'
|
|
|
+ order: 1
|
|
|
+ active: true
|
|
|
+ created_at: new Date().toISOString()
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
+ }
|
|
|
+ {
|
|
|
+ _id: 'event_concert_1'
|
|
|
+ type: 'event'
|
|
|
+ title: 'Симфонический оркестр'
|
|
|
+ content: '## Концерт симфонического оркестра\n\nВ программе произведения классической музыки.'
|
|
|
+ event_date: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString()
|
|
|
+ location: 'Большой зал'
|
|
|
+ price: 150
|
|
|
+ tags: ['концерт', 'классика', 'оркестр']
|
|
|
+ image: '/assets/borbad.s5l.ru/concert-1.jpg'
|
|
|
+ created_at: new Date().toISOString()
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
+ }
|
|
|
+ {
|
|
|
+ _id: 'blog_about'
|
|
|
+ type: 'blog_post'
|
|
|
+ title: 'О нашем зале'
|
|
|
+ content: '## История создания\n\nКонцертный зал Борбад был открыт в 2023 году...'
|
|
|
+ tags: ['история', 'архитектура']
|
|
|
+ created_at: new Date().toISOString()
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
+ }
|
|
|
+ ]
|
|
|
+
|
|
|
+ for doc in testData
|
|
|
+ try
|
|
|
+ response = await fetch(@baseUrl+"/"+@dbName+"/"+doc._id,
|
|
|
+ method: 'PUT'
|
|
|
+ headers:
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ body: JSON.stringify(doc)
|
|
|
+ )
|
|
|
+
|
|
|
+ if response.status == 201
|
|
|
+ debug.log "Документ "+doc._id+" успешно создан"
|
|
|
+ else
|
|
|
+ debug.log "Ошибка при создании документа "+doc._id+": "+response.status
|
|
|
+
|
|
|
+ catch error
|
|
|
+ debug.log "Ошибка при создании тестового документа: "+error
|
|
|
+
|
|
|
+ # Основной метод инициализации
|
|
|
+ initialize: ->
|
|
|
+ debug.log "Начало инициализации базы данных мероприятий"
|
|
|
+ await this.checkDatabase()
|
|
|
+ await this.setupDesignDocuments()
|
|
|
+ await this.seedTestData()
|
|
|
+ debug.log "Инициализация базы данных завершена"
|
|
|
+
|
|
|
+# Экспорт класса
|
|
|
+module.exports = EventSeeder
|
|
|
|
|
|
-# Запуск скрипта
|
|
|
-seeder = new EventSeeder()
|
|
|
-seeder.seed().then ->
|
|
|
- console.log '\n✨ Скрипт завершил работу'
|
|
|
- process.exit(0)
|
|
|
-.catch (error) ->
|
|
|
- console.error '\n💥 Критическая ошибка:', error
|
|
|
- process.exit(1)
|
|
|
+# Если файл запускается напрямую
|
|
|
+if require.main == module
|
|
|
+ seeder = new EventSeeder()
|
|
|
+ seeder.initialize()
|