import 'package:sqflite/sqflite.dart'; import 'package:uuid/uuid.dart'; import '../models/inventory_models.dart'; import 'database_helper.dart'; class InventoryRepository { InventoryRepository(); final DatabaseHelper _dbHelper = DatabaseHelper(); final Uuid _uuid = const Uuid(); Future> fetchSummaries({bool includeHidden = false}) async { final db = await _dbHelper.database; final whereClauses = []; if (!includeHidden) { whereClauses.add('COALESCE(mh.is_hidden, p.is_hidden, 0) = 0'); } final whereSql = whereClauses.isEmpty ? '' : 'WHERE ${whereClauses.join(' AND ')}'; final rows = await db.rawQuery(''' SELECT p.id, p.name, p.category, p.default_unit_price, p.stock_quantity, MAX(m.created_at) AS last_movement_at FROM products p LEFT JOIN master_hidden mh ON mh.master_type = 'product' AND mh.master_id = p.id LEFT JOIN inventory_movements m ON m.product_id = p.id $whereSql GROUP BY p.id ORDER BY p.name COLLATE NOCASE ASC '''); return rows.map((row) { return InventorySummary( productId: row['id'] as String, productName: row['name'] as String? ?? '-', stockQuantity: row['stock_quantity'] as int? ?? 0, category: row['category'] as String?, defaultUnitPrice: row['default_unit_price'] as int?, lastMovementAt: row['last_movement_at'] != null ? DateTime.parse(row['last_movement_at'] as String) : null, ); }).toList(); } Future> fetchMovements(String productId, {int limit = 50}) async { final db = await _dbHelper.database; final rows = await db.query( 'inventory_movements', where: 'product_id = ?', whereArgs: [productId], orderBy: 'created_at DESC', limit: limit, ); return rows.map(InventoryMovement.fromMap).toList(); } Future recordMovement({ required String productId, required InventoryMovementType type, required int quantity, required int quantityDelta, String? reference, String? notes, }) async { final db = await _dbHelper.database; late InventorySummary summary; await db.transaction((txn) async { final productRows = await txn.query('products', where: 'id = ?', whereArgs: [productId], limit: 1); if (productRows.isEmpty) { throw StateError('product not found: $productId'); } final product = productRows.first; final currentStock = product['stock_quantity'] as int? ?? 0; final nextStock = currentStock + quantityDelta; final now = DateTime.now(); final movement = InventoryMovement( id: _uuid.v4(), productId: productId, productNameSnapshot: product['name'] as String? ?? '-', type: type, quantity: quantity, quantityDelta: quantityDelta, reference: reference, notes: notes, createdAt: now, ); await txn.insert('inventory_movements', movement.toMap(), conflictAlgorithm: ConflictAlgorithm.replace); await txn.update('products', {'stock_quantity': nextStock}, where: 'id = ?', whereArgs: [productId]); summary = InventorySummary( productId: productId, productName: product['name'] as String? ?? '-', stockQuantity: nextStock, category: product['category'] as String?, defaultUnitPrice: product['default_unit_price'] as int?, lastMovementAt: now, ); }); return summary; } }