aman-kassa-flutter/lib/views/payment/payment_view.dart

403 lines
15 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:convert';
import 'package:aman_kassa_flutter/core/entity/Voucher.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/calc_model.dart';
import 'package:aman_kassa_flutter/core/models/check_image_modal.dart';
import 'package:aman_kassa_flutter/core/models/card_data.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/BankService.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';
import 'package:aman_kassa_flutter/redux/actions/calc_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart';
import 'package:aman_kassa_flutter/redux/actions/user_actions.dart';
import 'package:aman_kassa_flutter/redux/constants/operation_const.dart';
import 'package:aman_kassa_flutter/redux/constants/setting_const.dart';
import 'package:aman_kassa_flutter/redux/state/bank_state.dart';
import 'package:aman_kassa_flutter/redux/state/calc_state.dart';
import 'package:aman_kassa_flutter/redux/state/kassa_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/shared/app_colors.dart';
import 'package:aman_kassa_flutter/shared/ui_helpers.dart';
import 'package:aman_kassa_flutter/views/check/image_show_container.dart';
import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart';
import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart';
import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aman_kassa_flutter/views/payment/halyk_pos_service.dart';
import '../../core/models/aman_dao.dart';
import '../../core/models/card_data.dart';
import '../../core/models/card_data.dart';
class PaymentView extends StatefulWidget {
final PaymentModel model;
const PaymentView({Key? key, required this.model}) : super(key: key);
@override
_PaymentViewState createState() => _PaymentViewState();
}
class _PaymentViewState extends State<PaymentView> {
final GlobalKey<State> _keyLoader = new GlobalKey<State>();
final DataService _dataService = locator<DataService>();
final DialogService _dialogService = locator<DialogService>();
BankService _bankService = locator<BankService>();
final NavigatorService _navigatorService = locator<NavigatorService>();
late bool isBusy;
late bool isBankApiAccess;
@override
void initState() {
super.initState();
isBusy = false;
isBankApiAccess = false;
_bankInit();
}
_bankInit() async {
int version = await _bankService.version();
if (version >= _bankService.sdkVersion) {
setState(() {
isBankApiAccess = true;
});
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
if (!isBusy) Navigator.pop(context);
return new Future(() => false);
},
child: Scaffold(
appBar: AppBar(
brightness: Brightness.light,
backgroundColor: whiteColor,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
color: Colors.black87,
onPressed: () => Navigator.pop(context),
),
title: Text(
dataTitle(),
style: TextStyle(color: Colors.black87),
),
),
body: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
dataText(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black26,
fontSize: 15),
),
buildStoreConnector(),
verticalSpaceLarge,
_buildBodyContent(),
],
),
),
),
);
}
String dataTitle() =>
widget.model.operationType == OperationTypePay ? 'Оплата' : 'Возврат';
String dataText() =>
widget.model.operationType == OperationTypePay
? 'К оплате'
: 'К возврату';
StoreConnector buildStoreConnector() {
if (widget.model.mode == SettingModeCalc) {
return StoreConnector<AppState, CalcState>(
converter: (store) => store.state.calcState!,
builder: (_, vm) {
return Text('${totalCalc(vm.calcItems!)} тнг',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
fontSize: 35));
});
}
return StoreConnector<AppState, KassaState>(
converter: (store) => store.state.kassaState!,
builder: (_, vm) {
return Text('${totalKassa(vm.kassaItems!)} тнг',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
fontSize: 35));
});
}
Expanded _buildBodyContent() {
return Expanded(
child: Column(
children: <Widget>[
Container(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: BusyButton(
title: 'Оплатить картой',
onPressed: () {
pressPayment('card', null);
},
mainColor: primaryColor,
)),
horizontalSpaceSmall,
Expanded(
child: BusyButton(
title: 'Наличными',
onPressed: () {
pressPayment('cash', null);
},
mainColor: greenColor,
)),
],
),
),
verticalSpaceLarge,
_nfsButtonRender(),
verticalSpaceSmall,
Expanded(
child: Container(),
),
Container(
child: BusyButton(
title: 'Отмена',
onPressed: () {
Navigator.pop(context);
},
mainColor: redColor,
)),
],
),
);
}
Widget _nfsButtonRender() {
if (!isBankApiAccess || widget.model.operationType != OperationTypePay) {
return Container();
}
return StoreConnector<AppState, AppState>(
converter: (store) => store.state,
builder: (_, _state) {
BankState state = _state.bankState!;
double _total;
if (widget.model.mode == SettingModeCalc) {
String value = totalCalc(_state.calcState!.calcItems!);
_total = double.parse(value);
} else {
String value = totalKassa(_state.kassaState!.kassaItems!);
_total = double.parse(value);
}
if (state.password == null || state.login == null || state.password!.length < 1 || state.login!.length < 1) {
return Container();
}
return InkWell(
onTap: isBusy ? null : () async {
var today = new DateTime.now();
var yesterday = today.subtract(new Duration(days: 1));
if( Redux.store!.state.userState == null
|| Redux.store!.state.userState!.smena == null
|| Redux.store!.state.userState!.smena!.startedAt == null
|| yesterday.isAfter(Redux.store!.state.userState!.smena!.startedAt!)) {
_dialogService.showDialog(description: 'Текущая смена открыта более 24 ч. Необходимо закрыть смену и открыть ее заново.');
return;
}
setState(() {
isBusy = true;
});
try {
await Redux.store!.dispatch(changePinSkipFromSetting(true));
AmanDao<CardData> data = await paymentHalykPos(_total);
if (data.success == true) {
pressPayment('card', data.data);
} else {
_dialogService.showDialog(description: data.msg ?? '');
}
} finally {
await Redux.store!.dispatch(changePinSkipFromSetting(false));
setState(() {
isBusy = false;
});
}
},
splashColor: halykColor.withOpacity(0.4),
borderRadius: BorderRadius.circular(10.0),
highlightColor: halykColor.withOpacity(0.1),
child: Container(
width: ScreenUtil().setSp(100.0),
padding: const EdgeInsets.symmetric(vertical: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0)
),
child: Column(
children: [
Container(
width: ScreenUtil().setSp(80.0),
height: ScreenUtil().setSp(80.0),
margin: const EdgeInsets.only(bottom: 8.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(10.0),
image: DecorationImage(
image: AssetImage('assets/images/halykpos.png'), fit: BoxFit.fitWidth
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
),
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Icon(
// MdiIcons.nfc,
// color: halykColor,
// size: ScreenUtil().setSp(20.0),
// ),
// Text('Tap2Phone',style: TextStyle(fontSize: ScreenUtil().setSp(10.0), color: halykColor, fontWeight: FontWeight.bold ),),
// ],
// ),
],
),
),
);
}
);
}
pressPayment(String type, CardData? cardData) async {
setState(() {
isBusy = true;
});
Dialogs.showLoadingDialog(context, _keyLoader);
try {
AppState _state = Redux.store!.state;
String _token = _state.userState!.user!.token!;
String _tradeType = _state.settingState!.tradeType!;
String _mode = _state.settingState!.mode!;
if (_mode == SettingModeCalc) {
_tradeType = SettingTradeTypeGood;
}
List<ProductDao> kassaItems = _state.kassaState!.kassaItems!;
List<CalcModel> calcItems = _state.calcState!.calcItems!;
Response<dynamic>? response = await _dataService.sellOrReturn(
token: _token,
kassaItems: kassaItems,
paymentType: type,
operationType: widget.model.operationType,
tradeType: _tradeType,
calcItems: calcItems,
mode: _mode,
cardData: cardData
);
setState(() {
isBusy = false;
});
if (response != null) {
if (response.operation) {
String message = response.body['message'];
String check = response.body['check'];
var checkText = response.body['check_text'];
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);
Redux.store!.dispatch(openSmenaPseudo);
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
_navigatorService.pop();
_navigatorService.push(ImageShowRoute,
arguments: ImageShowModel(data: new CheckImageModal(
base64Data: check, textData: checkText != null ? jsonEncode(checkText) : null),
title: message,
url: url));
} else if (!response.operation && ![401, 402, 403, 412, 500].contains(response.status)) {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
_dialogService.showDialog(description: response.body['message']);
} else if (!response.operation && response.body['message'] != null) {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
_dialogService.showDialog(description: response.body['message']);
} else {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
}
} else {
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
}
} catch (e) {
print(e);
Navigator.of(_keyLoader.currentContext!, rootNavigator: true).pop();
} finally {
//Navigator.of(context, rootNavigator: true).pop();
setState(() {
isBusy = false;
});
}
}
String totalKassa(List<ProductDao> kassaItems) {
num total = 0.0;
kassaItems.forEach((element) {
total += element.total == null ? 0.0 : element.total.toDouble();
});
return total.toString();
}
String totalCalc(List<CalcModel> items) {
num total = 0.0;
items.forEach((element) {
if (element.operation == Calculations.MULTIPLY) {
double num1 = element.num1 == null ? 0.0 : double.parse(element.num1);
double num2 = element.num2 == null ? 0.0 : double.parse(element.num2!);
total += num1 * num2;
} else {
total += element.num1 == null ? 0.0 : double.parse(element.num1);
}
});
return total.toString();
}
}
class PaymentModel {
String operationType;
String mode;
Voucher? voucher;
CardData? cardData;
PaymentModel({required this.mode, required this.operationType, this.voucher, this.cardData});
}