barcode_scanner/lib/pages/operation/reception/reception_scan_page_model.dart
your-name 18f74daae4 feat: Implement explicit synchronization and validation
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.
2025-07-31 02:34:50 +03:00

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;
}