import 'package:drift/drift.dart'; import 'package:drift_postgres/drift_postgres.dart'; import '../converters.dart' show generateUuid, IntListConverter, StringListConverter; /// Таблица CardPacks - наборы карточек class CardPacks extends Table { // ID как String, но фактически UUID (генерируется PostgreSQL на стороне БД) TextColumn get id => text() .withDefault(const CustomExpression('gen_random_uuid()::text'))(); // Основная информация TextColumn get title => text()(); TextColumn get subtitle => text()(); TextColumn get description => text().nullable()(); // Визуальное оформление TextColumn get color => text().nullable()(); TextColumn get cover => text().nullable()(); // URL обложки // Параметры IntColumn get size => integer()(); // количество карточек TextColumn get version => text().nullable()(); IntColumn get order => integer().withDefault(const Constant(0))(); BoolColumn get enabled => boolean() .customConstraint('NOT NULL DEFAULT TRUE')(); // PostgreSQL использует нативный BOOLEAN // Порядок карточек (JSON array of IDs) TextColumn get cardsOrder => text() .withDefault(const Constant('[]')) .map(const StringListConverter())(); // Store IDs для покупок TextColumn get googlePlayId => text().nullable()(); TextColumn get rustoreId => text().nullable()(); TextColumn get appStoreId => text().nullable()(); // Цена TextColumn get price => text().nullable()(); TextColumn get currency => text().withDefault(const Constant('RUB'))(); // Audit Column get createdAt => customType(PgTypes.timestampWithTimezone) .withDefault(now())(); Column get updatedAt => customType(PgTypes.timestampWithTimezone) .withDefault(now())(); BoolColumn get isDeleted => boolean() .customConstraint('NOT NULL DEFAULT FALSE')(); // PostgreSQL использует нативный BOOLEAN @override Set get primaryKey => {id}; } /// Таблица GameCards - карточки для изучения class GameCards extends Table { // ID как String, но фактически UUID (генерируется PostgreSQL на стороне БД) TextColumn get id => text() .withDefault(const CustomExpression('gen_random_uuid()::text'))(); // packId удален - связь теперь только через CardPackCards (many-to-many) // Основной контент TextColumn get original => text()(); // слово на иностранном языке TextColumn get translation => text()(); // перевод TextColumn get mnemo => text().nullable()(); // мнемоническая подсказка // Изображения TextColumn get image => text()(); // основное изображение TextColumn get imageBack => text().nullable()(); // изображение на обратной стороне // Произношение TextColumn get transcription => text().nullable()(); TextColumn get transcriptionMnemo => text().nullable()(); // Дополнительная информация TextColumn get back => text().nullable()(); // дополнительный текст // Audit Column get createdAt => customType(PgTypes.timestampWithTimezone) .withDefault(now())(); Column get updatedAt => customType(PgTypes.timestampWithTimezone) .withDefault(now())(); BoolColumn get isDeleted => boolean() .customConstraint('NOT NULL DEFAULT FALSE')(); // PostgreSQL использует нативный BOOLEAN @override Set get primaryKey => {id}; } /// Таблица VoiceModels - голосовые файлы для карточек class VoiceModels extends Table { // ID как String, но фактически UUID (генерируется PostgreSQL на стороне БД) TextColumn get id => text() .withDefault(const CustomExpression('gen_random_uuid()::text'))(); TextColumn get cardId => text() .references(GameCards, #id, onDelete: KeyAction.cascade)(); TextColumn get voiceUrl => text()(); // URL аудиофайла TextColumn get language => text()(); // язык озвучки Column get createdAt => customType(PgTypes.timestampWithTimezone) .withDefault(now())(); @override Set get primaryKey => {id}; } // IntListConverter импортирован из converters.dart