diff --git a/lib/core/models/but_item/buy_item_response.dart b/lib/core/models/but_item/buy_item_response.dart new file mode 100644 index 0000000..f57a9c9 --- /dev/null +++ b/lib/core/models/but_item/buy_item_response.dart @@ -0,0 +1,41 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'buy_item_response.g.dart'; + +@JsonSerializable() +class BuyItemResponse { + BuyItemResponse({ + required this.id, + required this.eaccBuyInvoiceId, + required this.eaccGoodId, + required this.cnt, + required this.price, + required this.createdAt, + required this.updatedAt, + required this.unitPrice, + this.deletedAt, + this.refOkeiId, + }); + + int id; + @JsonKey(name: 'eacc_buy_invoice_id') + int eaccBuyInvoiceId; + @JsonKey(name: 'eacc_good_id') + int eaccGoodId; + @JsonKey(name: 'ref_okei_id') + int? refOkeiId; + double cnt; + double price; + @JsonKey(name: 'created_at') + DateTime createdAt; + @JsonKey(name: 'updated_at') + DateTime updatedAt; + @JsonKey(name: 'deleted_at') + DateTime? deletedAt; + @JsonKey(name: 'unit_price') + double unitPrice; + +factory BuyItemResponse.fromJson(Map json) => _$BuyItemResponseFromJson(json); + +Map toJson() => _$BuyItemResponseToJson(this); +} diff --git a/lib/core/models/but_item/buy_item_response.g.dart b/lib/core/models/but_item/buy_item_response.g.dart new file mode 100644 index 0000000..fc6f221 --- /dev/null +++ b/lib/core/models/but_item/buy_item_response.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'buy_item_response.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BuyItemResponse _$BuyItemResponseFromJson(Map json) => + BuyItemResponse( + id: json['id'] as int, + eaccBuyInvoiceId: json['eacc_buy_invoice_id'] as int, + eaccGoodId: json['eacc_good_id'] as int, + cnt: (json['cnt'] as num).toDouble(), + price: (json['price'] as num).toDouble(), + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + unitPrice: (json['unit_price'] as num).toDouble(), + deletedAt: json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + refOkeiId: json['ref_okei_id'] as int?, + ); + +Map _$BuyItemResponseToJson(BuyItemResponse instance) => + { + 'id': instance.id, + 'eacc_buy_invoice_id': instance.eaccBuyInvoiceId, + 'eacc_good_id': instance.eaccGoodId, + 'ref_okei_id': instance.refOkeiId, + 'cnt': instance.cnt, + 'price': instance.price, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + 'unit_price': instance.unitPrice, + }; diff --git a/lib/core/models/buy_invoice/buy_invoice_response.dart b/lib/core/models/buy_invoice/buy_invoice_response.dart new file mode 100644 index 0000000..8e0dfde --- /dev/null +++ b/lib/core/models/buy_invoice/buy_invoice_response.dart @@ -0,0 +1,50 @@ +import 'package:json_annotation/json_annotation.dart'; +// "eacc_contract_id": null, +// "file_id": null, +// "invoice": null, +// "invoice_check": null, +// "cruser_id": 10, +// "invoice_doc_date": null, +// "invoice_number": null, +// "returned_id": null, +// "returned_by_id": null, +// not usable fields + +part 'buy_invoice_response.g.dart'; +@JsonSerializable() +class BuyInvoiceResponse { + BuyInvoiceResponse({ + required this.id, + required this.appCompanyId, + required this.refBuyInvoiceStatusId, + required this.invoiceDate, + required this.docNumber, + required this.eaccContragentId, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.summ, +}); + int id; + double? summ; + @JsonKey(name: 'app_company_id') + int appCompanyId; + @JsonKey(name: 'ref_buy_invoice_status_id') + int refBuyInvoiceStatusId; + @JsonKey(name: 'invoice_date') + DateTime invoiceDate; + @JsonKey(name: 'doc_number') + int docNumber; + @JsonKey(name: 'eacc_contragent_id') + int eaccContragentId; + @JsonKey(name: 'created_at') + DateTime createdAt; + @JsonKey(name: 'updated_at') + DateTime updatedAt; + @JsonKey(name: 'deleted_at') + DateTime? deletedAt; + +factory BuyInvoiceResponse.fromJson(Map json) => _$BuyInvoiceResponseFromJson(json); + +Map toJson() => _$BuyInvoiceResponseToJson(this); +} \ No newline at end of file diff --git a/lib/core/models/buy_invoice/buy_invoice_response.g.dart b/lib/core/models/buy_invoice/buy_invoice_response.g.dart new file mode 100644 index 0000000..5d1ed11 --- /dev/null +++ b/lib/core/models/buy_invoice/buy_invoice_response.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'buy_invoice_response.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BuyInvoiceResponse _$BuyInvoiceResponseFromJson(Map json) => + BuyInvoiceResponse( + id: json['id'] as int, + appCompanyId: json['app_company_id'] as int, + refBuyInvoiceStatusId: json['ref_buy_invoice_status_id'] as int, + invoiceDate: DateTime.parse(json['invoice_date'] as String), + docNumber: json['doc_number'] as int, + eaccContragentId: json['eacc_contragent_id'] as int, + createdAt: DateTime.parse(json['created_at'] as String), + updatedAt: DateTime.parse(json['updated_at'] as String), + deletedAt: json['deleted_at'] == null + ? null + : DateTime.parse(json['deleted_at'] as String), + summ: (json['summ'] as num?)?.toDouble(), + ); + +Map _$BuyInvoiceResponseToJson(BuyInvoiceResponse instance) => + { + 'id': instance.id, + 'summ': instance.summ, + 'app_company_id': instance.appCompanyId, + 'ref_buy_invoice_status_id': instance.refBuyInvoiceStatusId, + 'invoice_date': instance.invoiceDate.toIso8601String(), + 'doc_number': instance.docNumber, + 'eacc_contragent_id': instance.eaccContragentId, + 'created_at': instance.createdAt.toIso8601String(), + 'updated_at': instance.updatedAt.toIso8601String(), + 'deleted_at': instance.deletedAt?.toIso8601String(), + }; diff --git a/lib/core/models/response/response_entity.dart b/lib/core/models/response/response_entity.dart index fa6f748..a66b048 100644 --- a/lib/core/models/response/response_entity.dart +++ b/lib/core/models/response/response_entity.dart @@ -48,6 +48,7 @@ class ResponseOriginal { int? page; int? perpage; List? data; + List? items; dynamic result; Map>? errors; String? message; diff --git a/lib/core/models/response/response_entity.g.dart b/lib/core/models/response/response_entity.g.dart index a14b9eb..e1cbfdb 100644 --- a/lib/core/models/response/response_entity.g.dart +++ b/lib/core/models/response/response_entity.g.dart @@ -33,6 +33,7 @@ ResponseOriginal _$ResponseOriginalFromJson(Map json) => ..page = json['page'] as int? ..perpage = json['perpage'] as int? ..data = json['data'] as List? + ..items = json['items'] as List? ..result = json['result'] ..errors = (json['errors'] as Map?)?.map( (k, e) => @@ -46,6 +47,7 @@ Map _$ResponseOriginalToJson(ResponseOriginal instance) => 'page': instance.page, 'perpage': instance.perpage, 'data': instance.data, + 'items': instance.items, 'result': instance.result, 'errors': instance.errors, 'message': instance.message, diff --git a/lib/core/services/buy_service.dart b/lib/core/services/buy_service.dart new file mode 100644 index 0000000..709dee9 --- /dev/null +++ b/lib/core/services/buy_service.dart @@ -0,0 +1,62 @@ +import 'package:satu/core/base/base_service.dart'; +import 'package:satu/core/models/but_item/buy_item_response.dart'; +import 'package:satu/core/services/api_service.dart'; +import 'package:satu/core/utils/locator.dart'; + +import '../models/buy_invoice/buy_invoice_response.dart'; +import '../models/response/response_entity.dart'; + +class BuyService extends BaseService { + final ApiService _api = locator(); + Future> getList( + {required int page, required int perpage, dynamic filter}) async { + List list = []; + try { + final Map requestBody = { + 'page': page, + 'perpage': perpage, + }; + + ResponseEntity categories = await _api.postRequest('/general_purchases_get', + requestBody: requestBody); + if (categories.original.data != null && + categories.original.data!.isNotEmpty) { + for (final dynamic map in categories.original.data!) { + final BuyInvoiceResponse item = + BuyInvoiceResponse.fromJson(map); + list.add(item); + } + } + } catch (e, stack) { + log.e('getList', e, stack); + } + return list; + } + + Future> getItemList(int id, + {required int page, required int perpage, dynamic filter}) async { + List list = []; + try { + final Map requestBody = { + 'page': page, + 'perpage': perpage, + 'id': id + }; + log.i(requestBody); + + ResponseEntity categories = await _api.postRequest('/general_purchases_get_items', + requestBody: requestBody); + if (categories.original.items != null && + categories.original.items!.isNotEmpty) { + for (final dynamic map in categories.original.items!) { + final BuyItemResponse item = + BuyItemResponse.fromJson(map); + list.add(item); + } + } + } catch (e, stack) { + log.e('getList', e, stack); + } + return list; + } +} \ No newline at end of file diff --git a/lib/core/services/dictionary_service.dart b/lib/core/services/dictionary_service.dart index f088b7c..2da60a0 100644 --- a/lib/core/services/dictionary_service.dart +++ b/lib/core/services/dictionary_service.dart @@ -198,6 +198,7 @@ class DictionaryService extends BaseService { Future saveGood(GoodResponseEntity good) async { ResponseEntity? status; + log.i(good.toJson()); if (good.id != null) { status = await _api.dictionarySave('/goods_goods_edit', good.toJson()); } else { diff --git a/lib/core/services/inventarization_service.dart b/lib/core/services/inventarization_service.dart index 3b67525..d557346 100644 --- a/lib/core/services/inventarization_service.dart +++ b/lib/core/services/inventarization_service.dart @@ -77,6 +77,25 @@ class InventarizationService extends BaseService { return result ; } + Future deleteFromList(int inventoryId, int inventory_item_id) async { + bool result = false; + try { + final Map requestBody = { + 'page': 1, + 'perpage': 1, + 'id': inventoryId, + 'inventory_item_id' : inventory_item_id + }; + ResponseEntity response = await _api.postRequest( + '/goods_inventory_delete_item', + requestBody: requestBody); + result = response.original.result != null; + } catch (e, stack) { + log.e('getList', e, stack); + } + return result ; + } + Future setCountToItem(int inventoryId, int inventoryItemId, double value) async { bool result = false; try { diff --git a/lib/core/services/data_service.dart b/lib/core/services/sell_service.dart similarity index 99% rename from lib/core/services/data_service.dart rename to lib/core/services/sell_service.dart index 0079628..92aea0b 100644 --- a/lib/core/services/data_service.dart +++ b/lib/core/services/sell_service.dart @@ -20,7 +20,7 @@ import 'api_service.dart'; import 'db_service.dart'; import 'dialog_service.dart'; -class DataService extends BaseService { +class SellService extends BaseService { final ApiService _api = locator(); final DbService _db = locator(); diff --git a/lib/core/utils/locator.dart b/lib/core/utils/locator.dart index 481e384..e2c7c88 100644 --- a/lib/core/utils/locator.dart +++ b/lib/core/utils/locator.dart @@ -3,7 +3,8 @@ import 'package:get_it/get_it.dart'; import 'package:logger/logger.dart'; import 'package:satu/core/services/api_service.dart'; -import 'package:satu/core/services/data_service.dart'; +import 'package:satu/core/services/buy_service.dart'; +import 'package:satu/core/services/sell_service.dart'; import 'package:satu/core/services/db_service.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dictionary_service.dart'; @@ -30,7 +31,9 @@ class LocatorInjector { // depencies _log.d('Initializing DataService Service'); - locator.registerLazySingleton(() => DataService()); + locator.registerLazySingleton(() => SellService()); + _log.d('Initializing BuyService Service'); + locator.registerLazySingleton(() => BuyService()); _log.d('Initializing DictionaryService Service'); locator.registerLazySingleton(() => DictionaryService()); _log.d('Initializing InventarizationService Service'); diff --git a/lib/routes/route_names.dart b/lib/routes/route_names.dart index 9a2226a..bb28804 100644 --- a/lib/routes/route_names.dart +++ b/lib/routes/route_names.dart @@ -23,6 +23,9 @@ const String contragentEditRoute = 'contragentEditRoute'; // inventarization const String inventarizationEditRoute = 'inventarizationEditRoute'; +//buy +const String buyEditRoute = 'buyEditRoute'; + // setting - ble printer const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView'; const String settingPrinterBluetoothSelectViewRoute = diff --git a/lib/routes/router.dart b/lib/routes/router.dart index 3980f42..c94b6bf 100644 --- a/lib/routes/router.dart +++ b/lib/routes/router.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:satu/core/models/buy_invoice/buy_invoice_response.dart'; import 'package:satu/core/models/dictionary/category/category_response.dart'; import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; import 'package:satu/core/models/dictionary/good/good_response_entity.dart'; @@ -13,6 +14,7 @@ import 'package:satu/views/settings/printer_bluetooth/printer_encoding_select.da import 'package:satu/views/settings/printer_bluetooth/printer_paper_size_select.dart'; import 'package:satu/views/settings/printer_bluetooth/printer_select.dart'; import 'package:satu/views/settings/printer_bluetooth/printer_view.dart'; +import 'package:satu/views/work/tabs/buy/buy_edit.dart'; import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart'; import 'package:satu/views/work/views/add_product/add_product_view.dart'; import 'package:satu/views/work/views/contragent/select_contragent_view.dart'; @@ -127,6 +129,15 @@ Route generateRoute(RouteSettings settings) { item: inventarizationResponse, ), ); + case buyEditRoute: + final BuyInvoiceResponse invoice = settings.arguments! as BuyInvoiceResponse; + return _getPageRoute( + routeName: settings.name, + viewToShow: BuyEditView( + invoice: invoice, + ), + ); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/shared/shared_styles.dart b/lib/shared/shared_styles.dart index fdc3599..7c06f74 100644 --- a/lib/shared/shared_styles.dart +++ b/lib/shared/shared_styles.dart @@ -34,6 +34,9 @@ const TextStyle dropDownTradeTypeTextStyle = const TextStyle textGray11Style = TextStyle(color: placeholderColor, fontWeight: FontWeight.w400, fontSize: 11); +const TextStyle textBlack12Style = +TextStyle(color: textColor, fontWeight: FontWeight.w400, fontSize: 12); + // Box Shadow BoxShadow buttonShadowBox = const BoxShadow(blurRadius: 10, color: shadowColor, offset: Offset(0, 4)); diff --git a/lib/views/dictionaries/goods/goods_edit.dart b/lib/views/dictionaries/goods/goods_edit.dart index da0d5d0..b9ab887 100644 --- a/lib/views/dictionaries/goods/goods_edit.dart +++ b/lib/views/dictionaries/goods/goods_edit.dart @@ -92,6 +92,7 @@ class _GoodEditState extends State { good.basePrice = parseNumeric(_controllerBasePrice.text); good.ean13 = _controllerEan.text; good.description = _controllerDescription.text; + good.categoryId = parentCategoryId; String? message = await _dictionaryService.saveGood(good); if (message != null) { _dialogService.showDialog(description: message); diff --git a/lib/views/inventarization/view/inventarization_edit_view.dart b/lib/views/inventarization/view/inventarization_edit_view.dart index 18e4d62..a8617a0 100644 --- a/lib/views/inventarization/view/inventarization_edit_view.dart +++ b/lib/views/inventarization/view/inventarization_edit_view.dart @@ -48,6 +48,7 @@ class _InventarizationEditViewState extends State { }); super.initState(); } + @override void dispose() { _pagingController.dispose(); @@ -122,7 +123,7 @@ class _InventarizationEditViewState extends State { ean: item.ean13, isOdd: index % 2 == 0, refresh: () { - _refreshData(_pageCurrent, _pageSize); + _pagingController.refresh(); }, ); }, @@ -145,7 +146,7 @@ class _InventarizationEditViewState extends State { crossAxisAlignment: CrossAxisAlignment.end, children: [ Visibility( - visible: true, + visible: false, child: Padding( padding: const EdgeInsets.all(8.0), child: FloatingActionButton( @@ -176,7 +177,10 @@ class _InventarizationEditViewState extends State { _pagingController.refresh(); } else { _dialogService.showDialog( - description: 'Товара отсутсвует в остатке'); + description: + 'Товара отсутсвует в остатке или ранее не' + ' использователся в системе', + ); } } }, @@ -196,9 +200,7 @@ class _InventarizationEditViewState extends State { if (result != null) { final List goods = await locator() .getGoodsByNameOrEan(result as String); - if (goods.isNotEmpty) { - - } + if (goods.isNotEmpty) {} } }, child: Icon(Icons.qr_code_rounded, size: 30, color: whiteColor), @@ -228,14 +230,13 @@ class _InventarizationEditViewState extends State { Future _refreshData(int pageKey, int perPage) async { print('${pageKey} - ${perPage}'); final List newItems = - await _service.getGoodByInventarizationId( - page: pageKey, perpage: perPage, id: widget.item.id); - final List oldList = _pagingController.value.itemList ?? []; - oldList.setAll((pageKey - 1) * perPage , newItems); + await _service.getGoodByInventarizationId( + page: pageKey, perpage: perPage, id: widget.item.id); + final List oldList = + _pagingController.value.itemList ?? []; + oldList.setAll((pageKey - 1) * perPage, newItems); setState(() { _pagingController.itemList = oldList; }); } - - } diff --git a/lib/views/inventarization/view/inventarization_view.dart b/lib/views/inventarization/view/inventarization_view.dart index 7e0b391..1667333 100644 --- a/lib/views/inventarization/view/inventarization_view.dart +++ b/lib/views/inventarization/view/inventarization_view.dart @@ -41,6 +41,12 @@ class _InventarizationViewState extends State { super.initState(); } + @override + void dispose() { + _pagingController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/views/inventarization/widget/good_inventarization_list_item.dart b/lib/views/inventarization/widget/good_inventarization_list_item.dart index 24af91c..1b2e954 100644 --- a/lib/views/inventarization/widget/good_inventarization_list_item.dart +++ b/lib/views/inventarization/widget/good_inventarization_list_item.dart @@ -72,10 +72,15 @@ class _GoodInventarizationListItemState ' - ${widget.count} ед. ?', confirmationTitle: 'Удалить', cancelTitle: 'Отмена'); - - return response.confirmed; + if (response.confirmed) { + bool result = await _service.deleteFromList(widget.inventoryId,widget.inventoryItemId); + return result; + } + return false; + }, + onDismissed: (DismissDirection direction) { + widget.refresh(); }, - onDismissed: (direction) {}, key: widget.key!, child: ListTile( key: widget.key!, diff --git a/lib/views/work/tabs/buy/buy_edit.dart b/lib/views/work/tabs/buy/buy_edit.dart new file mode 100644 index 0000000..b1a387d --- /dev/null +++ b/lib/views/work/tabs/buy/buy_edit.dart @@ -0,0 +1,98 @@ +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/views/work/tabs/buy/component/product_buy_tile.dart'; + + +import '../../../../core/models/buy_invoice/buy_invoice_response.dart'; +import '../../../../core/services/buy_service.dart'; +import '../../../../core/services/navigator_service.dart'; +import '../../../../core/utils/locator.dart'; +import '../../../../shared/app_colors.dart'; +import '../../../../widgets/bar/products_app_bar.dart'; + +class BuyEditView extends StatefulWidget { + const BuyEditView({required this.invoice, Key? key}) : super(key: key); + + final BuyInvoiceResponse invoice; + + @override + State createState() => _BuyEditViewState(); +} + +class _BuyEditViewState extends State { + final BuyService _service = locator(); + + static const _pageSize = 20; + + final PagingController _pagingController = + PagingController(firstPageKey: 1); + + + @override + void initState() { + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize); + }); + super.initState(); + } + + @override + void dispose() { + + _pagingController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const ProductsAppBar( + title: 'Покупка', + ), + body: Column( + children: [ + Expanded( + child: PagedListView.separated( + physics: const BouncingScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return const Divider( + height: 1.0, + color: disableColor, + ); + }, + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (BuildContext context, BuyItemResponse item, + int index) { + return ProductBuyTile( + key: ValueKey(item.id), + ean: '1234567890123', + name: 'Картофель', + price: item.price, + count: item.cnt, + categoryName: 'Овощи', + isOdd: true, + ); + }, + ), + ), + ) + ], + ), + ); + } + + Future _fetchData(int pageKey, int perPage) async { + final List newItems = await _service + .getItemList(widget.invoice.id, page: pageKey, perpage: perPage); + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage(newItems, nextPageKey); + } + } + +} diff --git a/lib/views/work/tabs/buy/buy_view.dart b/lib/views/work/tabs/buy/buy_view.dart new file mode 100644 index 0000000..f7ec568 --- /dev/null +++ b/lib/views/work/tabs/buy/buy_view.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; +import 'package:intl/intl.dart'; +import 'package:satu/core/services/buy_service.dart'; +import 'package:satu/core/utils/utils_parse.dart'; + +import '../../../../core/models/buy_invoice/buy_invoice_response.dart'; +import '../../../../core/services/navigator_service.dart'; +import '../../../../core/utils/locator.dart'; +import '../../../../routes/route_names.dart'; +import '../../../../shared/app_colors.dart'; +import '../../../../shared/shared_styles.dart'; +import '../../../../shared/ui_helpers.dart'; +import '../../../../widgets/bar/products_app_bar.dart'; +import '../../../dictionaries/component/dictionary_list_tile.dart'; +import '../../../inventarization/widget/inventarization_list_tile.dart'; + +class BuyView extends StatefulWidget { + @override + State createState() => _BuyViewState(); +} + +class _BuyViewState extends State { + + + final BuyService _service = locator(); + final NavigatorService _navigatorService = locator(); + + static const _pageSize = 20; + + final PagingController _pagingController = + PagingController(firstPageKey: 1); + + final DateFormat formatterDay = DateFormat('dd.MM.yyyy'); + + @override + void initState() { + _pagingController.addPageRequestListener((pageKey) { + _fetchData(pageKey, _pageSize); + }); + super.initState(); + } + + @override + void dispose() { + + _pagingController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: const ProductsAppBar( + title: 'Накладные покупок', + drawerShow: true, + ), + body: Column( + children: [ + Expanded( + child: PagedListView.separated( + physics: const BouncingScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return const Divider( + height: 1.0, + color: disableColor, + ); + }, + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (BuildContext context, BuyInvoiceResponse item, + int index) { + return DictionaryTile( + key: Key('category_${item.id}'), + onPress: () async { + final dynamic result = await _navigatorService + .push(buyEditRoute, arguments: item); + if (result != null && true == (result as bool)) { + _pagingController.refresh(); + } + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${item.eaccContragentId.toString()}', + style: textBlack12Style, + ), + SizedBox( + height: 5.0, + ), + Text( + 'Статус: ${item.eaccContragentId.toString()}', + style: textGray11Style, + ), + ], + )), + Expanded( + flex: 2, + child: Text( + '${formatterDay.format(item.invoiceDate)}', + style: textBlack12Style, + ), + ), + Expanded( + flex: 1, + child: Column( + children: [ + Text( + '${formatDecimal(item.summ ?? 0)} т.', + style: textGray11Style, + ), + ], + ), + ), + ], + ), + ); + }, + ), + ), + ) + ], + ), + ); + } + + Future _fetchData(int pageKey, int perPage) async { + final List newItems = await _service + .getList(page: pageKey, perpage: perPage); + final isLastPage = newItems.length < _pageSize; + if (isLastPage) { + _pagingController.appendLastPage(newItems); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage(newItems, nextPageKey); + } + } +} diff --git a/lib/views/work/tabs/buy/component/product_buy_tile.dart b/lib/views/work/tabs/buy/component/product_buy_tile.dart new file mode 100644 index 0000000..815923c --- /dev/null +++ b/lib/views/work/tabs/buy/component/product_buy_tile.dart @@ -0,0 +1,222 @@ + +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/dialog_service.dart'; +import 'package:satu/core/utils/locator.dart'; +import 'package:satu/core/utils/utils_parse.dart'; +import 'package:satu/shared/app_colors.dart'; +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); + + final String name; + final String? ean; + final String? categoryName; + final num? price; + final num? count; + final bool? isOdd; + final int? transactionId; + + @override + _ProductBuyTileState createState() => _ProductBuyTileState(); +} + +class _ProductBuyTileState extends State { + 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( + background: Container( + alignment: AlignmentDirectional.centerEnd, + color: dangerColor, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Text( + 'Удалить', + style: TextStyle(color: whiteColor, fontWeight: FontWeight.w500), + ), + ), + ), + direction: DismissDirection.endToStart, + confirmDismiss: (DismissDirection direction) async { + final DialogResponse response = + await _dialogService.showConfirmationDialog( + title: 'Внимание', + description: 'Удалить из списка товар ' + '"${widget.name}"' + ' - ${widget.count} ед. ?', + confirmationTitle: 'Удалить', + cancelTitle: 'Отмена'); + + return response.confirmed; + }, + onDismissed: (direction) { + Redux.store! + .dispatch(removeSellItem(transactionId: widget.transactionId!)); + }, + key: Key(widget.name), + child: ListTile( + key: Key(widget.name), + onTap: () { + editProductModal(); + }, + contentPadding: + const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0), + title: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: ProductTitleWidget( + name: widget.name, + ean: widget.ean, + categoryName: widget.categoryName, + ), + ), + SizedBox( + width: 100, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '${widget.price} ₸', + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: textColor), + ), + ), + 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, + ), + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + tileColor: !widget.isOdd! ? whiteColor : whiteColor, + ), + ); + } + + Future editProductModal() async { + final DialogResponse response = + 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!), + )); + } else { + _dialogService.showDialog(description: 'Не верный формат'); + } + } + } +} diff --git a/lib/views/work/tabs/buy_view.dart b/lib/views/work/tabs/buy_view.dart deleted file mode 100644 index c5e8902..0000000 --- a/lib/views/work/tabs/buy_view.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../widgets/bar/products_app_bar.dart'; - -class BuyView extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: ProductsAppBar(title: 'Покупка',), - body: Center( - child: Text( - 'Index 2: School', - style: TextStyle( - fontWeight: FontWeight.w600, color: Colors.black, fontSize: 15), - ), - ), - ); - } -} diff --git a/lib/views/work/tabs/journal_view.dart b/lib/views/work/tabs/journal/journal_view.dart similarity index 99% rename from lib/views/work/tabs/journal_view.dart rename to lib/views/work/tabs/journal/journal_view.dart index 5adfa4f..2a3390c 100644 --- a/lib/views/work/tabs/journal_view.dart +++ b/lib/views/work/tabs/journal/journal_view.dart @@ -11,7 +11,7 @@ import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/buttons/option_pill.dart'; -import 'component/journal_list_tile.dart'; +import '../component/journal_list_tile.dart'; class JournalView extends StatefulWidget { @override diff --git a/lib/views/work/tabs/component/product_list_item.dart b/lib/views/work/tabs/sell/component/product_sell_tile.dart similarity index 97% rename from lib/views/work/tabs/component/product_list_item.dart rename to lib/views/work/tabs/sell/component/product_sell_tile.dart index 7b4075e..e628c27 100644 --- a/lib/views/work/tabs/component/product_list_item.dart +++ b/lib/views/work/tabs/sell/component/product_sell_tile.dart @@ -13,8 +13,8 @@ import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart'; import 'package:satu/widgets/ui/product_title_widget.dart'; -class ProductListItem extends StatefulWidget { - const ProductListItem( +class ProductSellTile extends StatefulWidget { + const ProductSellTile( {Key? key, this.name = '', this.ean, @@ -34,10 +34,10 @@ class ProductListItem extends StatefulWidget { final int? transactionId; @override - _ProductListItemState createState() => _ProductListItemState(); + _ProductSellTileState createState() => _ProductSellTileState(); } -class _ProductListItemState extends State { +class _ProductSellTileState extends State { final DialogService _dialogService = locator(); void _onItemTapped(BuildContext context) { diff --git a/lib/views/work/tabs/sell_view.dart b/lib/views/work/tabs/sell/sell_view.dart similarity index 94% rename from lib/views/work/tabs/sell_view.dart rename to lib/views/work/tabs/sell/sell_view.dart index 406e73c..7c72bd8 100644 --- a/lib/views/work/tabs/sell_view.dart +++ b/lib/views/work/tabs/sell/sell_view.dart @@ -10,16 +10,16 @@ import 'package:satu/core/utils/locator.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/ui_helpers.dart'; -import 'package:satu/views/work/tabs/component/product_list_item.dart'; +import 'package:satu/views/work/tabs/sell/component/product_sell_tile.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_header_bar.dart'; import 'package:satu/widgets/bar/products_title_bar.dart'; import 'package:satu/views/work/tabs/utils/product_utils.dart'; -import '../../../core/entity/goods_entity.dart'; -import '../../../core/redux/actions/sell_actions.dart'; -import '../../../core/services/dictionary_service.dart'; -import 'component/contagent_select_bar.dart'; +import '../../../../core/entity/goods_entity.dart'; +import '../../../../core/redux/actions/sell_actions.dart'; +import '../../../../core/services/dictionary_service.dart'; +import '../component/contagent_select_bar.dart'; class SellView extends StatelessWidget { @override @@ -62,7 +62,7 @@ class SellView extends StatelessWidget { itemBuilder: (BuildContext context, int index) { final ProductDao product = state.items!.elementAt(index); - return ProductListItem( + return ProductSellTile( key: UniqueKey(), ean: product.eanCode, isOdd: index % 2 == 0, diff --git a/lib/views/work/views/payment/payment_view.dart b/lib/views/work/views/payment/payment_view.dart index fc36f3d..0dbbe78 100644 --- a/lib/views/work/views/payment/payment_view.dart +++ b/lib/views/work/views/payment/payment_view.dart @@ -7,7 +7,7 @@ import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/utils_parse.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/app_colors.dart'; -import 'package:satu/core/services/data_service.dart'; +import 'package:satu/core/services/sell_service.dart'; import 'package:satu/views/work/views/payment/component/combine_dock.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_header_bar.dart'; @@ -24,7 +24,7 @@ class PaymentView extends StatefulWidget { } class _PaymentViewState extends State { - final DataService _dataService = locator(); + final SellService _dataService = locator(); final NavigatorService _navigatorService = locator(); bool combine = false; diff --git a/lib/views/work/views/receipt/receipt_view.dart b/lib/views/work/views/receipt/receipt_view.dart index 09a8e2c..f879c05 100644 --- a/lib/views/work/views/receipt/receipt_view.dart +++ b/lib/views/work/views/receipt/receipt_view.dart @@ -9,7 +9,7 @@ import 'package:satu/core/models/flow/sell_response.dart'; import 'package:satu/core/models/settings/printer_setting.dart'; import 'package:satu/core/models/ui_dao/popup_item_dao.dart'; import 'package:satu/core/redux/store.dart'; -import 'package:satu/core/services/data_service.dart'; +import 'package:satu/core/services/sell_service.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; @@ -32,7 +32,7 @@ class ReceiptView extends StatefulWidget { class _ReceiptViewState extends State { final DialogService _dialogService = locator(); - final DataService _dataService = locator(); + final SellService _dataService = locator(); final NavigatorService _navigatorService = locator(); PrinterBluetoothManager printerManager = PrinterBluetoothManager(); bool printerLocked = false; diff --git a/lib/views/work/work_view.dart b/lib/views/work/work_view.dart index 5782272..91ee30d 100644 --- a/lib/views/work/work_view.dart +++ b/lib/views/work/work_view.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/redux/store.dart'; -import 'package:satu/views/work/tabs/buy_view.dart'; -import 'package:satu/views/work/tabs/journal_view.dart'; -import 'package:satu/views/work/tabs/sell_view.dart'; +import 'package:satu/views/work/tabs/buy/buy_view.dart'; +import 'package:satu/views/work/tabs/journal/journal_view.dart'; +import 'package:satu/views/work/tabs/sell/sell_view.dart'; import 'package:satu/widgets/bar/bottom_bar.dart'; class WorkView extends StatefulWidget { diff --git a/lib/widgets/bar/bottom_bar.dart b/lib/widgets/bar/bottom_bar.dart index 28cab50..8f4995f 100644 --- a/lib/widgets/bar/bottom_bar.dart +++ b/lib/widgets/bar/bottom_bar.dart @@ -29,7 +29,6 @@ class BottomBar extends StatelessWidget { active: selectedIndex == 1, onTap: () => onTap(1), svgFile: 'buy', - disable: true, name: 'Покупка', ), BottomButton(