diff --git a/lib/core/models/response/response_entity.dart b/lib/core/models/response/response_entity.dart index a66b048..7e6a11b 100644 --- a/lib/core/models/response/response_entity.dart +++ b/lib/core/models/response/response_entity.dart @@ -52,6 +52,7 @@ class ResponseOriginal { dynamic result; Map>? errors; String? message; + String? status; Map toJson() => _$ResponseOriginalToJson(this); diff --git a/lib/core/models/response/response_entity.g.dart b/lib/core/models/response/response_entity.g.dart index e1cbfdb..89ab707 100644 --- a/lib/core/models/response/response_entity.g.dart +++ b/lib/core/models/response/response_entity.g.dart @@ -39,7 +39,8 @@ ResponseOriginal _$ResponseOriginalFromJson(Map json) => (k, e) => MapEntry(k, (e as List).map((e) => e as String).toList()), ) - ..message = json['message'] as String?; + ..message = json['message'] as String? + ..status = json['status'] as String?; Map _$ResponseOriginalToJson(ResponseOriginal instance) => { @@ -51,4 +52,5 @@ Map _$ResponseOriginalToJson(ResponseOriginal instance) => 'result': instance.result, 'errors': instance.errors, 'message': instance.message, + 'status': instance.status, }; diff --git a/lib/core/services/buy_service.dart b/lib/core/services/buy_service.dart index 709dee9..9d4dfb9 100644 --- a/lib/core/services/buy_service.dart +++ b/lib/core/services/buy_service.dart @@ -59,4 +59,61 @@ class BuyService extends BaseService { } return list; } + + Future editItem({required int invoiceId, required int id, required double price, required double count}) async { + bool result = false; + try { + final Map requestBody = { + 'eacc_buy_invoice_item_id': id, + 'id': invoiceId, + 'price': price, + 'cnt': count + }; + log.i(requestBody); + + ResponseEntity response = await _api.postRequest('/general_purchases_edit_item', + requestBody: requestBody); + result = response.original.status == 'success'; + } catch (e, stack) { + log.e('getList', e, stack); + } + return result; + } + + Future deleteItem(int id) async { + bool result = false; + try { + final Map requestBody = { + 'id': id, + }; + log.i(requestBody); + + ResponseEntity response = await _api.postRequest('/general_purchases_delete_item', + requestBody: requestBody); + result = response.original.status == 'success'; + log.i(response.toJson()); + } catch (e, stack) { + log.e('getList', e, stack); + } + return result; + } + + Future addItem(int invoiceId, int goodId) async { + bool result = false; + try { + final Map requestBody = { + 'eacc_good_id': goodId, + 'id': invoiceId, + }; + log.i(requestBody); + + ResponseEntity response = await _api.postRequest('/general_purchases_add_item', + requestBody: requestBody); + result = response.original.status == 'success'; + log.i(response.toJson()); + } catch (e, stack) { + log.e('getList', e, stack); + } + return result; + } } \ No newline at end of file diff --git a/lib/views/work/tabs/buy/buy_edit.dart b/lib/views/work/tabs/buy/buy_edit.dart index b1a387d..c899a76 100644 --- a/lib/views/work/tabs/buy/buy_edit.dart +++ b/lib/views/work/tabs/buy/buy_edit.dart @@ -1,14 +1,21 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:satu/core/models/but_item/buy_item_response.dart'; +import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/views/work/tabs/buy/component/product_buy_tile.dart'; +import '../../../../core/entity/goods_entity.dart'; import '../../../../core/models/buy_invoice/buy_invoice_response.dart'; import '../../../../core/services/buy_service.dart'; +import '../../../../core/services/dictionary_service.dart'; import '../../../../core/services/navigator_service.dart'; import '../../../../core/utils/locator.dart'; +import '../../../../routes/route_names.dart'; import '../../../../shared/app_colors.dart'; +import '../../../../shared/ui_helpers.dart'; import '../../../../widgets/bar/products_app_bar.dart'; class BuyEditView extends StatefulWidget { @@ -22,18 +29,27 @@ class BuyEditView extends StatefulWidget { class _BuyEditViewState extends State { final BuyService _service = locator(); + final DialogService _dialogService = locator(); static const _pageSize = 20; final PagingController _pagingController = PagingController(firstPageKey: 1); + bool editable = false; + @override void initState() { + log('initState'); _pagingController.addPageRequestListener((pageKey) { _fetchData(pageKey, _pageSize); }); + log('refBuyInvoiceStatusId: ${widget.invoice.refBuyInvoiceStatusId}'); + if(widget.invoice.refBuyInvoiceStatusId == 1){ + editable = true; + } + super.initState(); } @@ -72,7 +88,12 @@ class _BuyEditViewState extends State { price: item.price, count: item.cnt, categoryName: 'Овощи', - isOdd: true, + editable: editable, + invoiceId: widget.invoice.id, + id: item.id, + editData: (id, price, count) { + _editData(id, price, count); + }, ); }, ), @@ -80,6 +101,83 @@ class _BuyEditViewState extends State { ) ], ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: editable ? floatingActionButtonRender() : null, + ); + } + + /// render floating buttons + Widget floatingActionButtonRender() { + return Padding( + padding: EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Visibility( + visible: false, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: FloatingActionButton( + mini: true, + elevation: 2, + backgroundColor: successColor, + onPressed: () {}, + child: Icon( + Icons.check, + color: whiteColor, + size: 35, + ), + ), + )), + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + FloatingActionButton( + elevation: 2, + mini: true, + onPressed: () async { + final Good? good = await locator() + .push(addProductViewRoute) as Good?; + if (good != null && good.id != null) { + bool result = + await _service.addItem(widget.invoice.id, good.id!); + if (result) { + _pagingController.refresh(); + } else { + _dialogService.showDialog( + description: + 'Товара отсутсвует в остатке или ранее не' + ' использователся в системе', + ); + } + } + }, + child: Icon( + Icons.add_rounded, + size: 40, + color: whiteColor, + ), + ), + verticalSpaceSmall, + FloatingActionButton( + elevation: 2, + mini: true, + onPressed: () async { + final NavigatorService _nav = locator(); + final dynamic result = await _nav.push(addByBarcodeViewRoute); + if (result != null) { + final List goods = await locator() + .getGoodsByNameOrEan(result as String); + if (goods.isNotEmpty) {} + } + }, + child: Icon(Icons.qr_code_rounded, size: 30, color: whiteColor), + ), + ], + ) + ], + ), ); } @@ -95,4 +193,14 @@ class _BuyEditViewState extends State { } } + void _editData(int id, double price, double count) { + final List oldList = + _pagingController.value.itemList ?? []; + oldList..firstWhere((element) => element.id == id).price = price + ..firstWhere((element) => element.id == id).cnt = count; + setState(() { + _pagingController.itemList = oldList; + }); + } + } diff --git a/lib/views/work/tabs/buy/buy_view.dart b/lib/views/work/tabs/buy/buy_view.dart index f7ec568..fafc00b 100644 --- a/lib/views/work/tabs/buy/buy_view.dart +++ b/lib/views/work/tabs/buy/buy_view.dart @@ -95,7 +95,7 @@ class _BuyViewState extends State { height: 5.0, ), Text( - 'Статус: ${item.eaccContragentId.toString()}', + 'Статус: ${item.refBuyInvoiceStatusId.toString()}', style: textGray11Style, ), ], diff --git a/lib/views/work/tabs/buy/component/product_buy_tile.dart b/lib/views/work/tabs/buy/component/product_buy_tile.dart index 815923c..512f95e 100644 --- a/lib/views/work/tabs/buy/component/product_buy_tile.dart +++ b/lib/views/work/tabs/buy/component/product_buy_tile.dart @@ -1,9 +1,9 @@ - import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:satu/core/models/dialog_models.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/redux/store.dart'; +import 'package:satu/core/services/buy_service.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/utils_parse.dart'; @@ -12,39 +12,38 @@ import 'package:satu/shared/shared_styles.dart'; import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart'; import 'package:satu/widgets/ui/product_title_widget.dart'; - class ProductBuyTile extends StatefulWidget { - const ProductBuyTile( - {Key? key, - this.name = '', - this.ean, - this.categoryName, - this.price, - this.count, - this.isOdd, - this.transactionId}) - : super(key: key); - + const ProductBuyTile({ + required this.invoiceId, + required this.id, + Key? key, + this.name = '', + this.ean, + this.categoryName, + this.price, + this.count, + this.editable = false, + this.editData, + }) : super(key: key); + final int id; + final int invoiceId; final String name; final String? ean; final String? categoryName; final num? price; final num? count; - final bool? isOdd; - final int? transactionId; + final bool editable; @override _ProductBuyTileState createState() => _ProductBuyTileState(); + + final void Function(int id, double price, double count)? editData; } class _ProductBuyTileState extends State { + final BuyService _service = locator(); final DialogService _dialogService = locator(); - void _onItemTapped(BuildContext context) { - Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => const AddByBarcodeView())); - } - @override Widget build(BuildContext context) { return Dismissible( @@ -59,31 +58,36 @@ class _ProductBuyTileState extends State { ), ), ), - direction: DismissDirection.endToStart, + direction: + widget.editable ? DismissDirection.endToStart : DismissDirection.none, confirmDismiss: (DismissDirection direction) async { final DialogResponse response = - await _dialogService.showConfirmationDialog( - title: 'Внимание', - description: 'Удалить из списка товар ' - '"${widget.name}"' - ' - ${widget.count} ед. ?', - confirmationTitle: 'Удалить', - cancelTitle: 'Отмена'); + await _dialogService.showConfirmationDialog( + title: 'Внимание', + description: 'Удалить из списка товар ' + '"${widget.name}"' + ' - ${widget.count} ед. ?', + confirmationTitle: 'Удалить', + cancelTitle: 'Отмена'); - return response.confirmed; - }, - onDismissed: (direction) { - Redux.store! - .dispatch(removeSellItem(transactionId: widget.transactionId!)); + if (response.confirmed) { + bool result = await _service.deleteItem(widget.id); + return result; + } + + return false; }, + onDismissed: (direction) {}, key: Key(widget.name), child: ListTile( key: Key(widget.name), - onTap: () { - editProductModal(); - }, + onTap: widget.editable + ? () { + editProductModal(); + } + : null, contentPadding: - const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0), + const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0), title: Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -113,79 +117,13 @@ class _ProductBuyTileState extends State { Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(5), - child: InkWell( - onTap: () { - Redux.store!.dispatch(counterOrEditSellItem( - transactionId: widget.transactionId!, - counter: 1.0)); - }, - child: Container( - decoration: BoxDecoration( - //color: whiteColor, - borderRadius: BorderRadius.circular( - ScreenUtil().radius(5), - ), - border: Border.all(color: successColor), - ), - child: const Icon( - Icons.add, - color: successColor, - size: 20, - ), - ), - ), - ), - Container( - width: 45, - margin: const EdgeInsets.symmetric(horizontal: 5.0), - decoration: BoxDecoration( - color: whiteColor, - borderRadius: BorderRadius.circular(5), - boxShadow: [cardShadowBox]), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 6.0), - child: SizedBox( - width: 45, - child: Text( - '${widget.count} шт', - style: const TextStyle( - fontSize: 10, color: placeholderColor), - textAlign: TextAlign.center, - ), - ), - ), - ), - Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(5), - child: InkWell( - onTap: () { - if (widget.count! > 1.0) { - Redux.store!.dispatch(counterOrEditSellItem( - transactionId: widget.transactionId!, - counter: -1.0)); - } - }, - child: Container( - decoration: BoxDecoration( - //color: whiteColor, - borderRadius: BorderRadius.circular(5), - border: Border.all( - width: 1.0.sp, - color: widget.count! <= 1.0 - ? disableColor - : dangerColor)), - child: Icon( - Icons.remove, - color: widget.count! <= 1.0 - ? disableColor - : dangerColor, - size: 20, - ), - ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Text( + '${widget.count} шт', + style: const TextStyle( + fontSize: 12, color: placeholderColor), + textAlign: TextAlign.center, ), ), ], @@ -195,25 +133,29 @@ class _ProductBuyTileState extends State { ), ], ), - tileColor: !widget.isOdd! ? whiteColor : whiteColor, + tileColor: whiteColor, ), ); } Future editProductModal() async { final DialogResponse response = - await _dialogService.showConfirmationDialogInput( - title: widget.name, - requestCount: formatDecimal(widget.count!.toDouble()), - requestPrice: formatDecimal(widget.price!.toDouble())); + await _dialogService.showConfirmationDialogInput( + title: widget.name, + requestCount: formatDecimal(widget.count!.toDouble()), + requestPrice: formatDecimal(widget.price!.toDouble())); if (response.confirmed) { if (isNumeric(response.responsePrice) && isNumeric(response.responseCount)) { - Redux.store!.dispatch(counterOrEditSellItem( - transactionId: widget.transactionId!, - counter: double.parse(response.responseCount!), - price: double.parse(response.responsePrice!), - )); + bool result = await _service.editItem( + invoiceId: widget.invoiceId, + id: widget.id, + price: double.parse(response.responsePrice!), + count: double.parse(response.responseCount!)); + if (result && widget.editData != null) { + widget.editData!(widget.id, double.parse(response.responsePrice!), + double.parse(response.responseCount!)); + } } else { _dialogService.showDialog(description: 'Не верный формат'); }