diff --git a/backend/seed.ts b/backend/seed.ts deleted file mode 100644 index 140f2f2..0000000 --- a/backend/seed.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { DatabaseService } from './src/database/database.service'; -import { wishlistCategories, wishlistItems } from './src/database/schema'; - -async function seed() { - const db = new DatabaseService(); - - console.log('🌱 Seeding wishlist categories...'); - - // Создать категории - const categories = await db.database - .insert(wishlistCategories) - .values([ - { - name: 'БЮДЖЕТНО', - slug: 'tier-1', - minPrice: 0, - maxPrice: 150000, // 1500 руб - color: '#00ff41', - icon: '🟢', - order: 1, - }, - { - name: 'СРЕДНИЙ', - slug: 'tier-2', - minPrice: 150001, - maxPrice: 500000, // 5000 руб - color: '#00cc33', - icon: '🟡', - order: 2, - }, - { - name: 'ТОП', - slug: 'tier-3', - minPrice: 500001, - maxPrice: null, // без ограничения - color: '#009922', - icon: '🔴', - order: 3, - }, - ]) - .returning(); - - console.log(`✅ Created ${categories.length} categories`); - - console.log('🌱 Seeding wishlist items...'); - - // Создать примерные товары - const items = await db.database - .insert(wishlistItems) - .values([ - { - title: 'Зерновой Кофе (Эфиопия)', - description: 'Люблю светлую обжарку. Желательно Эфиопия или Кения. Нужен именно в зернах.', - price: 85000, // 850 руб - currency: 'RUB', - link: 'https://ozon.ru', - images: [ - 'url:https://images.unsplash.com/photo-1497935586351-b67a49e012bf?w=500', - ], - categoryId: categories[0].id, // БЮДЖЕТНО - }, - { - title: 'Молескин в точку', - description: 'Черный, классический. Обязательно в точку, а не в линейку.', - price: 120000, // 1200 руб - currency: 'RUB', - link: 'https://wildberries.ru', - images: [ - 'url:https://images.unsplash.com/photo-1531346878377-a513bc957374?w=500', - ], - categoryId: categories[0].id, // БЮДЖЕТНО - }, - { - title: 'Винил: Daft Punk', - description: 'Альбом "Random Access Memories". Мечтаю послушать его на проигрывателе.', - price: 350000, // 3500 руб - currency: 'RUB', - link: 'https://market.yandex.ru', - images: [ - 'url:https://images.unsplash.com/photo-1603048588665-791ca8aea617?w=500', - ], - categoryId: categories[1].id, // СРЕДНИЙ - }, - { - title: 'D&D Стартовый набор', - description: '5-я редакция. Хочу попробовать поиграть с друзьями.', - price: 290000, // 2900 руб - currency: 'RUB', - link: 'https://hobbygames.ru', - images: [ - 'url:https://images.unsplash.com/photo-1632501641765-e568d90e09b2?w=500', - ], - categoryId: categories[1].id, // СРЕДНИЙ - }, - { - title: 'LEGO Speed Champions', - description: 'Любая машинка из этой серии, желательно Porsche или Ferrari.', - price: 250000, // 2500 руб - currency: 'RUB', - link: 'https://detmir.ru', - images: [ - 'url:https://images.unsplash.com/photo-1585366119957-e9730b6d0f60?w=500', - ], - categoryId: categories[1].id, // СРЕДНИЙ - }, - { - title: 'Keychron K2', - description: 'Механическая клавиатура. Свичи Red или Brown. Нужна подсветка.', - price: 900000, // 9000 руб - currency: 'RUB', - link: 'https://geekboards.ru', - images: [ - 'url:https://images.unsplash.com/photo-1595225476474-87563907a212?w=500', - ], - categoryId: categories[2].id, // ТОП - }, - ]) - .returning(); - - console.log(`✅ Created ${items.length} wishlist items`); - console.log('✨ Seeding completed!'); - - process.exit(0); -} - -seed().catch((error) => { - console.error('❌ Seeding failed:', error); - process.exit(1); -}); diff --git a/backend/src/database/database.module.ts b/backend/src/database/database.module.ts index aa3fbd8..48900de 100644 --- a/backend/src/database/database.module.ts +++ b/backend/src/database/database.module.ts @@ -22,7 +22,7 @@ const databaseProvider = { const client = new PGlite(dbPath); const db = drizzle(client, { schema }); - // Создаем таблицу напрямую вместо использования миграций + // Создаем таблицы напрямую вместо использования миграций try { await client.exec(` CREATE TABLE IF NOT EXISTS events ( @@ -42,6 +42,32 @@ const databaseProvider = { created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); + + CREATE TABLE IF NOT EXISTS wishlist_categories ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL UNIQUE, + slug TEXT NOT NULL UNIQUE, + min_price INTEGER NOT NULL DEFAULT 0, + max_price INTEGER, + color TEXT, + icon TEXT, + "order" INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() + ); + + CREATE TABLE IF NOT EXISTS wishlist_items ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + title TEXT NOT NULL, + description TEXT, + price INTEGER NOT NULL, + currency TEXT NOT NULL DEFAULT 'RUB', + link TEXT, + images TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[], + category_id UUID NOT NULL REFERENCES wishlist_categories(id) ON DELETE RESTRICT, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() + ); `); console.log('✅ Database initialized successfully'); } catch (error) { @@ -58,4 +84,4 @@ const databaseProvider = { providers: [databaseProvider], exports: [DATABASE_CONNECTION], }) -export class DatabaseModule {} +export class DatabaseModule { } diff --git a/backend/src/wishlist/categories.controller.ts b/backend/src/wishlist/categories.controller.ts index 38d5861..aa9ad43 100644 --- a/backend/src/wishlist/categories.controller.ts +++ b/backend/src/wishlist/categories.controller.ts @@ -1,6 +1,6 @@ import { Controller, Get, Post, Patch, Delete, Body, Param, UsePipes } from '@nestjs/common'; import { WishlistCategoriesService } from './categories.service'; -import { CreateWishlistCategoryDto, UpdateWishlistCategoryDto } from './dto/category.dto'; +import type { CreateWishlistCategoryDto, UpdateWishlistCategoryDto } from './dto/category.dto'; import { ZodValidationPipe } from '../pipes/zod-validation.pipe'; import { CreateWishlistCategorySchema, UpdateWishlistCategorySchema } from './dto/category.dto'; diff --git a/backend/src/wishlist/categories.service.ts b/backend/src/wishlist/categories.service.ts index 9bf842a..8c82cf7 100644 --- a/backend/src/wishlist/categories.service.ts +++ b/backend/src/wishlist/categories.service.ts @@ -1,21 +1,27 @@ -import { Injectable, ConflictException, NotFoundException } from '@nestjs/common'; +import { Injectable, ConflictException, NotFoundException, Inject } from '@nestjs/common'; import { eq, and, lte, gte, or, isNull, asc } from 'drizzle-orm'; +import { PgliteDatabase } from 'drizzle-orm/pglite'; +import { DATABASE_CONNECTION } from '../database/database.module'; +import * as schema from '../database/schema'; import { wishlistCategories, WishlistCategory, NewWishlistCategory } from '../database/schema'; -import { CreateWishlistCategoryDto, UpdateWishlistCategoryDto } from './dto/category.dto'; +import type { CreateWishlistCategoryDto, UpdateWishlistCategoryDto } from './dto/category.dto'; @Injectable() export class WishlistCategoriesService { - constructor(private readonly db: DatabaseService) { } + constructor( + @Inject(DATABASE_CONNECTION) + private readonly db: PgliteDatabase, + ) { } async findAll(): Promise { - return this.db.database + return this.db .select() .from(wishlistCategories) .orderBy(asc(wishlistCategories.order)); } async findOne(id: string): Promise { - const [category] = await this.db.database + const [category] = await this.db .select() .from(wishlistCategories) .where(eq(wishlistCategories.id, id)) @@ -29,7 +35,7 @@ export class WishlistCategoriesService { } async findBySlug(slug: string): Promise { - const [category] = await this.db.database + const [category] = await this.db .select() .from(wishlistCategories) .where(eq(wishlistCategories.slug, slug)) @@ -54,7 +60,7 @@ export class WishlistCategoriesService { updatedAt: new Date(), }; - const [category] = await this.db.database + const [category] = await this.db .insert(wishlistCategories) .values(newCategory) .returning(); @@ -80,7 +86,7 @@ export class WishlistCategoriesService { await this.validatePriceRange(minPrice, maxPrice, id); } - const [updated] = await this.db.database + const [updated] = await this.db .update(wishlistCategories) .set({ ...dto, updatedAt: new Date() }) .where(eq(wishlistCategories.id, id)) @@ -92,13 +98,13 @@ export class WishlistCategoriesService { async delete(id: string): Promise { await this.findOne(id); - await this.db.database + await this.db .delete(wishlistCategories) .where(eq(wishlistCategories.id, id)); } async findCategoryByPrice(price: number): Promise { - const [category] = await this.db.database + const [category] = await this.db .select() .from(wishlistCategories) .where( diff --git a/backend/src/wishlist/wishlist.service.ts b/backend/src/wishlist/wishlist.service.ts index 59e0645..c44b93a 100644 --- a/backend/src/wishlist/wishlist.service.ts +++ b/backend/src/wishlist/wishlist.service.ts @@ -1,8 +1,10 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException, Inject } from '@nestjs/common'; import { eq } from 'drizzle-orm'; -import { DatabaseService } from '../database/database.service'; +import { PgliteDatabase } from 'drizzle-orm/pglite'; +import { DATABASE_CONNECTION } from '../database/database.module'; +import * as schema from '../database/schema'; import { wishlistItems, WishlistItem, NewWishlistItem } from '../database/schema'; -import { CreateWishlistItemDto, UpdateWishlistItemDto } from './dto/wishlist-item.dto'; +import type { CreateWishlistItemDto, UpdateWishlistItemDto } from './dto/wishlist-item.dto'; import { WishlistCategoriesService } from './categories.service'; import * as fs from 'fs/promises'; import * as path from 'path'; @@ -10,12 +12,13 @@ import * as path from 'path'; @Injectable() export class WishlistService { constructor( - private readonly db: DatabaseService, + @Inject(DATABASE_CONNECTION) + private readonly db: PgliteDatabase, private readonly categoriesService: WishlistCategoriesService, ) { } async findAll(categoryId?: string): Promise { - const query = this.db.database.select().from(wishlistItems); + const query = this.db.select().from(wishlistItems); if (categoryId) { query.where(eq(wishlistItems.categoryId, categoryId)); @@ -25,7 +28,7 @@ export class WishlistService { } async findOne(id: string): Promise { - const [item] = await this.db.database + const [item] = await this.db .select() .from(wishlistItems) .where(eq(wishlistItems.id, id)) @@ -74,7 +77,7 @@ export class WishlistService { updatedAt: new Date(), }; - const [item] = await this.db.database + const [item] = await this.db .insert(wishlistItems) .values(newItem) .returning(); @@ -113,7 +116,7 @@ export class WishlistService { } } - const [updated] = await this.db.database + const [updated] = await this.db .update(wishlistItems) .set({ ...dto, @@ -132,7 +135,7 @@ export class WishlistService { // Удалить загруженные файлы await this.deleteUploadedImages(item.images); - await this.db.database + await this.db .delete(wishlistItems) .where(eq(wishlistItems.id, id)); }