151 lines
5.4 KiB
Dart
151 lines
5.4 KiB
Dart
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<Database> get database async {
|
|
if (_database != null) return _database!;
|
|
_database = await _initDatabase();
|
|
return _database!;
|
|
}
|
|
|
|
Future<Database> _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<void> _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<void> _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<int> 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<List<Product>> getProducts() async {
|
|
final db = await database;
|
|
final List<Map<String, dynamic>> maps = await db.query(tableName);
|
|
return List.generate(maps.length, (i) {
|
|
return Product.fromMap(maps[i]);
|
|
});
|
|
}
|
|
|
|
Future<int> 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<int> deleteProduct(int id) async {
|
|
final db = await database;
|
|
return await db.delete(
|
|
tableName,
|
|
where: 'id = ?',
|
|
whereArgs: [id],
|
|
);
|
|
}
|
|
} |