refactor: Rename Category table to Categories and fix references
This commit is contained in:
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user