seed-events.coffee 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. # Подключение PouchDB
  2. PouchDB = require 'pouchdb'
  3. # Важно сохранять для seed-events.coffee
  4. debug = require('../../../utils/coffee/debug.coffee').default
  5. class DatabaseSeeder
  6. constructor: (dbName, baseUrl = 'http://oleg:631074@localhost:5984') ->
  7. @dbName = dbName
  8. @baseUrl = baseUrl
  9. @db = new PouchDB(@baseUrl+"/"+@dbName)
  10. @designDoc = require './design-documents.coffee'
  11. @orderCounter = 0
  12. @currentYear = new Date().getFullYear()
  13. # Генератор ID для заказов
  14. generateOrderId: ->
  15. @orderCounter++
  16. return "order_"+@currentYear+"_"+@orderCounter.toString().padStart(3, '0')
  17. # Генератор ID для блог постов
  18. generateBlogPostId: (title, domain = null) ->
  19. slug = title
  20. .toLowerCase()
  21. .replace(/[^a-z0-9а-яё]/g, '_')
  22. .replace(/_+/g, '_')
  23. .replace(/^_|_$/g, '')
  24. year = new Date().getFullYear()
  25. id = "blog_post_"+slug+"_"+year
  26. if domain
  27. domainPart = domain.replace(/\./g, '_')
  28. id += "_"+domainPart
  29. return id
  30. # Генератор ID для мероприятий
  31. generateEventId: (title, eventDate, domain = null) ->
  32. slug = title
  33. .toLowerCase()
  34. .replace(/[^a-z0-9а-яё]/g, '_')
  35. .replace(/_+/g, '_')
  36. .replace(/^_|_$/g, '')
  37. date = new Date(eventDate)
  38. year = date.getFullYear()
  39. month = (date.getMonth() + 1).toString().padStart(2, '0')
  40. id = "event_"+slug+"_"+year+"_"+month
  41. if domain
  42. domainPart = domain.replace(/\./g, '_')
  43. id += "_"+domainPart
  44. return id
  45. # Проверка существования базы данных
  46. checkDatabaseExists: ->
  47. try
  48. info = await @db.info()
  49. debug.log "База данных "+@dbName+" существует"
  50. return true
  51. catch error
  52. debug.log "База данных "+@dbName+" не существует: "+error
  53. return false
  54. # Создание базы данных если не существует
  55. createDatabaseIfNotExists: ->
  56. exists = await @checkDatabaseExists()
  57. if not exists
  58. try
  59. response = await fetch(@baseUrl+"/"+@dbName, method: 'PUT')
  60. if response.ok
  61. debug.log "База данных "+@dbName+" создана"
  62. else
  63. debug.log "Ошибка создания базы: "+response.statusText
  64. catch error
  65. debug.log "Ошибка при создании базы: "+error
  66. return exists
  67. # Удаление старых версий документов
  68. cleanupOldDocuments: ->
  69. try
  70. debug.log "Начало очистки старых документов"
  71. allDocs = await @db.allDocs(include_docs: true)
  72. documentsToDelete = []
  73. documentsToKeep = new Set()
  74. documentsByType = {}
  75. for row in allDocs.rows
  76. doc = row.doc
  77. if doc._id.startsWith('_design/')
  78. continue
  79. docType = doc.type or 'unknown'
  80. if not documentsByType[docType]
  81. documentsByType[docType] = []
  82. documentsByType[docType].push(doc)
  83. for docType, docs of documentsByType
  84. if docs.length <= 6
  85. for doc in docs
  86. documentsToKeep.add(doc._id)
  87. continue
  88. sortedDocs = docs.sort (a, b) ->
  89. new Date(b.created_at) - new Date(a.created_at)
  90. for doc, index in sortedDocs
  91. if index < 6
  92. documentsToKeep.add(doc._id)
  93. else
  94. documentsToDelete.push({
  95. _id: doc._id
  96. _rev: doc._rev
  97. _deleted: true
  98. })
  99. if documentsToDelete.length > 0
  100. result = await @db.bulkDocs(documentsToDelete)
  101. debug.log "Удалено старых документов: "+documentsToDelete.length
  102. else
  103. debug.log "Старые документы для удаления не найдены"
  104. debug.log "Очистка старых документов завершена"
  105. catch error
  106. debug.log "Ошибка при очистке старых документов: "+error
  107. # Проверка и создание design документов
  108. setupDesignDocuments: ->
  109. try
  110. for designName, designDoc of @designDoc
  111. docId = "_design/"+designName
  112. try
  113. currentDoc = await @db.get(docId)
  114. if currentDoc.version isnt designDoc.version
  115. debug.log "Обновление design документа: "+designName
  116. designDoc._id = docId
  117. designDoc._rev = currentDoc._rev
  118. await @db.put(designDoc)
  119. debug.log "Design документ "+designName+" обновлен до версии "+designDoc.version
  120. else
  121. debug.log "Design документ "+designName+" актуален"
  122. catch error
  123. if error.status is 404
  124. debug.log "Создание design документа: "+designName
  125. designDoc._id = docId
  126. await @db.put(designDoc)
  127. debug.log "Design документ "+designName+" создан"
  128. else
  129. throw error
  130. catch error
  131. debug.log "Ошибка при настройке design документов: "+error
  132. # Создание тестовых данных для сайта
  133. createSampleData: ->
  134. currentDate = new Date().toISOString()
  135. futureDate = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString()
  136. pastDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()
  137. sampleData = [
  138. # Доменные настройки для основного домена
  139. {
  140. _id: "domain_settings_borbad_s5l_ru"
  141. type: "domain_settings"
  142. domain: "borbad.s5l.ru"
  143. name: "Кохи Борбад - Концертный зал Душанбе"
  144. description: "Официальный сайт концертного зала Борбад"
  145. active: true
  146. priority: 1
  147. theme: "borbad"
  148. languages: ["ru", "en", "tj"]
  149. default_language: "ru"
  150. timezone: "Asia/Dushanbe"
  151. currency: "TJS"
  152. settings: {
  153. seo: {
  154. title_template: "{page} - Кохи Борбад"
  155. description: "Концертный зал Борбад - культурный центр Душанбе"
  156. keywords: ["концерты", "мероприятия", "Душанбе", "культура"]
  157. }
  158. social: {
  159. facebook: "https://facebook.com/borbad"
  160. instagram: "https://instagram.com/borbad"
  161. twitter: "https://twitter.com/borbad"
  162. }
  163. contact: {
  164. address: "г. Душанбе, пр. Рудаки 22"
  165. phone: "+992 37 123-45-67"
  166. email: "info@borbad.s5l.ru"
  167. }
  168. features: {
  169. online_booking: true
  170. multi_language: true
  171. ecommerce: true
  172. }
  173. }
  174. created_at: currentDate
  175. updated_at: currentDate
  176. }
  177. # Доменные настройки для второго домена
  178. {
  179. _id: "domain_settings_concert_hall_tj"
  180. type: "domain_settings"
  181. domain: "concert-hall.tj"
  182. name: "Концертный зал Борбад - Таджикистан"
  183. description: "Культурная площадка для мероприятий и концертов"
  184. active: true
  185. priority: 2
  186. theme: "borbad_light"
  187. languages: ["tj", "ru"]
  188. default_language: "tj"
  189. timezone: "Asia/Dushanbe"
  190. currency: "TJS"
  191. settings: {
  192. seo: {
  193. title_template: "{page} - Борбад"
  194. description: "Концерты и мероприятия в Душанбе"
  195. keywords: ["концерты", "Борбад", "Душанбе", "мероприятия"]
  196. }
  197. social: {
  198. facebook: "https://facebook.com/borbad.tj"
  199. instagram: "https://instagram.com/borbad.tj"
  200. }
  201. contact: {
  202. address: "г. Душанбе, пр. Рудаки 22"
  203. phone: "+992 37 123-45-68"
  204. email: "info@concert-hall.tj"
  205. }
  206. features: {
  207. online_booking: true
  208. multi_language: true
  209. ecommerce: false
  210. }
  211. }
  212. created_at: currentDate
  213. updated_at: currentDate
  214. }
  215. # Слайдеры (6 слайдов) - мультидоменные
  216. {
  217. _id: "slide_01_borbad"
  218. type: "slide"
  219. domain: ["borbad.s5l.ru", "concert-hall.tj"]
  220. domain_priority: ["borbad.s5l.ru", "concert-hall.tj"]
  221. language: "ru"
  222. title: "Добро пожаловать в Кохи Борбад"
  223. content: "## Современный концертный зал в сердце Душанбе\n\nМесто, где встречаются искусство и культура"
  224. image: "/assets/borbad.s5l.ru/sliders/main-hall.jpg"
  225. mobile_image: "/assets/borbad.s5l.ru/sliders/main-hall-mobile.jpg"
  226. order: 1
  227. active: true
  228. button_text: "Узнать больше"
  229. button_link: "/about"
  230. button_style: "primary"
  231. text_color: "#ffffff"
  232. text_position: "center"
  233. overlay: true
  234. overlay_opacity: 0.4
  235. start_date: "2024-01-01T00:00:00.000Z"
  236. end_date: "2024-12-31T23:59:59.000Z"
  237. target_audience: ["all"]
  238. created_at: currentDate
  239. updated_at: currentDate
  240. }
  241. {
  242. _id: "slide_02_borbad"
  243. type: "slide"
  244. domain: ["borbad.s5l.ru"]
  245. domain_priority: ["borbad.s5l.ru"]
  246. language: "ru"
  247. title: "Симфонические вечера"
  248. content: "## Погрузитесь в мир классической музыки\n\nЕженедельные концерты симфонического оркестра"
  249. image: "/assets/borbad.s5l.ru/sliders/orchestra.jpg"
  250. order: 2
  251. active: true
  252. button_text: "Расписание"
  253. button_link: "/events"
  254. text_color: "#ffffff"
  255. overlay: true
  256. created_at: currentDate
  257. updated_at: currentDate
  258. }
  259. # ... остальные 4 слайда с аналогичной структурой
  260. # Блог посты (6 постов) - мультидоменные
  261. {
  262. _id: @generateBlogPostId("Открытие нового сезона 2024", "borbad")
  263. type: "blog_post"
  264. domain: ["borbad.s5l.ru", "global"]
  265. domain_priority: ["borbad.s5l.ru", "global"]
  266. language: "ru"
  267. translation_of: null
  268. translation_status: "original"
  269. title: "Открытие нового сезона 2024"
  270. content: "# Добро пожаловать в новый творческий сезон!\n\nМы рады объявить о начале нового сезона в концертном зале Борбад..."
  271. excerpt: "Новый творческий сезон 2024 года в концертном зале Борбад"
  272. image: "/assets/borbad.s5l.ru/posts/season-opening.jpg"
  273. tags: ["новости", "сезон", "анонс"]
  274. category_id: "category_news_borbad"
  275. author: "Администрация Борбад"
  276. status: "published"
  277. meta_title: "Открытие нового сезона 2024 - Кохи Борбад"
  278. meta_description: "Новый творческий сезон 2024 года в концертном зале Борбад в Душанбе"
  279. featured: true
  280. featured_image: "/assets/borbad.s5l.ru/posts/season-opening-featured.jpg"
  281. reading_time: 5
  282. created_at: currentDate
  283. updated_at: currentDate
  284. published_at: currentDate
  285. views: 156
  286. likes: 23
  287. shares: 45
  288. }
  289. {
  290. _id: @generateBlogPostId("История создания концертного зала", "borbad")
  291. type: "blog_post"
  292. domain: ["borbad.s5l.ru", "concert-hall.tj"]
  293. domain_priority: ["borbad.s5l.ru", "concert-hall.tj"]
  294. language: "ru"
  295. translation_of: null
  296. translation_status: "original"
  297. title: "История создания концертного зала"
  298. content: "# Кохи Борбад: История и архитектура\n\n## Начало пути\n\nКонцертный зал Борбад был основан в 2010 году..."
  299. excerpt: "История создания и архитектурные особенности концертного зала Борбад"
  300. image: "/assets/borbad.s5l.ru/posts/history-building.jpg"
  301. tags: ["история", "архитектура", "культура"]
  302. category_id: "category_about_borbad"
  303. author: "Директор зала"
  304. status: "published"
  305. featured: true
  306. created_at: pastDate
  307. updated_at: currentDate
  308. published_at: pastDate
  309. views: 289
  310. }
  311. # ... остальные 4 поста с аналогичной структурой
  312. # Мероприятия (6 мероприятий) - мультидоменные
  313. {
  314. _id: @generateEventId("Симфонический концерт: Бетховен и Чайковский", "2024-03-20T19:00:00.000Z", "borbad")
  315. type: "event"
  316. domain: ["borbad.s5l.ru", "concert-hall.tj"]
  317. domain_priority: ["borbad.s5l.ru", "concert-hall.tj"]
  318. language: "ru"
  319. translation_of: null
  320. translation_status: "original"
  321. title: "Симфонический концерт: Бетховен и Чайковский"
  322. content: "# Великие композиторы\n\n## Программа концерта\n\n- **Л. ван Бетховен** - Симфония №5..."
  323. event_date: "2024-03-20T19:00:00.000Z"
  324. end_date: "2024-03-20T21:00:00.000Z"
  325. location: "Большой зал"
  326. venue_id: "venue_main_hall_borbad"
  327. address: {
  328. street: "пр. Рудаки 22"
  329. city: "Душанбе"
  330. country: "Таджикистан"
  331. }
  332. coordinates: {
  333. lat: 38.5732
  334. lng: 68.7734
  335. }
  336. price: 500
  337. currency: "TJS"
  338. available_tickets: 45
  339. total_tickets: 300
  340. image: "/assets/borbad.s5l.ru/events/beethoven-concert.jpg"
  341. gallery: [
  342. "/assets/borbad.s5l.ru/gallery/concert1.jpg"
  343. "/assets/borbad.s5l.ru/gallery/concert2.jpg"
  344. ]
  345. tags: ["концерт", "симфоническая музыка", "классика", "Бетховен", "Чайковский"]
  346. category_id: "category_concerts_borbad"
  347. status: "upcoming"
  348. registration_required: true
  349. max_attendees: 300
  350. age_restriction: "6+"
  351. organizer: "Симфонический оркестр Борбад"
  352. performers: ["Фаррух Саидов (дирижер)", "Солисты оркестра"]
  353. duration: 120
  354. created_at: currentDate
  355. updated_at: currentDate
  356. }
  357. # ... остальные 5 мероприятий с аналогичной структурой
  358. # Категории - мультидоменные
  359. {
  360. _id: "category_concerts_borbad"
  361. type: "category"
  362. domain: ["borbad.s5l.ru", "concert-hall.tj"]
  363. domain_priority: ["borbad.s5l.ru", "concert-hall.tj"]
  364. language: "ru"
  365. translation_of: null
  366. translation_status: "original"
  367. name: "Концерты"
  368. slug: "concerts"
  369. description: "Музыкальные мероприятия и концерты различных жанров"
  370. image: "/assets/borbad.s5l.ru/categories/concerts.jpg"
  371. icon: "music"
  372. parent_id: null
  373. order: 2
  374. meta_title: "Концерты - Кохи Борбад"
  375. meta_description: "Музыкальные мероприятия и концерты в концертном зале Борбад"
  376. active: true
  377. featured: true
  378. show_in_menu: true
  379. menu_order: 2
  380. color: "#3B82F6"
  381. created_at: currentDate
  382. updated_at: currentDate
  383. }
  384. {
  385. _id: "category_news_borbad"
  386. type: "category"
  387. domain: ["borbad.s5l.ru"]
  388. domain_priority: ["borbad.s5l.ru"]
  389. language: "ru"
  390. name: "Новости"
  391. slug: "news"
  392. description: "Последние новости и анонсы концертного зала"
  393. image: "/assets/borbad.s5l.ru/categories/news.jpg"
  394. parent_id: null
  395. order: 1
  396. meta_title: "Новости - Кохи Борбад"
  397. meta_description: "Последние новости и анонсы концертного зала Борбад"
  398. active: true
  399. created_at: currentDate
  400. updated_at: currentDate
  401. }
  402. # Пользователи - глобальные
  403. {
  404. _id: "user_admin_main"
  405. type: "user"
  406. domain: "global"
  407. email: "admin@borbad.s5l.ru"
  408. name: "Администратор Борбад"
  409. role: "admin"
  410. active: true
  411. permissions: ["read", "write", "delete", "admin"]
  412. profile: {
  413. avatar: "/assets/borbad.s5l.ru/avatars/admin.jpg"
  414. phone: "+992 37 123-45-67"
  415. position: "Системный администратор"
  416. bio: "Ответственный за техническую часть сайта"
  417. }
  418. preferences: {
  419. language: "ru"
  420. notifications: true
  421. theme: "dark"
  422. timezone: "Asia/Dushanbe"
  423. }
  424. security: {
  425. last_password_change: "2024-01-01T00:00:00.000Z"
  426. two_factor_enabled: true
  427. login_attempts: 0
  428. }
  429. domains_access: ["borbad.s5l.ru", "concert-hall.tj"]
  430. created_at: currentDate
  431. updated_at: currentDate
  432. last_login: "2024-01-15T09:30:00.000Z"
  433. }
  434. # Заказы - специфичные для домена
  435. {
  436. _id: @generateOrderId()+"_borbad"
  437. type: "order"
  438. domain: "borbad.s5l.ru"
  439. language: "ru"
  440. user_id: "user_customer_ivanov"
  441. status: "completed"
  442. total: 1500
  443. currency: "TJS"
  444. items: [
  445. {
  446. product_id: "event_ticket_1"
  447. name: "Билет на симфонический концерт"
  448. quantity: 2
  449. price: 500
  450. total: 1000
  451. type: "ticket"
  452. }
  453. ]
  454. customer_info: {
  455. name: "Иван Иванов"
  456. email: "ivan@example.com"
  457. phone: "+992 123-45-67"
  458. }
  459. payment_info: {
  460. method: "card"
  461. transaction_id: "txn_123456"
  462. status: "paid"
  463. amount: 1500
  464. currency: "TJS"
  465. payment_date: "2024-01-15T14:00:00.000Z"
  466. }
  467. shipping_info: {
  468. method: "pickup"
  469. address: null
  470. tracking_number: null
  471. }
  472. metadata: {
  473. ip_address: "192.168.1.100"
  474. user_agent: "Mozilla/5.0..."
  475. source: "website"
  476. }
  477. created_at: "2024-01-15T13:45:00.000Z"
  478. updated_at: "2024-01-15T14:00:00.000Z"
  479. }
  480. ]
  481. try
  482. createdCount = 0
  483. updatedCount = 0
  484. for doc in sampleData
  485. try
  486. existing = await @db.get(doc._id)
  487. doc._rev = existing._rev
  488. await @db.put(doc)
  489. updatedCount++
  490. debug.log "Обновлен документ: "+doc._id
  491. catch error
  492. if error.status is 404
  493. await @db.put(doc)
  494. createdCount++
  495. debug.log "Создан документ: "+doc._id
  496. else
  497. throw error
  498. debug.log "Тестовые данные успешно созданы: создано "+createdCount+", обновлено "+updatedCount
  499. catch error
  500. debug.log "Ошибка при создании тестовых данных: "+error
  501. # Основной метод инициализации
  502. initialize: ->
  503. debug.log "Начало инициализации базы данных"
  504. await @createDatabaseIfNotExists()
  505. await @cleanupOldDocuments()
  506. await @setupDesignDocuments()
  507. await @createSampleData()
  508. debug.log "Инициализация базы данных завершена"
  509. # Экспорт класса
  510. module.exports = DatabaseSeeder
  511. # Если файл запущен напрямую
  512. if require.main is module
  513. seeder = new DatabaseSeeder('borbad_events')
  514. seeder.initialize().catch (error) ->
  515. debug.log "Критическая ошибка инициализации: "+error