diff --git a/lib/core/entity/Voucher.dart b/lib/core/entity/Voucher.dart index 5a50a94..8b6740a 100644 --- a/lib/core/entity/Voucher.dart +++ b/lib/core/entity/Voucher.dart @@ -12,6 +12,7 @@ const String Voucher_columnUrl = 'url'; const String VoucherTypePayment = 'payment'; +const String VoucherTypeReturnPay = 'returnPay'; const String VoucherTypeReport = 'report'; class Voucher { diff --git a/lib/core/route_names.dart b/lib/core/route_names.dart index d6ac0a5..f880aa9 100644 --- a/lib/core/route_names.dart +++ b/lib/core/route_names.dart @@ -3,4 +3,6 @@ const String HomeViewRoute = "HomeView"; const String ImageShowRoute = "ImageShowRoute"; const String PaymentViewRoute = "PaymentView"; const String HistoryViewRoute = "HistoryView"; +const String InfoKkmViewRoute = "InfoKkmViewRoute"; +const String QrViewRoute = "QrViewRoute"; // Generate the views here diff --git a/lib/core/router.dart b/lib/core/router.dart index 3afc806..b8b1fe8 100644 --- a/lib/core/router.dart +++ b/lib/core/router.dart @@ -1,6 +1,8 @@ import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; import 'package:aman_kassa_flutter/views/history/history_view.dart'; +import 'package:aman_kassa_flutter/views/info_kkm/info_kkm_view.dart'; import 'package:aman_kassa_flutter/views/payment/payment_view.dart'; +import 'package:aman_kassa_flutter/views/qr_view/qr_view.dart'; import './route_names.dart'; import 'package:aman_kassa_flutter/views/home/home_view.dart'; @@ -30,9 +32,24 @@ Route generateRoute(RouteSettings settings) { routeName: settings.name, viewToShow: HistoryView(), ); + case InfoKkmViewRoute: + return _getPageRoute( + routeName: settings.name, + viewToShow: InfoKkmView(), + ); + case QrViewRoute: + ImageShowModel data = settings.arguments as ImageShowModel; + return _getPageRoute( + routeName: settings.name, + viewToShow: QrView(data), + ); case ImageShowRoute: ImageShowModel data = settings.arguments as ImageShowModel; - return SlideRightRoute(widget: ImageShowContainer(data)); + //return SlideRightRoute(widget: ImageShowContainer(data)); + return _getPageRoute( + routeName: settings.name, + viewToShow: ImageShowContainer(data), + ); default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/core/services/ApiService.dart b/lib/core/services/ApiService.dart index 448b496..4cde25d 100644 --- a/lib/core/services/ApiService.dart +++ b/lib/core/services/ApiService.dart @@ -16,8 +16,10 @@ import 'package:http/http.dart' as http; /// The service responsible for networking requests class ApiService extends BaseService { - static const test_endpoint = 'https://kassa-test.aman.com.kz/ru/api/v2'; - static const endpoint = 'https://kassa.aman.com.kz/ru/api/v2'; + static const test_host = 'https://kassa-test.aman.com.kz'; + static const test_endpoint = '$test_host/ru/api/v2'; + static const host = 'https://kassa.aman.com.kz'; + static const endpoint = '$host/ru/api/v2'; final NavigatorService _navigatorService = locator(); final DialogService _dialogService = locator(); @@ -64,6 +66,12 @@ class ApiService extends BaseService { return Response.fromJsonDynamic(json.decode(response)); } + Future> infoKkm(String token) async { + Map requestBody = {'api_token': token}; + var response = await requestFormData('/info', requestBody); + return Response.fromJsonDynamic(json.decode(response)); + } + Future> deposit(String token, String sum) async { Map requestBody = {'api_token': token, 'summ': sum}; var response = await requestFormData('/deposit', requestBody); @@ -172,4 +180,5 @@ class ApiService extends BaseService { var response = await requestFormData('/services', requestBody); return Response.fromJsonDynamic(json.decode(response)); } + } diff --git a/lib/core/services/DataService.dart b/lib/core/services/DataService.dart index 2f49ed3..524c7a7 100644 --- a/lib/core/services/DataService.dart +++ b/lib/core/services/DataService.dart @@ -151,11 +151,18 @@ class DataService extends BaseService { User user = Redux.store.state.userState.user; String check = response?.body['check']; dynamic journal = response?.body['journal']; - print(journal); + String url = response?.body['link']; int checkNum = journal['check_num']; var summ = journal['summ']; double total = summ!= null ? double.parse(summ.toString()) : 0.0; - this.insertVoucher(user: user, name: 'Чек №$checkNum', data: data , base64Data: check, total: total ); + this.insertVoucher( + user: user, + name: 'Чек №$checkNum', + data: data , + base64Data: check, + total: total, + url: url, + type: operationType == OperationTypeReturn ? VoucherTypeReturnPay : VoucherTypePayment ); } return response; } catch (e) { diff --git a/lib/views/check/image_show_container.dart b/lib/views/check/image_show_container.dart index 7ab716e..99af302 100644 --- a/lib/views/check/image_show_container.dart +++ b/lib/views/check/image_show_container.dart @@ -2,7 +2,9 @@ import 'dart:convert'; import 'dart:io'; import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/models/dialog_models.dart'; +import 'package:aman_kassa_flutter/core/route_names.dart'; import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; +import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart'; @@ -41,8 +43,9 @@ Padding imageFromBase64String(String base64String) { class ImageShowModel { final String data; final String title; + final String url; - ImageShowModel(this.data, this.title); + ImageShowModel({ this.data, this.title, this.url}); } class MyFloatingActionButton extends StatefulWidget { @@ -55,6 +58,7 @@ class MyFloatingActionButton extends StatefulWidget { class _MyFloatingActionButtonState extends State { bool showFab = true; DialogService _dialog = locator(); + NavigatorService _navigatorService = locator(); // String _batteryLevel = 'Unknown battery level.'; // static const platform = const MethodChannel('samples.flutter.dev/battery'); // @@ -93,21 +97,22 @@ class _MyFloatingActionButtonState extends State { spreadRadius: 5) ]), //color: Colors.grey[900], - height: 200, + height: 260, child: Column( - children: [ - //verticalSpaceSmall, - //BusyButton(title: 'Электронная почта', onPressed: shareFile , mainColor: primaryColor, icon: Icons.mail, enabled: false, ), + children: [ verticalSpaceSmall, BusyButton( title: 'WhatsApp', onPressed: callWhatsApp, mainColor: greenColor, icon: MdiIcons.whatsapp, + enabled: widget.data.url != null, ), verticalSpaceSmall, + BusyButton(title: 'QR-код чека', onPressed: qrGenerate , mainColor: primaryColor, icon: MdiIcons.qrcode, enabled: widget.data.url != null, ), + verticalSpaceSmall, BusyButton( - title: '', + title: 'Поделиться', onPressed: shareFile, mainColor: yellowColor, icon: Icons.share, @@ -132,6 +137,10 @@ class _MyFloatingActionButtonState extends State { } } + void qrGenerate() async { + _navigatorService.push(QrViewRoute, arguments: ImageShowModel(data: widget.data.url, title: 'Спасибо за покупку')); + } + void callWhatsApp() async { DialogResponse response = await _dialog.showConfirmationDialogInput( description: 'Номер телефона', @@ -140,7 +149,7 @@ class _MyFloatingActionButtonState extends State { ); if (response.confirmed) { String phoneNumber = response.responseText; - String msg = "Спасибо за покупку! \r\n https://picsum.photos/200/300 "; + String msg = "Спасибо за покупку! \r\n ${widget.data.url} "; launchWhatsApp(phone: phoneNumber, message: msg); //FlutterOpenWhatsapp.sendSingleMessage(phoneNumber, "Спасибо что выбераете нас \r\n https://picsum.photos/200/300 "); diff --git a/lib/views/history/history_view.dart b/lib/views/history/history_view.dart index 8803ce9..a1635a7 100644 --- a/lib/views/history/history_view.dart +++ b/lib/views/history/history_view.dart @@ -22,16 +22,16 @@ class _HistoryViewState extends State { NavigatorService _navigatorService = locator(); List data = []; @override - void initState() { + void initState() { super.initState(); load(); } load() async { - List list = await _dbService.queryAllRowsOrderBy(Voucher_tableName, '$Voucher_columnDateTime desc'); - print(list); + List list = await _dbService.queryAllRowsOrderBy( + Voucher_tableName, '$Voucher_columnDateTime desc'); setState(() { - data = list.map((e) => Voucher.fromMap(e)).toList(); + data = list.map((e) => Voucher.fromMap(e)).toList(); }); } @@ -42,39 +42,62 @@ class _HistoryViewState extends State { title: Text('История чеков'), actions: [ FlatButton( - child: Text('Очистить', style: TextStyle(color: whiteColor, fontSize: 15, fontWeight: FontWeight.bold),), - onPressed: () async { - await _dbService.deleteAll(Voucher_tableName); - await this.load(); - }) + child: Text( + 'Очистить', + style: TextStyle( + color: whiteColor, + fontSize: 15, + fontWeight: FontWeight.bold), + ), + onPressed: () async { + await _dbService.deleteAll(Voucher_tableName); + await this.load(); + }) ], ), body: ListView.separated( itemCount: data.length, separatorBuilder: (BuildContext context, int index) { - return Divider(); - }, + return Divider(); + }, itemBuilder: (BuildContext context, int index) { Voucher voucher = data[index]; - return ListTile( - onTap: (){ - _navigatorService.push(ImageShowRoute, - arguments: ImageShowModel(voucher.base64Data, voucher.name)); - }, - title: buildText(voucher), - subtitle: Text(dateFormat.format(voucher.dateTime)), - trailing: Icon(Icons.arrow_right), - leading: voucher.type == VoucherTypePayment ? Icon(MdiIcons.cashRegister, size: 40,) : Icon(Icons.description, size: 40,), - ); - }, + return ListTile( + onTap: () { + _navigatorService.push(ImageShowRoute, + arguments: ImageShowModel( + data: voucher.base64Data, + title: voucher.name, + url: voucher.url)); + }, + title: buildText(voucher), + subtitle: Text(dateFormat.format(voucher.dateTime)), + trailing: Icon(Icons.arrow_right), + leading: voucher.type == VoucherTypePayment + ? Icon( + MdiIcons.cashRegister, + size: 40, + ) + : voucher.type == VoucherTypeReturnPay ? + Icon( + MdiIcons.backupRestore, + size: 40, + ) + : Icon( + Icons.description, + size: 40, + ), + ); + }, ), ); } - Text buildText(Voucher voucher) { - if( voucher.type == VoucherTypePayment ){ - return Text('${voucher.name} на сумму: ${voucher.total.toStringAsFixed(2)}'); + Text buildText(Voucher voucher) { + if (voucher.type == VoucherTypePayment || voucher.type == VoucherTypeReturnPay) { + return Text( + '${voucher.name} на сумму: ${voucher.total.toStringAsFixed(2)}'); } return Text('${voucher.name}'); - } + } } diff --git a/lib/views/home/components/popup_menu.dart b/lib/views/home/components/popup_menu.dart index 432159b..a2b0d8b 100644 --- a/lib/views/home/components/popup_menu.dart +++ b/lib/views/home/components/popup_menu.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; const List choices = const [ //const Choice(title: 'Обновить номенклатуру', icon: Icons.update, command: 'update'), //const Choice(title: 'Помощь', icon: Icons.help, command: 'help'), - //const Choice(title: 'О Программе', icon: Icons.info_outline, command: 'info'), + const Choice(title: 'Информацио о ККМ', icon: Icons.info_outline, command: 'infokkm'), //const Choice(title: 'Язык', icon: Icons.language, command: 'language'), const Choice(title: 'Выйти', icon: Icons.exit_to_app, command: 'exit') ]; diff --git a/lib/views/home/home_view.dart b/lib/views/home/home_view.dart index bc9554b..46c3459 100644 --- a/lib/views/home/home_view.dart +++ b/lib/views/home/home_view.dart @@ -2,6 +2,7 @@ import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/logger.dart'; import 'package:aman_kassa_flutter/core/models/choice.dart'; import 'package:aman_kassa_flutter/core/models/response.dart'; +import 'package:aman_kassa_flutter/core/route_names.dart'; import 'package:aman_kassa_flutter/core/services/ApiService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart'; import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; @@ -61,11 +62,8 @@ class _HomeViewState extends State { Redux.store.dispatch(logoutAction); } Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); - } else if (choice.command == 'update') { - Dialogs.showLoadingDialog(context, _keyLoader); - bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user); - log.i('result: $result'); - Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + } else if (choice.command == 'infokkm') { + _navigatorService.push(InfoKkmViewRoute); } } diff --git a/lib/views/home/tabs/AdditionalTab.dart b/lib/views/home/tabs/AdditionalTab.dart index c89067e..4b2b131 100644 --- a/lib/views/home/tabs/AdditionalTab.dart +++ b/lib/views/home/tabs/AdditionalTab.dart @@ -86,12 +86,18 @@ class _AdditionalTabState extends State { xReportBusy = true; }); User user = Redux.store.state.userState.user; - Response response = - await _api.xReport(user.token); - if (response.operation) { + Response response = await _api.xReport(user.token); + if (response.operation) { _navigator.push(ImageShowRoute, - arguments: ImageShowModel(response.body['check'], 'X Отчет')); - _dataService.insertVoucher(user: user, name: 'X Отчет', base64Data: response.body['check'], type: VoucherTypeReport); + arguments: + ImageShowModel(data: response.body['check'], title: 'X Отчет')); + String url = response?.body['link']; + _dataService.insertVoucher( + user: user, + name: 'X Отчет', + base64Data: response.body['check'], + type: VoucherTypeReport, + url: url); } else { _dialog.showDialog(description: response.body['message']); } @@ -104,16 +110,15 @@ class _AdditionalTabState extends State { setState(() { updateCatalog = true; }); - Dialogs.showLoadingDialog(context, _keyLoader); - bool result = await _dataService.getDataFromServer(Redux.store.state.userState.user); - Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + Dialogs.showLoadingDialog(context, _keyLoader); + bool result = + await _dataService.getDataFromServer(Redux.store.state.userState.user); + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); setState(() { updateCatalog = false; }); } - - void _deposit() async { setState(() { depositBusy = true; @@ -318,7 +323,7 @@ class _AdditionalTabState extends State { ), AmanIconButton( title: 'История чеков', - onPressed: (){ + onPressed: () { _navigator.push(HistoryViewRoute); }, mainColor: yellowColor, @@ -331,7 +336,6 @@ class _AdditionalTabState extends State { mainColor: greenColor, icon: MdiIcons.databaseRefresh, ), - ], ), verticalSpaceMedium, diff --git a/lib/views/info_kkm/info_kkm_view.dart b/lib/views/info_kkm/info_kkm_view.dart new file mode 100644 index 0000000..b42aa31 --- /dev/null +++ b/lib/views/info_kkm/info_kkm_view.dart @@ -0,0 +1,120 @@ +import 'package:aman_kassa_flutter/core/entity/Voucher.dart'; +import 'package:aman_kassa_flutter/core/locator.dart'; +import 'package:aman_kassa_flutter/core/models/response.dart'; +import 'package:aman_kassa_flutter/core/models/user.dart'; +import 'package:aman_kassa_flutter/core/route_names.dart'; +import 'package:aman_kassa_flutter/core/services/ApiService.dart'; +import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; +import 'package:aman_kassa_flutter/redux/store.dart'; +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; + +class InfoKkmView extends StatefulWidget { + InfoKkmView(); + + @override + _InfoKkmViewState createState() => _InfoKkmViewState(); +} + +class _InfoKkmViewState extends State { + DateFormat dateFormat = DateFormat("dd.MM.yyyy HH:mm:ss"); + ApiService _apiService = locator(); + List data = []; + bool loading = false; + @override + void initState() { + super.initState(); + load(); + } + + load() async { + setState(() { + loading = true; + }); + User user = Redux.store.state.userState.user; + Response response = await _apiService.infoKkm(user.token); + if (response.operation) { + List list = []; + for (var key in response.body.keys) { + switch (key) { + case 'sn': + list.add({'key': 'Серийный номер', 'value': response.body[key]}); + break; + case 'name': + list.add( + {'key': 'Наименование компании', 'value': response.body[key]}); + break; + case 'biniin': + list.add({'key': 'ИИН/БИН', 'value': response.body[key]}); + break; + case 'address': + list.add({'key': 'Адрес', 'value': response.body[key]}); + break; + case 'kkmreg': + list.add({ + 'key': 'Регистрационный номер в органах НК', + 'value': response.body[key] + }); + break; + default: + } + } + setState(() { + data = list; + }); + } + setState(() { + loading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text('Информация о ККМ'), + ), + body: loading + ? Container(child: Center(child: CircularProgressIndicator())) + : SingleChildScrollView( + child: Container( + margin: const EdgeInsets.all(8.0), + child: Table( + //defaultVerticalAlignment: TableCellVerticalAlignment.top, + children: data.map((e) { + return this.buildRow(e['key'], e['value']); + }).toList(), + ), + ), + ), + ); + } + + TableRow buildRow(String key, String value) { + return TableRow( + children: [ + Container( + child: Text( + '$key :', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 15.0, + ), + ), + margin: EdgeInsets.only(bottom: 8.0), + ), + Container( + child: Text( + value, + style: TextStyle(fontSize: 15.0), + ), + margin: EdgeInsets.only(bottom: 8.0), + ), + ], + ); + } +} diff --git a/lib/views/login/login_view.dart b/lib/views/login/login_view.dart index f5c4d1e..4ae217d 100644 --- a/lib/views/login/login_view.dart +++ b/lib/views/login/login_view.dart @@ -20,8 +20,8 @@ import 'package:flutter/material.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; class LoginView extends StatelessWidget { - final emailController = TextEditingController(text: 'test@kkm-kassa.kz'); - final passwordController = TextEditingController(text: 'qwe123'); + final emailController = TextEditingController(); + final passwordController = TextEditingController(); final FocusNode passwordNode = new FocusNode(); final GlobalKey _scaffoldKey = new GlobalKey(); diff --git a/lib/views/payment/payment_view.dart b/lib/views/payment/payment_view.dart index 5cff5fc..cc2cb79 100644 --- a/lib/views/payment/payment_view.dart +++ b/lib/views/payment/payment_view.dart @@ -3,6 +3,7 @@ import 'package:aman_kassa_flutter/core/models/calc_model.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart'; import 'package:aman_kassa_flutter/core/models/response.dart'; import 'package:aman_kassa_flutter/core/route_names.dart'; +import 'package:aman_kassa_flutter/core/services/ApiService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart'; import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; @@ -188,28 +189,38 @@ class _PaymentViewState extends State { tradeType: _tradeType, calcItems: calcItems, mode: _mode); - Navigator.of(context, rootNavigator: true).pop(); setState(() { isBusy = false; }); - if (response.operation) { - String message = response.body['message']; - String check = response.body['check']; - if (_mode == SettingModeCalc) { - Redux.store.dispatch(cleanCalcItems); - } else if (_mode == SettingModeKassa) { - Redux.store.dispatch(cleanKassaItems); + if( response != null) { + if (response.operation) { + String message = response.body['message']; + String check = response.body['check']; + String url = response?.body['link']; + print('url : $url'); + if (_mode == SettingModeCalc) { + Redux.store.dispatch(cleanCalcItems); + } else if (_mode == SettingModeKassa) { + Redux.store.dispatch(cleanKassaItems); + } + Redux.store.dispatch(checkMoney); + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + _navigatorService.pop(); + _navigatorService.push(ImageShowRoute, + arguments: ImageShowModel(data:check, title: message, url: url )); + } else if (!response.operation && response.status != 500) { + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + _dialogService.showDialog(description: response.body['message']); } - Redux.store.dispatch(checkMoney); - _navigatorService.pop(); - _navigatorService.push(ImageShowRoute, - arguments: ImageShowModel(check, message)); - } else if (!response.operation && response.status != 500) { - _dialogService.showDialog(description: response.body['message']); + } else { + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); } } catch (e) { - //Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); - Navigator.of(context, rootNavigator: true).pop(); + print(e); + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + } finally { + + //Navigator.of(context, rootNavigator: true).pop(); setState(() { isBusy = false; }); diff --git a/lib/views/qr_view/qr_view.dart b/lib/views/qr_view/qr_view.dart new file mode 100644 index 0000000..58d15b7 --- /dev/null +++ b/lib/views/qr_view/qr_view.dart @@ -0,0 +1,39 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; +import 'package:flutter/material.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + +class QrView extends StatefulWidget { + final ImageShowModel data; + + QrView(this.data); + + @override + _QrViewState createState() => _QrViewState(); +} + +class _QrViewState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( widget.data.title), + ), + body: Container( + child: Center( + child: QrImage( + data: widget.data.data, + version: QrVersions.auto, + size: 220.0, + ), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 02867b2..b332fb0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -310,6 +310,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.4.4" + qr: + dependency: transitive + description: + name: qr + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index db09be0..b4c19f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,6 +28,7 @@ dependencies: esys_flutter_share: ^1.0.2 auto_size_text: ^2.1.0 url_launcher: ^5.4.11 + qr_flutter: ^3.2.0 dev_dependencies: flutter_test: sdk: flutter