refactor: Rename Category table to Categories and fix references

This commit is contained in:
2025-05-04 22:38:05 +03:00
parent c5da00c013
commit f14cde0247
+47 -21
View File
@@ -19,8 +19,9 @@ part 'database.g.dart';
enum TransactionType { income, expense }
// Определение таблицы Categories
// ИСПРАВЛЕНО: Имя класса таблицы изменено на Categories для ясности
@DataClassName('CategoryDb')
class Category extends Table {
class Categories extends Table { // Changed class name to plural 'Categories'
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text().unique()();
TextColumn get icon => text()();
@@ -42,7 +43,7 @@ class Transactions extends Table {
// Класс базы данных
// Аннотация @DriftDatabase указывает Drift сгенерировать код для этой базы данных
@DriftDatabase(tables: [Category, Transactions])
@DriftDatabase(tables: [Categories, Transactions]) // Updated table name here
class AppDatabase extends _$AppDatabase {
// Используем функцию connect() из условного импорта для создания соединения
// Во время компиляции будет выбрана правильная реализация connect()
@@ -70,6 +71,19 @@ class AppDatabase extends _$AppDatabase {
}
// Add more migration steps for future versions here
// if (from < 3) { ... }
// If migrating to version 4 where Categories table was added,
// Drift handles creating the new table automatically.
// We might want to ensure initial data is inserted if upgrading
// from a version before initial data logic was robust.
if (from < 4) {
// Ensure the categories table exists if upgrading from a version before it was defined
// (Drift's createAll in onCreate handles new tables, but onUpgrade might need it)
// However, `m.createAll()` is usually for onCreate.
// For adding tables in upgrades, you typically use `m.createTable(categories);`
// But Drift's default strategy handles adding new tables defined in the @DriftDatabase annotation.
// So, we mainly need to ensure the initial data gets inserted if needed.
await insertInitialDataIfNeeded(isCreating: false); // Check and insert if missing
}
},
beforeOpen: (details) async {
if (details.wasCreated) {
@@ -77,7 +91,7 @@ class AppDatabase extends _$AppDatabase {
} else {
print("Opening existing database version ${details.versionNow}. Checking if initial data needs insertion (e.g., if DB was created empty before initial data logic).");
// Check and insert initial data if the database exists but might be empty
// (e.g., if created before the initial data logic was in onCreate)
// (e.g., if created before the initial data logic was in onCreate or migration)
await insertInitialDataIfNeeded(isCreating: false);
}
},
@@ -124,6 +138,7 @@ class AppDatabase extends _$AppDatabase {
// --- Методы для работы с категориями и суммами ---
// Вычислить и наблюдать за общими суммами по категориям РАСХОДОВ
// Возвращает Stream<List<Category>> где Category - это класс модели из '../models/category.dart'
Stream<List<Category>> calculateCategoryTotals() {
// 1. Получаем поток всех транзакций
return watchAllTransactions().map((transactionList) {
@@ -140,10 +155,11 @@ class AppDatabase extends _$AppDatabase {
}
}
// 3. Преобразуем сгруппированные данные в список объектов Category
// 3. Преобразуем сгруппированные данные в список объектов Category (модель)
return categoryTotals.entries.map((entry) {
// Используем утилиту для получения деталей (иконка, цвет) по имени
final categoryDetails = CategoryUtils.getCategoryDetails(entry.key);
return Category(
return Category( // Это Category из models/category.dart
entry.key, // name
entry.value, // amount
categoryDetails.colorCode,
@@ -183,29 +199,39 @@ class AppDatabase extends _$AppDatabase {
// Добавление начальных данных (если база данных пуста)
Future<void> insertInitialDataIfNeeded({bool isCreating = false}) async {
// Проверяем, есть ли уже категории
final categoriesCount = await (selectOnly(category)..addColumns([category.id.count()])).getSingleOrNull();
if (categoriesCount?.read(categories.id.count()) == 0) {
// ИСПРАВЛЕНО: Используем 'categories' (имя экземпляра таблицы) вместо 'category'
final categoriesCountResult = await (selectOnly(categories)..addColumns([categories.id.count()])).getSingleOrNull();
final categoriesCount = categoriesCountResult?.read(categories.id.count()) ?? 0;
if (categoriesCount == 0) {
print("Categories table is empty. Inserting initial categories...");
await batch((batch) {
batch.insertAll(category, [
CategoriesCompanion.insert(name: 'Groceries', icon: 'shopping_cart', color: c.Colors.green.value),
CategoriesCompanion.insert(name: 'Subscriptions', icon: 'subscriptions', color: c.Colors.orange.value),
CategoriesCompanion.insert(name: 'Restaurant', icon: 'restaurant', color: c.Colors.red.value),
CategoriesCompanion.insert(name: 'Shopping', icon: 'shopping_bag', color: c.Colors.blue.value),
CategoriesCompanion.insert(name: 'Transport', icon: 'directions_bus', color: c.Colors.purple.value),
CategoriesCompanion.insert(name: 'Travel', icon: 'flight_takeoff', color: c.Colors.cyan.value),
CategoriesCompanion.insert(name: 'Utilities', icon: 'home', color: c.Colors.teal.value),
CategoriesCompanion.insert(name: 'Income', icon: 'attach_money', color: c.Colors.greenAccent.value),
// ИСПРАВЛЕНО: Используем 'categories' (имя экземпляра таблицы) вместо 'category'
batch.insertAll(categories, [
// Используем CategoriesCompanion (сгенерированный для таблицы Categories)
CategoriesCompanion.insert(name: 'Groceries', icon: 'shopping_cart_outlined', color: c.Colors.green.shade400.value),
CategoriesCompanion.insert(name: 'Subscriptions', icon: 'subscriptions_outlined', color: c.Colors.orange.shade400.value),
CategoriesCompanion.insert(name: 'Restaurant', icon: 'restaurant_menu_outlined', color: c.Colors.red.shade400.value),
CategoriesCompanion.insert(name: 'Shopping', icon: 'shopping_bag_outlined', color: c.Colors.blue.shade400.value),
CategoriesCompanion.insert(name: 'Transport', icon: 'directions_bus_filled_outlined', color: c.Colors.purple.shade400.value),
CategoriesCompanion.insert(name: 'Travel', icon: 'flight_takeoff_outlined', color: c.Colors.cyan.shade400.value),
CategoriesCompanion.insert(name: 'Utilities', icon: 'home_outlined', color: c.Colors.teal.shade400.value), // Example: Added Utilities
// 'Income' category might not be needed if handled separately, but can be added for consistency
CategoriesCompanion.insert(name: 'Income', icon: 'attach_money', color: c.Colors.lightGreenAccent.shade400.value), // Example: Added Income category
]);
});
print("Initial categories inserted.");
} else {
print("Categories table already contains data ($categoriesCount categories). Skipping initial category insertion.");
}
// Проверяем, есть ли уже транзакции
final countResult = await (selectOnly(transactions)..addColumns([transactions.id.count()])).getSingleOrNull();
final transactionCount = countResult?.read(transactions.id.count()) ?? 0;
// Вставляем данные только если таблица пуста
// Вставляем данные только если таблица транзакций пуста
if (transactionCount == 0) {
print("Database is empty${isCreating ? ' (during creation)' : ''}. Inserting initial data...");
print("Transactions table is empty${isCreating ? ' (during creation)' : ''}. Inserting initial transactions...");
// Используем batch для эффективной вставки нескольких записей
await batch((batch) {
batch.insertAll(transactions, [
@@ -218,14 +244,14 @@ class AppDatabase extends _$AppDatabase {
TransactionsCompanion.insert(categoryName: 'Groceries', amount: 23.45, date: DateTime.now().subtract(const Duration(days: 4, hours: 9)), merchant: 'Local Market'),
TransactionsCompanion.insert(categoryName: 'Transport', amount: 15.00, date: DateTime.now().subtract(const Duration(days: 5, hours: 8)), merchant: 'City Bus'),
TransactionsCompanion.insert(categoryName: 'Restaurant', amount: 56.80, date: DateTime.now().subtract(const Duration(days: 5, hours: 20)), merchant: 'Sushi Express'),
TransactionsCompanion.insert(categoryName: 'Utilities', amount: 85.20, date: DateTime.now().subtract(const Duration(days: 6, hours: 10)), merchant: 'Electricity Bill'),
TransactionsCompanion.insert(categoryName: 'Utilities', amount: 85.20, date: DateTime.now().subtract(const Duration(days: 6, hours: 10)), merchant: 'Electricity Bill'), // Example: Added Utilities transaction
// Пример дохода - здесь нужно явно указать type: 'income'
TransactionsCompanion.insert(categoryName: 'Income', amount: 1200.00, date: DateTime.now().subtract(const Duration(days: 7, hours: 9)), merchant: 'Salary', type: Value('income')),
]);
});
print("Initial data inserted successfully.");
print("Initial transactions inserted successfully.");
} else {
print("Database already contains data ($transactionCount transactions). Skipping initial data insertion.");
print("Transactions table already contains data ($transactionCount transactions). Skipping initial transaction insertion.");
}
}
}