velmart-picker/lib/data/services/order_service.dart
Fibe Agent 5ba2691eac feat: initial Velmart Picker Flutter app
- All 5 batch steps: Picking, Sorting, Clarification, Slots, Handoff
- go_router navigation with step indicator
- graphql_flutter client wired up (endpoint via env var)
- Mock data layer swappable with real GraphQL service
- Item types: normal, cold, frozen, alcohol, clarify
- Storage slot assignment (cell/freezer/fridge)
2026-04-23 21:43:07 +00:00

101 lines
3.3 KiB
Dart

import '../models/models.dart';
import '../mock/mock_data.dart';
/// Abstract interface — swap MockOrderService for GraphQLOrderService
/// when the backend is ready. No other code changes needed.
abstract class OrderService {
Future<List<Order>> getOrderQueue({OrderStatus? status});
Future<Order> getOrderDetail(int orderId);
Future<void> markItemPicked(int itemId, double actualQty);
Future<void> markItemNotFound(int itemId);
Future<void> replaceItem(int itemId, String substituteSku, double actualQty);
Future<List<StorageSlot>> getAvailableSlots();
Future<void> assignSlots(int orderId, List<int> slotIds);
Future<void> finalizeOrder(int orderId);
}
/// Mock implementation — works entirely in-memory with fake data.
class MockOrderService implements OrderService {
final List<Order> _orders = MockData.orders;
@override
Future<List<Order>> getOrderQueue({OrderStatus? status}) async {
await Future.delayed(const Duration(milliseconds: 300));
if (status == null) return List.from(_orders);
return _orders.where((o) => o.status == status).toList();
}
@override
Future<Order> getOrderDetail(int orderId) async {
await Future.delayed(const Duration(milliseconds: 200));
return _orders.firstWhere((o) => o.id == orderId);
}
@override
Future<void> markItemPicked(int itemId, double actualQty) async {
await Future.delayed(const Duration(milliseconds: 150));
for (final order in _orders) {
for (final segment in order.segments) {
final item = segment.items.where((i) => i.id == itemId).firstOrNull;
if (item != null) {
item.status = ItemStatus.picked;
item.actualQty = actualQty;
return;
}
}
}
}
@override
Future<void> markItemNotFound(int itemId) async {
await Future.delayed(const Duration(milliseconds: 150));
for (final order in _orders) {
for (final segment in order.segments) {
final item = segment.items.where((i) => i.id == itemId).firstOrNull;
if (item != null) {
item.status = ItemStatus.notFound;
return;
}
}
}
}
@override
Future<void> replaceItem(int itemId, String substituteSku, double actualQty) async {
await Future.delayed(const Duration(milliseconds: 150));
for (final order in _orders) {
for (final segment in order.segments) {
final item = segment.items.where((i) => i.id == itemId).firstOrNull;
if (item != null) {
item.status = ItemStatus.replaced;
item.actualQty = actualQty;
return;
}
}
}
}
@override
Future<List<StorageSlot>> getAvailableSlots() async {
await Future.delayed(const Duration(milliseconds: 200));
return MockData.availableSlots;
}
@override
Future<void> assignSlots(int orderId, List<int> slotIds) async {
await Future.delayed(const Duration(milliseconds: 200));
final order = _orders.firstWhere((o) => o.id == orderId);
final slots = MockData.availableSlots.where((s) => slotIds.contains(s.id)).toList();
order.assignedSlots
..clear()
..addAll(slots);
}
@override
Future<void> finalizeOrder(int orderId) async {
await Future.delayed(const Duration(milliseconds: 300));
final order = _orders.firstWhere((o) => o.id == orderId);
order.status = OrderStatus.issued;
}
}