import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:path/path.dart'; import '../models/product.dart'; class DatabaseHelper { static Database? _database; static const String tableName = 'products'; static const int _databaseVersion = 2; // Increased database version for schema migration Future get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future _initDatabase() async { sqfliteFfiInit(); var databaseFactory = databaseFactoryFfi; String databasesPath = await databaseFactory.getDatabasesPath(); String path = join(databasesPath, 'product_database.db'); return await databaseFactory.openDatabase( path, options: OpenDatabaseOptions( version: _databaseVersion, onCreate: _onCreate, onUpgrade: _onUpgrade, // Add onUpgrade for schema migration ), ); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE $tableName( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, code TEXT NOT NULL, description TEXT, imageUrl TEXT, serialNumber TEXT, model TEXT, tags TEXT, price REAL NOT NULL, costPrice REAL, taxRate REAL, discount REAL, profitMargin REAL, quantity INTEGER NOT NULL, unitOfMeasure TEXT, location TEXT, minimumStock INTEGER, supplier TEXT, entryDate TEXT, manufactureDate TEXT, expirationDate TEXT, status TEXT, category TEXT, brand TEXT, createdBy TEXT, createdAt TEXT, lastModifiedBy TEXT, lastModifiedAt TEXT ) '''); } // Handle database schema upgrades Future _onUpgrade(Database db, int oldVersion, int newVersion) async { if (oldVersion < 2) { // Add new columns if upgrading from version 1 to 2 // This is a simplified migration. For real apps, check if columns exist before adding. await db.execute('ALTER TABLE $tableName ADD COLUMN description TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN imageUrl TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN serialNumber TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN model TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN tags TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN costPrice REAL;'); await db.execute('ALTER TABLE $tableName ADD COLUMN taxRate REAL;'); await db.execute('ALTER TABLE $tableName ADD COLUMN discount REAL;'); await db.execute('ALTER TABLE $tableName ADD COLUMN profitMargin REAL;'); await db.execute('ALTER TABLE $tableName ADD COLUMN unitOfMeasure TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN location TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN minimumStock INTEGER;'); await db.execute('ALTER TABLE $tableName ADD COLUMN supplier TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN entryDate TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN manufactureDate TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN expirationDate TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN status TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN category TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN brand TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN createdBy TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN createdAt TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN lastModifiedBy TEXT;'); await db.execute('ALTER TABLE $tableName ADD COLUMN lastModifiedAt TEXT;'); } // Add more upgrade paths for future versions if needed } Future insertProduct(Product product) async { final db = await database; final now = DateTime.now().toIso8601String(); // Ensure createdAt and lastModifiedAt are set for new products final productMap = product.toMap(); productMap['createdAt'] = now; productMap['lastModifiedAt'] = now; // You might want to get createdBy from a user session // productMap['createdBy'] = 'current_user_id'; // productMap['lastModifiedBy'] = 'current_user_id'; return await db.insert( tableName, productMap, conflictAlgorithm: ConflictAlgorithm.replace, ); } Future> getProducts() async { final db = await database; final List> maps = await db.query(tableName); return List.generate(maps.length, (i) { return Product.fromMap(maps[i]); }); } Future updateProduct(Product product) async { final db = await database; final now = DateTime.now().toIso8601String(); final productMap = product.toMap(); productMap['lastModifiedAt'] = now; // You might want to get lastModifiedBy from a user session // productMap['lastModifiedBy'] = 'current_user_id'; return await db.update( tableName, productMap, where: 'id = ?', whereArgs: [product.id], ); } Future deleteProduct(int id) async { final db = await database; return await db.delete( tableName, where: 'id = ?', whereArgs: [id], ); } }