barcode_scanner/lib/pages/operation/reception/reception_details_page_model.dart
mandreshope d131928235 enhance: Optimizes backorder dialog and fixes loading state
Refactors the backorder dialog to use local Consumer widgets, reducing unnecessary rebuilds and improving performance. Corrects the loading state variable updated when confirming backorders, ensuring accurate UI feedback. Introduces a dedicated refresh method for receptions that includes a pre-sync, ensuring up-to-date data.
2025-08-04 14:50:25 +03:00

197 lines
6.4 KiB
Dart

import 'package:e_scan/backend/api/api_calls.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:e_scan/backend/schema/stock_picking/update_move_line_dto.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'reception_details_page_model.freezed.dart';
final receptionDetailsPageModelProvider =
StateNotifierProvider.autoDispose<
ReceptionDetailsPageModel,
ReceptionDetailsPageState
>((ref) {
return ReceptionDetailsPageModel();
});
class ReceptionDetailsPageModel
extends StateNotifier<ReceptionDetailsPageState> {
ReceptionDetailsPageModel() : super(const ReceptionDetailsPageState());
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);
}
}
Future save({
required int receptionId,
VoidCallback? onSuccess,
VoidCallback? onError,
}) async {
try {
state = state.copyWith(saveLoading: true);
final stockPickingRecords = objectboxManager.store
.box<StockPickingRecordEntity>();
final stockPikingEntity = stockPickingRecords.get(receptionId);
final moveLinesDto =
stockPikingEntity?.moveLineIdsWithoutPackage
.map(
(m) => UpdateMoveLineDto(
operation: 1,
moveLineId: m.id,
values: {"quantity": m.quantity},
),
)
.toList() ??
[];
final res = await ApiCalls.updateAllMoveLineOnStockPicking(
stockPickingId: receptionId,
moveLineDto: moveLinesDto,
);
if (res) {
stockPikingEntity?.synchronized = true;
stockPickingRecords.put(stockPikingEntity!);
getReceptionById(id: receptionId);
onSuccess?.call();
} else {
onError?.call();
}
state = state.copyWith(saveLoading: false);
} catch (e) {
onError?.call();
state = state.copyWith(saveLoading: false);
}
}
Future validate({
required int receptionId,
VoidCallback? onSuccess,
VoidCallback? onError,
}) async {
await save(receptionId: receptionId);
try {
final stockPickingRecords = objectboxManager.store
.box<StockPickingRecordEntity>();
final stockPikingEntity = stockPickingRecords.get(receptionId);
state = state.copyWith(validateLoading: true);
final res = await ApiCalls.validateStockPicking(
stockPickingId: receptionId,
);
if (res) {
onSuccess?.call();
stockPikingEntity?.synchronized = true;
stockPikingEntity?.state = 'done';
stockPickingRecords.put(stockPikingEntity!);
getReceptionById(id: receptionId);
} else {
onError?.call();
}
state = state.copyWith(validateLoading: false);
} catch (e) {
onError?.call();
state = state.copyWith(validateLoading: false);
}
}
Future withBackorder({
required int receptionId,
VoidCallback? onSuccess,
VoidCallback? onError,
}) async {
await save(receptionId: receptionId);
try {
final stockPickingRecords = objectboxManager.store
.box<StockPickingRecordEntity>();
final stockPikingEntity = stockPickingRecords.get(receptionId);
state = state.copyWith(withBackorderLoading: true);
final createBackorderConfirmationId =
await ApiCalls.createBackorderConfirmation(
stockPickingId: receptionId,
toBackorder: true,
);
if (createBackorderConfirmationId != null) {
final res = await ApiCalls.withBackorder(
stockPickingId: receptionId,
createBackorderConfirmationId: createBackorderConfirmationId,
);
if (res) {
stockPikingEntity?.synchronized = true;
stockPikingEntity?.state = 'done';
stockPickingRecords.put(stockPikingEntity!);
await getReceptionById(id: receptionId);
onSuccess?.call();
} else {
onError?.call();
}
} else {
onError?.call();
}
state = state.copyWith(withBackorderLoading: false);
} catch (e) {
onError?.call();
state = state.copyWith(withBackorderLoading: false);
}
}
Future withoutBackorder({
required int receptionId,
VoidCallback? onSuccess,
VoidCallback? onError,
}) async {
await save(receptionId: receptionId);
try {
final stockPickingRecords = objectboxManager.store
.box<StockPickingRecordEntity>();
final stockPikingEntity = stockPickingRecords.get(receptionId);
state = state.copyWith(withoutBackorderLoading: true);
final createBackorderConfirmationId =
await ApiCalls.createBackorderConfirmation(
stockPickingId: receptionId,
toBackorder: false,
);
if (createBackorderConfirmationId != null) {
final res = await ApiCalls.withoutBackorder(
stockPickingId: receptionId,
createBackorderConfirmationId: createBackorderConfirmationId,
);
if (res) {
stockPikingEntity?.synchronized = true;
stockPikingEntity?.state = 'done';
stockPickingRecords.put(stockPikingEntity!);
await getReceptionById(id: receptionId);
onSuccess?.call();
} else {
onError?.call();
}
} else {
onError?.call();
}
state = state.copyWith(withoutBackorderLoading: false);
} catch (e) {
onError?.call();
state = state.copyWith(withoutBackorderLoading: false);
}
}
}
@freezed
abstract class ReceptionDetailsPageState with _$ReceptionDetailsPageState {
const factory ReceptionDetailsPageState({
StockPickingRecordEntity? reception,
@Default(false) bool loading,
@Default(false) bool validateLoading,
@Default(false) bool saveLoading,
@Default(false) bool withBackorderLoading,
@Default(false) bool withoutBackorderLoading,
}) = _ReceptionDetailsPageState;
}