
Refactors the reception process to provide clearer control over data synchronization and validation. - Replaces the `isDraft` property with `synchronized` in `StockPickingRecordEntity` to accurately represent the local data's sync status with the backend. - Introduces a new API endpoint and corresponding logic for `validateStockPicking`, allowing finalization of receptions. - Splits the "Save" action into "Synchronize data" and "Validate reception" on the details page. "Validate" now implicitly performs a synchronization first. - Updates UI elements (cards, quick actions) to reflect the new synchronization state and expose the new actions. - Corrects a typo in the `updateAllMoveLineOnStockPicking` API method name. - Improves local data update logic for scanned items, marking them as unsynchronized.
86 lines
3.0 KiB
Dart
86 lines
3.0 KiB
Dart
import 'package:e_scan/backend/objectbox/entities/product/product_entity.dart';
|
|
import 'package:e_scan/backend/objectbox/entities/stock_picking/stock_picking_record_entity.dart';
|
|
import 'package:e_scan/backend/objectbox/objectbox_manager.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
part 'reception_scan_page_model.freezed.dart';
|
|
|
|
final receptionScanPageModelProvider =
|
|
StateNotifierProvider.autoDispose<
|
|
ReceptionScanPageModel,
|
|
ReceptionScanPageModelState
|
|
>((ref) {
|
|
return ReceptionScanPageModel();
|
|
});
|
|
|
|
class ReceptionScanPageModel
|
|
extends StateNotifier<ReceptionScanPageModelState> {
|
|
ReceptionScanPageModel() : super(const ReceptionScanPageModelState());
|
|
|
|
Future getReceptionById({required int id}) async {
|
|
try {
|
|
final stockPickingRecords = objectboxManager.store
|
|
.box<StockPickingRecordEntity>();
|
|
state = state.copyWith(loading: true);
|
|
final entity = stockPickingRecords.get(id);
|
|
state = state.copyWith(loading: false, reception: entity);
|
|
} catch (e) {
|
|
state = state.copyWith(loading: false);
|
|
}
|
|
}
|
|
|
|
bool isProductExist({required String barcode}) {
|
|
final productBox = objectboxManager.store.box<ProductEntity>();
|
|
return productBox
|
|
.query(ProductEntity_.barcode.equals(barcode))
|
|
.build()
|
|
.findFirst() !=
|
|
null;
|
|
}
|
|
|
|
ProductEntity? getProduct({required String barcode}) {
|
|
final productBox = objectboxManager.store.box<ProductEntity>();
|
|
return productBox
|
|
.query(ProductEntity_.barcode.equals(barcode))
|
|
.build()
|
|
.findFirst();
|
|
}
|
|
|
|
void incrementMoveLineQuantity({
|
|
required String barcode,
|
|
required int receptionId,
|
|
}) {
|
|
final moveLineBox = objectboxManager.store
|
|
.box<MoveLineWithoutPackageEntity>();
|
|
final stockPickingRecordBox = objectboxManager.store
|
|
.box<StockPickingRecordEntity>();
|
|
final moveBox = objectboxManager.store.box<MoveWithoutPackageEntity>();
|
|
final stockPickingRecord = stockPickingRecordBox.get(receptionId);
|
|
final moveLineEntity = stockPickingRecord?.moveLineIdsWithoutPackage
|
|
.firstWhere((e) => e.productId.target?.barcode == barcode);
|
|
final moveEntity = stockPickingRecord?.moveIdsWithoutPackage.firstWhere(
|
|
(e) => e.productId.target?.barcode == barcode,
|
|
);
|
|
if (moveLineEntity != null &&
|
|
moveEntity != null &&
|
|
stockPickingRecord != null) {
|
|
moveLineEntity.quantity = (moveLineEntity.quantity ?? 0) + 1;
|
|
moveEntity.quantity = (moveEntity.quantity ?? 0) + 1;
|
|
stockPickingRecord.synchronized = false;
|
|
moveLineBox.put(moveLineEntity);
|
|
moveBox.put(moveEntity);
|
|
stockPickingRecordBox.put(stockPickingRecord);
|
|
}
|
|
}
|
|
}
|
|
|
|
@freezed
|
|
abstract class ReceptionScanPageModelState with _$ReceptionScanPageModelState {
|
|
const factory ReceptionScanPageModelState({
|
|
StockPickingRecordEntity? reception,
|
|
@Default(false) bool loading,
|
|
}) = _ReceptionScanPageModelState;
|
|
}
|