diff --git a/lib/core/models/dictionary/category/category_response.dart b/lib/core/models/dictionary/category/category_response.dart new file mode 100644 index 0000000..9c8468e --- /dev/null +++ b/lib/core/models/dictionary/category/category_response.dart @@ -0,0 +1,24 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'dart:convert'; + +part 'category_response.g.dart'; + +@JsonSerializable() +class CategoryResponse { + + CategoryResponse(); + + factory CategoryResponse.fromJson(Map json) => + _$CategoryResponseFromJson(json); + int? id; + @JsonKey(name: 'parent_id') + int? parentId; + String name = ''; + + Map toJson() => _$CategoryResponseToJson(this); + + @override + String toString() { + return jsonEncode(this); + } +} \ No newline at end of file diff --git a/lib/core/models/dictionary/category/category_response.g.dart b/lib/core/models/dictionary/category/category_response.g.dart new file mode 100644 index 0000000..b2d4d2e --- /dev/null +++ b/lib/core/models/dictionary/category/category_response.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'category_response.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +CategoryResponse _$CategoryResponseFromJson(Map json) => + CategoryResponse() + ..id = json['id'] as int? + ..parentId = json['parent_id'] as int? + ..name = json['name'] as String; + +Map _$CategoryResponseToJson(CategoryResponse instance) => + { + 'id': instance.id, + 'parent_id': instance.parentId, + 'name': instance.name, + }; diff --git a/lib/core/models/dictionary/category_response.dart b/lib/core/models/dictionary/category_response.dart deleted file mode 100644 index 1b16082..0000000 --- a/lib/core/models/dictionary/category_response.dart +++ /dev/null @@ -1,27 +0,0 @@ -/// id : 4 -/// parent_id : 0 -/// name : "" -/// updated_at : "2021-01-06 14:20:47" - -class CategoryResponse { - int? id; - int? parentId; - String name = ''; - String? updatedAt; - - static CategoryResponse fromMap(dynamic map) { - final CategoryResponse categoryResponseBean = CategoryResponse(); - categoryResponseBean.id = map['id'] as int; - categoryResponseBean.parentId = map['parent_id'] as int?; - categoryResponseBean.name = map['name'] as String; - categoryResponseBean.updatedAt = map['updated_at'] as String; - return categoryResponseBean; - } - - Map toJson() => { - 'id': id, - 'parent_id': parentId, - 'name': name, - 'updated_at': updatedAt, - }; -} \ No newline at end of file diff --git a/lib/core/models/dictionary/category_row_data.dart b/lib/core/models/dictionary/category_row_data.dart deleted file mode 100644 index 8e342f8..0000000 --- a/lib/core/models/dictionary/category_row_data.dart +++ /dev/null @@ -1,10 +0,0 @@ -class CategoryRowDao { - CategoryRowDao(this.name, this.parentName, this.id, - {this.parentId = 0, this.ean}); - - final String name; - final String parentName; - final String? ean; - final int? id; - final int? parentId; -} diff --git a/lib/core/models/dictionary/good/good_response_entity.dart b/lib/core/models/dictionary/good/good_response_entity.dart new file mode 100644 index 0000000..08ae0d2 --- /dev/null +++ b/lib/core/models/dictionary/good/good_response_entity.dart @@ -0,0 +1,38 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'dart:convert'; + +part 'good_response_entity.g.dart'; + +@JsonSerializable() +class GoodResponseEntity { + + factory GoodResponseEntity.fromJson(Map json) => + _$GoodResponseEntityFromJson(json); + + GoodResponseEntity(); + int? id; + @JsonKey(name: 'eacc_good_category_id') + int? categoryId; + String name = ''; + String? ean13; + int? articul; + double? price; + @JsonKey(name: 'opt_price') + double? optPrice; + @JsonKey(name: 'base_price') + double? basePrice; + @JsonKey(name: 'auto_base_price') + double? autoBasePrice; + int? divisible; + String? description; + @JsonKey(name: 'category_name') + String? categoryName; + + Map toJson() => _$GoodResponseEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + +} diff --git a/lib/core/models/dictionary/good/good_response_entity.g.dart b/lib/core/models/dictionary/good/good_response_entity.g.dart new file mode 100644 index 0000000..80234fc --- /dev/null +++ b/lib/core/models/dictionary/good/good_response_entity.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'good_response_entity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +GoodResponseEntity _$GoodResponseEntityFromJson(Map json) => + GoodResponseEntity() + ..id = json['id'] as int? + ..categoryId = json['eacc_good_category_id'] as int? + ..name = json['name'] as String + ..ean13 = json['ean13'] as String? + ..articul = json['articul'] as int? + ..price = (json['price'] as num?)?.toDouble() + ..optPrice = (json['opt_price'] as num?)?.toDouble() + ..basePrice = (json['base_price'] as num?)?.toDouble() + ..autoBasePrice = (json['auto_base_price'] as num?)?.toDouble() + ..divisible = json['divisible'] as int? + ..description = json['description'] as String? + ..categoryName = json['category_name'] as String?; + +Map _$GoodResponseEntityToJson(GoodResponseEntity instance) => + { + 'id': instance.id, + 'eacc_good_category_id': instance.categoryId, + 'name': instance.name, + 'ean13': instance.ean13, + 'articul': instance.articul, + 'price': instance.price, + 'opt_price': instance.optPrice, + 'base_price': instance.basePrice, + 'auto_base_price': instance.autoBasePrice, + 'divisible': instance.divisible, + 'description': instance.description, + 'category_name': instance.categoryName, + }; diff --git a/lib/core/models/dictionary/good_response.dart b/lib/core/models/dictionary/good_response.dart deleted file mode 100644 index 9dafb67..0000000 --- a/lib/core/models/dictionary/good_response.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:satu/core/utils/utils_parse.dart'; - -/// id : 6 -/// category_id : 4 -/// name : "KENT SILVER" -/// ean : "46187413" -/// articul : 1 -/// price : 500 -/// opt_price : 500 -/// base_price : 500 -/// divisible : 0 -/// updated_at : "2021-02-03 11:37:34" - -class GoodResponse { - int? id; - int? categoryId; - String name = ''; - String? ean; - int? articul; - double? price; - double? optPrice; - double? basePrice; - int? divisible; - String? updatedAt; - String? categoryName; - - - static GoodResponse fromMap(dynamic map) { - final GoodResponse goodResponseBean = GoodResponse(); - goodResponseBean.id = map['id'] as int; - goodResponseBean.categoryId = map['eacc_good_category_id'] as int?; - goodResponseBean.name = map['name'] as String; - goodResponseBean.ean = map['ean'] as String?; - goodResponseBean.articul = map['articul'] as int; - goodResponseBean.price = (cast(map['price']) ?? 0).toDouble() ; - goodResponseBean.optPrice = (cast(map['opt_price']) ?? 0).toDouble(); - goodResponseBean.basePrice = (cast(map['base_price']) ?? 0).toDouble(); - goodResponseBean.divisible = map['divisible'] as int?; - goodResponseBean.updatedAt = map['updated_at'] as String; - goodResponseBean.categoryName = map['category_name'] as String?; - return goodResponseBean; - } - - Map toJson() { - final Map map = { - 'id': id, - 'category_id': categoryId, - 'name': name, - 'ean': ean, - 'articul': articul, - 'price': price, - 'opt_price': optPrice, - 'base_price': basePrice, - 'divisible': divisible, - 'updated_at': updatedAt, - }; - return map; - } -} diff --git a/lib/core/models/dictionary/good_row_data.dart b/lib/core/models/dictionary/good_row_data.dart deleted file mode 100644 index 03c7b73..0000000 --- a/lib/core/models/dictionary/good_row_data.dart +++ /dev/null @@ -1,11 +0,0 @@ -class GoodRowDao { - GoodRowDao(this.name, this.categoryName, - {this.ean, this.id, this.categoryId} - ); - - final String name; - final String categoryName; - final int? categoryId; - final String? ean; - final int? id; -} \ No newline at end of file diff --git a/lib/core/services/dictionary_service.dart b/lib/core/services/dictionary_service.dart index af2475d..af34188 100644 --- a/lib/core/services/dictionary_service.dart +++ b/lib/core/services/dictionary_service.dart @@ -1,9 +1,9 @@ import 'package:satu/core/base/base_service.dart'; import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/entity/goods_entity.dart'; -import 'package:satu/core/models/dictionary/category_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_response.dart'; +import 'package:satu/core/models/dictionary/good/good_response_entity.dart'; import 'package:satu/core/models/dictionary/response/dict_response_entity.dart'; import 'package:satu/core/redux/store.dart'; import 'package:satu/core/utils/locator.dart'; @@ -15,11 +15,7 @@ class DictionaryService extends BaseService { final ApiService _api = locator(); final DbService _db = locator(); - Future refreshFull() async { - - } - - + Future refreshFull() async {} Future> getCategoryByParentId(int parentId) async { final List list = []; @@ -56,8 +52,6 @@ class DictionaryService extends BaseService { return result; } - - Future> getGoodsByCategoryId(int categoryId) async { final List list = []; try { @@ -104,7 +98,8 @@ class DictionaryService extends BaseService { return int.tryParse(str) != null; } - Future> getCategories( {required int page, String? query, required int perpage}) async { + Future> getCategories( + {required int page, required int perpage, String? query}) async { List list = []; try { final Map requestBody = { @@ -115,12 +110,12 @@ class DictionaryService extends BaseService { ] }; - DictResponseEntity categories = - await _api.dictionaries('/goods_categories_get', requestBody: requestBody); + DictResponseEntity categories = await _api + .dictionaries('/goods_categories_get', requestBody: requestBody); if (categories.original.data != null && categories.original.data!.isNotEmpty) { for (final dynamic map in categories.original.data!) { - final CategoryResponse good = CategoryResponse.fromMap(map); + final CategoryResponse good = CategoryResponse.fromJson(map); list.add(good); } } @@ -130,9 +125,31 @@ class DictionaryService extends BaseService { return list; } - Future> getGoods( - {required int page, String? query, required int perpage}) async { - List list = []; + Future saveCategory(CategoryResponse category) async { + DictResponseEntity? status; + log.i(category.toJson()); + if (category.id != null) { + status = await _api.dictionarySave( + '/goods_categories_edit', category.toJson()); + } else { + status = + await _api.dictionarySave('/goods_categories_add', category.toJson()); + } + String? message = getErrorMsg(status); + + return message; + } + + Future deleteCategory(CategoryResponse category) async { + DictResponseEntity status = await _api.dictionarySave( + '/goods_categories_delete', category.toJson()); + String? message = getErrorMsg(status); + return message; + } + + Future> getGoods( + {required int page, required int perpage, String? query}) async { + List list = []; try { final Map requestBody = { 'page': page, @@ -143,11 +160,11 @@ class DictionaryService extends BaseService { }; DictResponseEntity categories = - await _api.dictionaries('/goods_goods_get', requestBody: requestBody); + await _api.dictionaries('/goods_goods_get', requestBody: requestBody); if (categories.original.data != null && categories.original.data!.isNotEmpty) { for (final dynamic map in categories.original.data!) { - final GoodResponse good = GoodResponse.fromMap(map); + final GoodResponseEntity good = GoodResponseEntity.fromJson(map); list.add(good); } } @@ -157,6 +174,27 @@ class DictionaryService extends BaseService { return list; } + Future saveGood(GoodResponseEntity good) async { + DictResponseEntity? status; + if (good.id != null) { + status = + await _api.dictionarySave('/goods_goods_edit', good.toJson()); + } else { + status = + await _api.dictionarySave('/goods_goods_add', good.toJson()); + } + String? message = getErrorMsg(status); + + return message; + } + + Future deleteGood(GoodResponseEntity good) async { + DictResponseEntity status = + await _api.dictionarySave('/goods_goods_delete', good.toJson()); + String? message = getErrorMsg(status); + return message; + } + Future> getContragents( {int? page, int? perpage, String? query}) async { final List list = []; diff --git a/lib/routes/router.dart b/lib/routes/router.dart index da8324b..78d61f1 100644 --- a/lib/routes/router.dart +++ b/lib/routes/router.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:satu/core/models/dictionary/category_response.dart'; -import 'package:satu/core/models/dictionary/category_row_data.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_response.dart'; -import 'package:satu/core/models/dictionary/good_row_data.dart'; +import 'package:satu/core/models/dictionary/good/good_response_entity.dart'; import 'package:satu/views/dictionaries/category/category_edit.dart'; import 'package:satu/views/dictionaries/category/category_select_view.dart'; import 'package:satu/views/dictionaries/contragents/contragents_edit.dart'; @@ -102,7 +100,7 @@ Route generateRoute(RouteSettings settings) { viewToShow: CategorySelectView(), ); case goodsEditRoute: - final GoodResponse good = settings.arguments! as GoodResponse; + final GoodResponseEntity good = settings.arguments! as GoodResponseEntity; return _getPageRoute( routeName: settings.name, viewToShow: GoodEdit( diff --git a/lib/views/dictionaries/category/category_edit.dart b/lib/views/dictionaries/category/category_edit.dart index ec10884..3598d5d 100644 --- a/lib/views/dictionaries/category/category_edit.dart +++ b/lib/views/dictionaries/category/category_edit.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; -import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/models/dialog_models.dart'; -import 'package:satu/core/models/dictionary/category_response.dart'; -import 'package:satu/core/models/dictionary/category_row_data.dart'; +import 'package:satu/core/models/dictionary/category/category_response.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; @@ -53,6 +51,28 @@ class _CategoryEditState extends State { super.dispose(); } + void save() async { + CategoryResponse category = widget.category; + category.name = _controller.text; + category.parentId = parentCategoryId; + String? message = await _dictionaryService.saveCategory(category); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } + + void delete() async { + CategoryResponse category = widget.category; + String? message = await _dictionaryService.deleteCategory(category); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } + @override @@ -83,7 +103,9 @@ class _CategoryEditState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0), - child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {}), + child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () { + save(); + }), ), if (widget.category.id != null) Padding( @@ -99,8 +121,10 @@ class _CategoryEditState extends State { 'Вы уверены, что хотите удалить категорию?', confirmationTitle: 'Удалить', cancelTitle: 'Отмена'); + if(response.confirmed){ + delete(); + } - return response.confirmed; }, isDanger: true, ), diff --git a/lib/views/dictionaries/category/category_select_view.dart b/lib/views/dictionaries/category/category_select_view.dart index c25be43..e02d155 100644 --- a/lib/views/dictionaries/category/category_select_view.dart +++ b/lib/views/dictionaries/category/category_select_view.dart @@ -2,9 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/models/dictionary/category_response.dart'; -import 'package:satu/core/models/dictionary/category_row_data.dart'; +import 'package:satu/core/models/dictionary/category/category_response.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; diff --git a/lib/views/dictionaries/category/category_view.dart b/lib/views/dictionaries/category/category_view.dart index 8cf8e13..2744937 100644 --- a/lib/views/dictionaries/category/category_view.dart +++ b/lib/views/dictionaries/category/category_view.dart @@ -2,10 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/models/dictionary/category_response.dart'; -import 'package:satu/core/models/dictionary/category_row_data.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; +import 'package:satu/core/models/dictionary/category/category_response.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; @@ -27,7 +24,6 @@ class _CategoryDictionaryViewState extends State { late TextEditingController _searchTextController; final FocusNode _searchFocusNode = new FocusNode(); - static const _pageSize = 20; String query = ''; Timer? _debounce; @@ -93,8 +89,13 @@ class _CategoryDictionaryViewState extends State { int index) { return DictionaryTile( key: Key('category_${category.id}'), - onPress: () => _navigatorService.push(categoryEditRoute, - arguments: category), + onPress: () async { + final dynamic result = await _navigatorService + .push(categoryEditRoute, arguments: category); + if (result != null && true == (result as bool)) { + _pagingController.refresh(); + } + }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -104,7 +105,7 @@ class _CategoryDictionaryViewState extends State { const TextStyle(fontSize: 12, color: textColor), ), Text( - category.parentId ==null + category.parentId == null ? 'Корневая категория' : 'Родитель: ${category.parentId}', style: const TextStyle( @@ -120,8 +121,8 @@ class _CategoryDictionaryViewState extends State { ), floatingActionButton: FloatingActionButton( elevation: 2, - onPressed: () => locator() - .push(categoryEditRoute, arguments: CategoryRowDao('', '', null)), + onPressed: () => _navigatorService.push(categoryEditRoute, + arguments: CategoryResponse()), child: const Icon( Icons.add_rounded, size: 34.0, diff --git a/lib/views/dictionaries/contragents/contragents_edit.dart b/lib/views/dictionaries/contragents/contragents_edit.dart index 1aa546d..fc22d36 100644 --- a/lib/views/dictionaries/contragents/contragents_edit.dart +++ b/lib/views/dictionaries/contragents/contragents_edit.dart @@ -103,21 +103,37 @@ class _ContragentEditState extends State { controller: _controllerName, labelText: 'Наименование', placeholder: 'Введите наименование контрагента', + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( controller: _controllerBinIin, labelText: 'БИН/ИИН>', placeholder: 'Введите БИН/ИИН', + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( controller: _controllerPhone, labelText: 'Телефон', placeholder: 'Введите номер телефона', + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( controller: _controllerMail, labelText: 'E-mail"', placeholder: 'Введите электронную почту', + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputCheckBox('НДС', value: _isNds, labelText: 'Плательщик НДС', onChanged: (value) { diff --git a/lib/views/dictionaries/contragents/contragents_view.dart b/lib/views/dictionaries/contragents/contragents_view.dart index 4e1df98..f8a9686 100644 --- a/lib/views/dictionaries/contragents/contragents_view.dart +++ b/lib/views/dictionaries/contragents/contragents_view.dart @@ -1,9 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart'; -import 'package:satu/core/models/dictionary/good_row_data.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; @@ -88,7 +85,7 @@ class _ContragentsDictionaryViewState extends State { final dynamic result = await _navigatorService .push(contragentEditRoute, arguments: entity); if (result != null && true == (result as bool)) { - //searchByField(''); + _pagingController.refresh(); } }, child: Column( diff --git a/lib/views/dictionaries/goods/goods_edit.dart b/lib/views/dictionaries/goods/goods_edit.dart index 764a28b..da0d5d0 100644 --- a/lib/views/dictionaries/goods/goods_edit.dart +++ b/lib/views/dictionaries/goods/goods_edit.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; -import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/models/dialog_models.dart'; -import 'package:satu/core/models/dictionary/good_response.dart'; -import 'package:satu/core/models/dictionary/good_row_data.dart'; +import 'package:satu/core/models/dictionary/category/category_response.dart'; +import 'package:satu/core/models/dictionary/good/good_response_entity.dart'; import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/logger.dart'; +import 'package:satu/core/utils/utils_parse.dart'; import 'package:satu/routes/route_names.dart'; import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/widgets/bar/products_app_bar.dart'; @@ -21,7 +21,7 @@ class GoodEdit extends StatefulWidget { required this.good, Key? key, }) : super(key: key); - final GoodResponse good; + final GoodResponseEntity good; @override _GoodEditState createState() => _GoodEditState(); @@ -32,9 +32,18 @@ class _GoodEditState extends State { final DictionaryService _dictionaryService = locator(); final DialogService _dialogService = locator(); final Logger log = getLogger('_GoodEditState'); - late TextEditingController _controller; + late TextEditingController _controllerArticle; + late TextEditingController _controllerName; - String parentCategoryName = ''; + late TextEditingController _controllerPrice; + late TextEditingController _controllerOptPrice; + late TextEditingController _controllerBasePrice; + late TextEditingController _controllerEan; + late TextEditingController _controllerDescription; + + bool isDivisible = false; + + String? parentCategoryName; int? parentCategoryId; @override @@ -42,35 +51,64 @@ class _GoodEditState extends State { super.initState(); if (widget.good.categoryId != null) { parentCategoryId = widget.good.categoryId; - parentCategoryName = widget.good.categoryName ?? ''; + parentCategoryName = widget.good.categoryName; } - _controller = TextEditingController(text: widget.good.name); - - //getAndStateCategoryName(parentCategoryId); + _controllerArticle = + TextEditingController(text: widget.good.articul?.toString() ?? ''); + _controllerName = TextEditingController(text: widget.good.name); + _controllerPrice = TextEditingController( + text: + widget.good.price != null ? formatDecimal(widget.good.price!) : ''); + _controllerOptPrice = TextEditingController( + text: widget.good.optPrice != null + ? formatDecimal(widget.good.optPrice!) + : ''); + _controllerBasePrice = TextEditingController( + text: widget.good.basePrice != null + ? formatDecimal(widget.good.basePrice!) + : ''); + _controllerEan = TextEditingController(text: widget.good.ean13); + _controllerDescription = + TextEditingController(text: widget.good.description); } @override void dispose() { - _controller.dispose(); + _controllerArticle.dispose(); + _controllerName.dispose(); + _controllerPrice.dispose(); + _controllerOptPrice.dispose(); + _controllerBasePrice.dispose(); + _controllerEan.dispose(); + _controllerDescription.dispose(); super.dispose(); } - // Future getAndStateCategoryName(int? id) async { - // String name = ''; - // if (id == null) { - // } else if (id == 0) { - // name = 'Корневая категория'; - // } else { - // final Category? category = await _dictionaryService.getCategoryById(id); - // if (category != null) { - // name = category.name; - // } - // } - // setState(() { - // parentCategoryName = name; - // parentCategoryId = id; - // }); - // } + void save() async { + GoodResponseEntity good = widget.good; + good.name = _controllerName.text; + good.price = parseNumeric(_controllerPrice.text); + good.optPrice = parseNumeric(_controllerOptPrice.text); + good.basePrice = parseNumeric(_controllerBasePrice.text); + good.ean13 = _controllerEan.text; + good.description = _controllerDescription.text; + String? message = await _dictionaryService.saveGood(good); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } + + void delete() async { + GoodResponseEntity good = widget.good; + String? message = await _dictionaryService.deleteGood(good); + if (message != null) { + _dialogService.showDialog(description: message); + } else { + _navigatorService.pop(true); + } + } @override Widget build(BuildContext context) { @@ -88,52 +126,91 @@ class _GoodEditState extends State { verticalSpaceSmall, InputField( isReadOnly: true, - controller: _controller, + controller: _controllerArticle, labelText: 'Номенклатурный номер', placeholder: 'Не присвоен', ), LineTile( - parentCategoryName, + parentCategoryName ?? '', onTap: selectCategory, labelText: 'Категория', placeholder: 'Выберите категорию', ), verticalSpaceSmall, InputField( - controller: _controller, + controller: _controllerName, labelText: 'Наименование', placeholder: 'Введите наименование товара', + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( - controller: _controller, + controller: _controllerPrice, labelText: 'Розничная цена', placeholder: 'Введите розничную цену', + suffixText: '₸', + textInputType: + const TextInputType.numberWithOptions(decimal: true), + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( - controller: _controller, + controller: _controllerOptPrice, labelText: 'Оптовая цена', placeholder: 'Введите оптовую цену', + suffixText: '₸', + textInputType: + const TextInputType.numberWithOptions(decimal: true), + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( - controller: _controller, + controller: _controllerBasePrice, labelText: 'Закупочная цена для автоматически пополняемого товара', placeholder: 'Введите закупочную цену', + suffixText: '₸', + textInputType: + const TextInputType.numberWithOptions(decimal: true), + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( - controller: _controller, + controller: _controllerEan, labelText: 'EAN Штрих-код', placeholder: 'Введите EAN', + textInputType: + const TextInputType.numberWithOptions(decimal: false), + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), InputField( - controller: _controller, - labelText: 'Наименование', - placeholder: 'Введите наименование товара', + controller: _controllerDescription, + labelText: 'Описание', + placeholder: 'Введите описание товара', + multiline: true, + textInputType: TextInputType.multiline, + enterPressed: (){ + FocusManager.instance.primaryFocus?.unfocus(); + }, + textInputAction: TextInputAction.done, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0), - child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {}), + child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () { + save(); + }), ), if (widget.good.id != null) Padding( @@ -150,7 +227,9 @@ class _GoodEditState extends State { confirmationTitle: 'Удалить', cancelTitle: 'Отмена'); - return response.confirmed; + if(response.confirmed){ + delete(); + } }, isDanger: true, ), @@ -164,8 +243,10 @@ class _GoodEditState extends State { Future selectCategory() async { final dynamic result = await _navigatorService.push(categorySelectViewRoute); - if (result != null) { - //getAndStateCategoryName(result as int); - } + CategoryResponse? category = result as CategoryResponse?; + setState(() { + parentCategoryId = category?.id; + parentCategoryName = category?.name; + }); } } diff --git a/lib/views/dictionaries/goods/goods_view.dart b/lib/views/dictionaries/goods/goods_view.dart index eb385ec..b534e27 100644 --- a/lib/views/dictionaries/goods/goods_view.dart +++ b/lib/views/dictionaries/goods/goods_view.dart @@ -3,11 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -import 'package:satu/core/entity/category_entity.dart'; -import 'package:satu/core/entity/goods_entity.dart'; -import 'package:satu/core/models/dictionary/good_response.dart'; -import 'package:satu/core/models/dictionary/good_row_data.dart'; -import 'package:satu/core/redux/actions/sell_actions.dart'; +import 'package:satu/core/models/dictionary/good/good_response_entity.dart'; import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/utils/locator.dart'; @@ -33,8 +29,8 @@ class _GoodsDictionaryViewState extends State { String query = ''; Timer? _debounce; - final PagingController _pagingController = - PagingController(firstPageKey: 1); + final PagingController _pagingController = + PagingController(firstPageKey: 1); @override void initState() { @@ -100,40 +96,47 @@ class _GoodsDictionaryViewState extends State { ), const ProductsTitleBarBar(title: 'Список товаров'), Expanded( - child: PagedListView.separated( - physics: const BouncingScrollPhysics(), - separatorBuilder: (BuildContext context, int index) { - return const Divider( - height: 1.0, - color: disableColor, + 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, GoodResponseEntity good, int index) { + return DictionaryTile( + onPress: () async { + final dynamic result = await _navigatorService + .push(goodsEditRoute, arguments: good); + if (result != null && true == (result as bool)) { + _pagingController.refresh(); + } + }, + child: ProductTitleWidget( + name: good.name, + categoryName: good.categoryName, + ean: good.ean13, + ), ); }, - pagingController: _pagingController, - builderDelegate: PagedChildBuilderDelegate( - itemBuilder: - (BuildContext context, GoodResponse good, int index) { - return DictionaryTile( - onPress: () { - locator() - .push(goodsEditRoute, arguments: good); - }, - child: ProductTitleWidget( - name: good.name, - categoryName: good.categoryName, - ean: good.ean, - ), - ); - }, - ), ), + ), ) ], ), floatingActionButton: FloatingActionButton( elevation: 2, - onPressed: () => - locator() - .push(goodsEditRoute, arguments: GoodRowDao('', '')), + onPressed: () async { + final dynamic result = await _navigatorService.push(goodsEditRoute, + arguments: GoodResponseEntity()); + if (result != null && true == (result as bool)) { + _pagingController.refresh(); + } + }, child: const Icon( Icons.add_rounded, size: 34.0, @@ -148,7 +151,7 @@ class _GoodsDictionaryViewState extends State { } Future _fetchData(int pageKey, int perPage, String? query) async { - final List newItems = await _dictionaryService.getGoods( + final List newItems = await _dictionaryService.getGoods( page: pageKey, query: query, perpage: perPage); final isLastPage = newItems.length < _pageSize; diff --git a/lib/widgets/fields/input_field.dart b/lib/widgets/fields/input_field.dart index 7cb6160..8f13ea3 100644 --- a/lib/widgets/fields/input_field.dart +++ b/lib/widgets/fields/input_field.dart @@ -127,7 +127,7 @@ class _InputFieldState extends State { keyboardType: widget.textInputType, focusNode: widget.fieldFocusNode, textInputAction: widget.textInputAction, - maxLines: widget.multiline ? null : 1, + maxLines: widget.multiline ? 5 : 1, onChanged: widget.onChanged, initialValue: widget.initialValue, inputFormatters: