feat(frontend): module Production complet (BOM, OF, cycle PLANIFIE→LANCE→TERMINE)
- Modèles ProductionOrder, BomLine - ProductionService : plan, launch, complete, getBom - ProductionProvider : load, plan, launch, complete + stats rapides - ProductionScreen : liste avec filtre statut + actions rapides sur carte - ProductionFormScreen : sélection PF, affichage BOM dynamique, vérif stock - ProductionDetailScreen : infos, lancement OF, clôture avec qté réalisée - Cycle complet : MP consommées au lancement, PF entré en stock à la clôture Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/production_order.dart';
|
||||
import '../services/production_service.dart';
|
||||
|
||||
class ProductionProvider extends ChangeNotifier {
|
||||
List<ProductionOrder> _orders = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
List<ProductionOrder> get orders => _orders;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
|
||||
// Statistiques rapides
|
||||
int get ofPlanifies => _orders.where((o) => o.statut == 'PLANIFIE').length;
|
||||
int get ofEnCours => _orders.where((o) => o.statut == 'LANCE' || o.statut == 'EN_COURS').length;
|
||||
int get ofTermines => _orders.where((o) => o.statut == 'TERMINE').length;
|
||||
|
||||
Future<void> load() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
try {
|
||||
_orders = await ProductionService.fetchAll();
|
||||
} catch (_) {
|
||||
_error = 'Impossible de charger les ordres de fabrication.';
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> plan({
|
||||
required int produitFiniId,
|
||||
required double quantite,
|
||||
required String datePlanifiee,
|
||||
}) async {
|
||||
try {
|
||||
final of = await ProductionService.plan(
|
||||
produitFiniId: produitFiniId,
|
||||
quantite: quantite,
|
||||
datePlanifiee: datePlanifiee,
|
||||
);
|
||||
_orders.insert(0, of);
|
||||
notifyListeners();
|
||||
return null;
|
||||
} catch (e) {
|
||||
final msg = e.toString();
|
||||
if (msg.contains('Stock insuffisant')) return 'Stock matières premières insuffisant';
|
||||
if (msg.contains('nomenclature')) return 'Aucune nomenclature BOM définie pour ce produit';
|
||||
return 'Erreur lors de la planification';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> launch(int id) async {
|
||||
try {
|
||||
final updated = await ProductionService.launch(id);
|
||||
_replaceOrder(updated);
|
||||
return null;
|
||||
} catch (_) {
|
||||
return 'Erreur lors du lancement de l\'OF';
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> complete(int id, double quantiteRealisee) async {
|
||||
try {
|
||||
final updated = await ProductionService.complete(id, quantiteRealisee);
|
||||
_replaceOrder(updated);
|
||||
return null;
|
||||
} catch (_) {
|
||||
return 'Erreur lors de la clôture de l\'OF';
|
||||
}
|
||||
}
|
||||
|
||||
void _replaceOrder(ProductionOrder updated) {
|
||||
final idx = _orders.indexWhere((o) => o.id == updated.id);
|
||||
if (idx != -1) _orders[idx] = updated;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user