2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-07-10 23:54:12 +00:00

Scan items into location from location context

This commit is contained in:
Oliver Walters
2021-02-17 08:57:08 +11:00
parent b7e9c06dfa
commit 24b7cfaede
4 changed files with 152 additions and 95 deletions

View File

@ -267,86 +267,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
}
class InvenTreeQRView extends StatefulWidget {
final BarcodeHandler _handler;
InvenTreeQRView(this._handler, {Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _QRViewState(_handler);
}
class _QRViewState extends State<InvenTreeQRView> {
QRViewController _controller;
final BarcodeHandler _handler;
BuildContext context;
_QRViewState(this._handler) : super();
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
void _onViewCreated(QRViewController controller) {
_controller = controller;
controller.scannedDataStream.listen((scandata) {
_controller?.pauseCamera();
_handler.processBarcode(context, _controller, scandata);
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Save the context for later on!
this.context = context;
return Scaffold(
body: Stack(
children: <Widget>[
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: _onViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)
),
Center(
child: Column(
children: [
Spacer(),
Padding(
child: Text(_handler.getOverlayText(context),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
padding: EdgeInsets.all(20),
),
]
)
)
],
)
);
}
}
class StockItemScanIntoLocationHandler extends BarcodeHandler {
@ -362,16 +283,16 @@ class StockItemScanIntoLocationHandler extends BarcodeHandler {
String getOverlayText(BuildContext context) => I18N.of(context).barcodeScanLocation;
@override
Future<void> onBarcodeMatched(Map<String, dynamic> data) {
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
// If the barcode points to a 'stocklocation', great!
if (data.containsKey('stocklocation')) {
// Extract location information
int location = data['stocklocation']['pk'] as int;
// Transfer stock to specified location
item.transferStock(location).then((response) {
print("Response: ${response.statusCode}");
final result = await item.transferStock(location);
if (result) {
// Close the scanner
_controller.dispose();
Navigator.of(_context).pop();
@ -380,14 +301,17 @@ class StockItemScanIntoLocationHandler extends BarcodeHandler {
I18N.of(OneContext().context).barcodeScanIntoLocationSuccess,
success: true,
);
});
} else {
showSnackIcon(
I18N.of(OneContext().context).barcodeScanIntoLocationFailure,
success: false
);
}
} else {
showSnackIcon(
I18N.of(OneContext().context).invalidStockLocation,
success: false,
);
}
}
}
@ -406,12 +330,134 @@ class StockLocationScanInItemsHandler extends BarcodeHandler {
String getOverlayText(BuildContext context) => I18N.of(context).barcodeScanItem;
@override
Future<void> onBarcodeMatched(Map<String, dynamic> data) {
print("TODO, YO!");
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
// Returned barcode must match a stock item
if (data.containsKey('stockitem')) {
int item_id = data['stockitem']['pk'] as int;
final InvenTreeStockItem item = await InvenTreeStockItem().get(_context, item_id);
if (item == null) {
showSnackIcon(
I18N.of(OneContext().context).invalidStockItem,
success: false,
);
} else if (item.locationId == location.pk) {
showSnackIcon(
I18N.of(OneContext().context).itemInLocation,
success: true
);
}
else {
final result = await item.transferStock(location.pk);
if (result) {
showSnackIcon(
I18N.of(OneContext().context).barcodeScanIntoLocationSuccess,
success: true
);
} else {
showSnackIcon(
I18N.of(OneContext().context).barcodeScanIntoLocationFailure,
success: false
);
}
}
} else {
// Does not match a valid stock item!
showSnackIcon(
I18N.of(OneContext().context).invalidStockItem,
success: false,
);
}
}
}
class InvenTreeQRView extends StatefulWidget {
final BarcodeHandler _handler;
InvenTreeQRView(this._handler, {Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _QRViewState(_handler);
}
class _QRViewState extends State<InvenTreeQRView> {
QRViewController _controller;
final BarcodeHandler _handler;
BuildContext context;
_QRViewState(this._handler) : super();
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
void _onViewCreated(QRViewController controller) {
_controller = controller;
controller.scannedDataStream.listen((scandata) {
_controller?.pauseCamera();
_handler.processBarcode(context, _controller, scandata);
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Save the context for later on!
this.context = context;
return Scaffold(
body: Stack(
children: <Widget>[
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: _onViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)
),
Center(
child: Column(
children: [
Spacer(),
Padding(
child: Text(_handler.getOverlayText(context),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
padding: EdgeInsets.all(20),
),
]
)
)
],
)
);
}
}
Future<void> scanQrCode(BuildContext context) async {
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeQRView(BarcodeScanHandler())));

View File

@ -486,7 +486,7 @@ class InvenTreeStockItem extends InvenTreeModel {
return result;
}
Future<http.Response> transferStock(int location, {double quantity, String notes}) async {
Future<bool> transferStock(int location, {double quantity, String notes}) async {
if (quantity == null) {} else
if ((quantity < 0) || (quantity > this.quantity)) {
quantity = this.quantity;
@ -504,7 +504,9 @@ class InvenTreeStockItem extends InvenTreeModel {
data["item"]["quantity"] = "${quantity}";
}
return api.post("/stock/transfer/", body: data);
final response = await api.post("/stock/transfer/", body: data);
return (response.statusCode == 200);
}
}

View File

@ -1,4 +1,5 @@
import 'package:InvenTree/api.dart';
import 'package:InvenTree/barcode.dart';
import 'package:InvenTree/inventree/stock.dart';
import 'package:InvenTree/preferences.dart';
import 'package:InvenTree/widget/progress.dart';
@ -224,12 +225,10 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
label: I18N.of(context).stock,
),
// TODO - Add in actions when they are written...
/*
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.wrench),
label: I18N.of(context).actions,
)
*/
]
);
}
@ -324,14 +323,23 @@ List<Widget> detailTiles() {
// Scan items into location
tiles.add(
ListTile(
title: Text("Scan in Stock Item"),
title: Text(I18N.of(context).barcodeScanInItems),
leading: FaIcon(FontAwesomeIcons.exchangeAlt),
trailing: FaIcon(FontAwesomeIcons.qrcode),
onTap: null,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => InvenTreeQRView(StockLocationScanInItemsHandler(location)))
).then((context) {
refresh();
});
},
)
);
// Move location into another location
// TODO: Implement this!
/*
tiles.add(
ListTile(
title: Text("Move Stock Location"),
@ -339,6 +347,7 @@ List<Widget> detailTiles() {
trailing: FaIcon(FontAwesomeIcons.qrcode),
)
);
*/
return tiles;
}