diff --git a/lib/barcode.dart b/lib/barcode.dart index 805c7b7d..f88f5cba 100644 --- a/lib/barcode.dart +++ b/lib/barcode.dart @@ -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 createState() => _QRViewState(_handler); -} - - -class _QRViewState extends State { - - 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: [ - 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 onBarcodeMatched(Map data) { + Future onBarcodeMatched(Map 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, ); - } } } @@ -404,14 +328,136 @@ class StockLocationScanInItemsHandler extends BarcodeHandler { @override String getOverlayText(BuildContext context) => I18N.of(context).barcodeScanItem; - + @override - Future onBarcodeMatched(Map data) { - print("TODO, YO!"); + Future onBarcodeMatched(Map 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 createState() => _QRViewState(_handler); +} + + +class _QRViewState extends State { + + 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: [ + 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 scanQrCode(BuildContext context) async { Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeQRView(BarcodeScanHandler()))); diff --git a/lib/inventree/stock.dart b/lib/inventree/stock.dart index b39e6a04..738dda6f 100644 --- a/lib/inventree/stock.dart +++ b/lib/inventree/stock.dart @@ -486,7 +486,7 @@ class InvenTreeStockItem extends InvenTreeModel { return result; } - Future transferStock(int location, {double quantity, String notes}) async { + Future 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); } } diff --git a/lib/l10n b/lib/l10n index 0e412995..bc85d5b1 160000 --- a/lib/l10n +++ b/lib/l10n @@ -1 +1 @@ -Subproject commit 0e412995061a5b01530d0929f80e06c29ff639f8 +Subproject commit bc85d5b16cd74623ce42bd82b3ac30b9be1da6c6 diff --git a/lib/widget/location_display.dart b/lib/widget/location_display.dart index 50f13dd7..a3c82e1f 100644 --- a/lib/widget/location_display.dart +++ b/lib/widget/location_display.dart @@ -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 { 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 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 detailTiles() { trailing: FaIcon(FontAwesomeIcons.qrcode), ) ); + */ return tiles; }