enhance: Enhances reception details with refresh and syncs scan quantities

Adds pull-to-refresh functionality to the reception details page, allowing users to manually update the displayed information.

Ensures that when a product is scanned, both the move line and the main move entities have their quantities correctly incremented, improving data consistency.
This commit is contained in:
your-name 2025-07-30 20:00:03 +03:00
parent da2c3ac4f0
commit 46b93d7fa4
2 changed files with 99 additions and 90 deletions

View File

@ -39,101 +39,103 @@ class _ReceptionDetailsPageState extends ConsumerState<ReceptionDetailsPage> {
), ),
body: state.loading body: state.loading
? Center(child: LoadingProgressComponent()) ? Center(child: LoadingProgressComponent())
: Padding( : RefreshIndicator(
padding: const EdgeInsets.symmetric(horizontal: 16), color: AppTheme.of(context).white,
child: ListView( backgroundColor: AppTheme.of(context).primary,
children: [ onRefresh: () async {
const SizedBox(height: 16), await ref
if (reception?.isDone == false) ...[ .read(receptionDetailsPageModelProvider.notifier)
QuickActionComponent( .getReceptionById(id: widget.receptionId);
onTapScan: () { },
final id = reception?.id; child: Padding(
if (id == null) return; padding: const EdgeInsets.symmetric(horizontal: 16),
ReceptionScanRoute(receptionId: id).push(context); child: ListView(
}, children: [
),
const SizedBox(height: 16), const SizedBox(height: 16),
], if (reception?.isDone == false) ...[
Text( QuickActionComponent(
'Détails réception', onTapScan: () {
style: AppTheme.of( final id = reception?.id;
context, if (id == null) return;
).bodyMedium.copyWith(fontWeight: FontWeight.bold), ReceptionScanRoute(receptionId: id).push(context);
), },
SizedBox(height: 10),
StockPickingCard(
isDone: reception?.isDone == true,
margin: EdgeInsets.symmetric(horizontal: 5),
reference: reception?.name ?? '',
from: reception?.locationId.target?.completeName,
to: reception?.locationDestId.target?.completeName,
contact: reception?.partnerId.target?.displayName,
origin: reception?.origin,
status: reception?.state,
),
SizedBox(height: 20),
ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
primary: true,
children: [
Text(
'Produits',
style: AppTheme.of(
context,
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
), ),
SizedBox(height: 10), const SizedBox(height: 16),
...reception?.moveIdsWithoutPackage ],
.map( Text(
(move) => Card( 'Détails réception',
color: AppTheme.of(context).primaryBackground, style: AppTheme.of(
child: ListTile( context,
title: Text( ).bodyMedium.copyWith(fontWeight: FontWeight.bold),
move.productId.target?.displayName ?? '', ),
style: TextStyle(color: Colors.black), SizedBox(height: 10),
), StockPickingCard(
subtitle: Wrap( isDone: reception?.isDone == true,
spacing: 5, margin: EdgeInsets.symmetric(horizontal: 5),
children: [ reference: reception?.name ?? '',
Chip( from: reception?.locationId.target?.completeName,
backgroundColor: AppTheme.of( to: reception?.locationDestId.target?.completeName,
context, contact: reception?.partnerId.target?.displayName,
).secondaryBackground, origin: reception?.origin,
label: Text( status: reception?.state,
"Qté demandée: ${move.productUomQty}", ),
SizedBox(height: 20),
Text(
'Produits',
style: AppTheme.of(
context,
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
...reception?.moveIdsWithoutPackage
.map(
(move) => Card(
color: AppTheme.of(context).primaryBackground,
child: ListTile(
title: Text(
move.productId.target?.displayName ?? '',
style: TextStyle(color: Colors.black),
),
subtitle: Wrap(
spacing: 5,
children: [
Chip(
backgroundColor: AppTheme.of(
context,
).secondaryBackground,
label: Text(
"Qté demandée: ${move.productUomQty}",
),
),
Chip(
backgroundColor: AppTheme.of(
context,
).secondaryBackground,
label: Text(
"Qté reçue: ${move.quantity}",
),
),
Chip(
backgroundColor: AppTheme.of(
context,
).secondaryBackground,
label: Text(
"Ecart: ${move.ecart}",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
), ),
), ),
Chip( ),
backgroundColor: AppTheme.of( ],
context,
).secondaryBackground,
label: Text(
"Qté reçue: ${move.quantity}",
),
),
Chip(
backgroundColor: AppTheme.of(
context,
).secondaryBackground,
label: Text(
"Ecart: ${move.ecart}",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
),
],
),
), ),
), ),
) ),
.toList() ?? )
[], .toList() ??
], [],
), ],
], ),
), ),
), ),
floatingActionButton: reception?.isDone == false floatingActionButton: reception?.isDone == false

View File

@ -52,6 +52,7 @@ class ReceptionScanPageModel
void incrementMoveLineQuantity({required String barcode}) { void incrementMoveLineQuantity({required String barcode}) {
final moveLineBox = objectboxManager.store final moveLineBox = objectboxManager.store
.box<MoveLineWithoutPackageEntity>(); .box<MoveLineWithoutPackageEntity>();
final moveBox = objectboxManager.store.box<MoveWithoutPackageEntity>();
final productBox = objectboxManager.store.box<ProductEntity>(); final productBox = objectboxManager.store.box<ProductEntity>();
final productEntity = productBox final productEntity = productBox
.query(ProductEntity_.barcode.equals(barcode)) .query(ProductEntity_.barcode.equals(barcode))
@ -63,9 +64,15 @@ class ReceptionScanPageModel
.query(MoveLineWithoutPackageEntity_.productId.equals(productId)) .query(MoveLineWithoutPackageEntity_.productId.equals(productId))
.build() .build()
.findFirst(); .findFirst();
if (moveLineEntity != null) { final moveEntity = moveBox
.query(MoveWithoutPackageEntity_.productId.equals(productId))
.build()
.findFirst();
if (moveLineEntity != null && moveEntity != null) {
moveLineEntity.quantity = (moveLineEntity.quantity ?? 0) + 1; moveLineEntity.quantity = (moveLineEntity.quantity ?? 0) + 1;
moveEntity.quantity = (moveEntity.quantity ?? 0) + 1;
moveLineBox.put(moveLineEntity); moveLineBox.put(moveLineEntity);
moveBox.put(moveEntity);
} }
} }
} }