Справочники

категории + товары + каонтрагенты
null-safety-migration
suvaysov 2022-07-02 19:27:37 +06:00
parent 34b669eea0
commit 498c681f06
18 changed files with 398 additions and 229 deletions

View File

@ -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<String, dynamic> json) =>
_$CategoryResponseFromJson(json);
int? id;
@JsonKey(name: 'parent_id')
int? parentId;
String name = '';
Map<String, dynamic> toJson() => _$CategoryResponseToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}

View File

@ -0,0 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'category_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
CategoryResponse _$CategoryResponseFromJson(Map<String, dynamic> json) =>
CategoryResponse()
..id = json['id'] as int?
..parentId = json['parent_id'] as int?
..name = json['name'] as String;
Map<String, dynamic> _$CategoryResponseToJson(CategoryResponse instance) =>
<String, dynamic>{
'id': instance.id,
'parent_id': instance.parentId,
'name': instance.name,
};

View File

@ -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,
};
}

View File

@ -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;
}

View File

@ -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<String, dynamic> 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<String, dynamic> toJson() => _$GoodResponseEntityToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}

View File

@ -0,0 +1,38 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'good_response_entity.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GoodResponseEntity _$GoodResponseEntityFromJson(Map<String, dynamic> 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<String, dynamic> _$GoodResponseEntityToJson(GoodResponseEntity instance) =>
<String, dynamic>{
'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,
};

View File

@ -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<num>(map['price']) ?? 0).toDouble() ;
goodResponseBean.optPrice = (cast<num>(map['opt_price']) ?? 0).toDouble();
goodResponseBean.basePrice = (cast<num>(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<String, dynamic> toJson() {
final Map<String, dynamic> map = <String, dynamic>{
'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;
}
}

View File

@ -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;
}

View File

@ -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<ApiService>();
final DbService _db = locator<DbService>();
Future<void> refreshFull() async {
}
Future<void> refreshFull() async {}
Future<List<Category>> getCategoryByParentId(int parentId) async {
final List<Category> list = [];
@ -56,8 +52,6 @@ class DictionaryService extends BaseService {
return result;
}
Future<List<Good>> getGoodsByCategoryId(int categoryId) async {
final List<Good> list = [];
try {
@ -104,7 +98,8 @@ class DictionaryService extends BaseService {
return int.tryParse(str) != null;
}
Future<List<CategoryResponse>> getCategories( {required int page, String? query, required int perpage}) async {
Future<List<CategoryResponse>> getCategories(
{required int page, required int perpage, String? query}) async {
List<CategoryResponse> list = [];
try {
final Map<String, dynamic> requestBody = <String, dynamic>{
@ -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<List<GoodResponse>> getGoods(
{required int page, String? query, required int perpage}) async {
List<GoodResponse> list = [];
Future<String?> 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<String?> deleteCategory(CategoryResponse category) async {
DictResponseEntity status = await _api.dictionarySave(
'/goods_categories_delete', category.toJson());
String? message = getErrorMsg(status);
return message;
}
Future<List<GoodResponseEntity>> getGoods(
{required int page, required int perpage, String? query}) async {
List<GoodResponseEntity> list = [];
try {
final Map<String, dynamic> requestBody = <String, dynamic>{
'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<String?> 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<String?> deleteGood(GoodResponseEntity good) async {
DictResponseEntity status =
await _api.dictionarySave('/goods_goods_delete', good.toJson());
String? message = getErrorMsg(status);
return message;
}
Future<List<ContragentResponseEntity>> getContragents(
{int? page, int? perpage, String? query}) async {
final List<ContragentResponseEntity> list = [];

View File

@ -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<dynamic> 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(

View File

@ -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<CategoryEdit> {
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<CategoryEdit> {
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<CategoryEdit> {
'Вы уверены, что хотите удалить категорию?',
confirmationTitle: 'Удалить',
cancelTitle: 'Отмена');
if(response.confirmed){
delete();
}
return response.confirmed;
},
isDanger: true,
),

View File

@ -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';

View File

@ -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<CategoryDictionaryView> {
late TextEditingController _searchTextController;
final FocusNode _searchFocusNode = new FocusNode();
static const _pageSize = 20;
String query = '';
Timer? _debounce;
@ -93,8 +89,13 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
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<CategoryDictionaryView> {
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<CategoryDictionaryView> {
),
floatingActionButton: FloatingActionButton(
elevation: 2,
onPressed: () => locator<NavigatorService>()
.push(categoryEditRoute, arguments: CategoryRowDao('', '', null)),
onPressed: () => _navigatorService.push(categoryEditRoute,
arguments: CategoryResponse()),
child: const Icon(
Icons.add_rounded,
size: 34.0,

View File

@ -103,21 +103,37 @@ class _ContragentEditState extends State<ContragentEdit> {
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) {

View File

@ -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<ContragentsDictionaryView> {
final dynamic result = await _navigatorService
.push(contragentEditRoute, arguments: entity);
if (result != null && true == (result as bool)) {
//searchByField('');
_pagingController.refresh();
}
},
child: Column(

View File

@ -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<GoodEdit> {
final DictionaryService _dictionaryService = locator<DictionaryService>();
final DialogService _dialogService = locator<DialogService>();
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<GoodEdit> {
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<void> 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<GoodEdit> {
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<GoodEdit> {
confirmationTitle: 'Удалить',
cancelTitle: 'Отмена');
return response.confirmed;
if(response.confirmed){
delete();
}
},
isDanger: true,
),
@ -164,8 +243,10 @@ class _GoodEditState extends State<GoodEdit> {
Future<void> 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;
});
}
}

View File

@ -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<GoodsDictionaryView> {
String query = '';
Timer? _debounce;
final PagingController<int, GoodResponse> _pagingController =
PagingController(firstPageKey: 1);
final PagingController<int, GoodResponseEntity> _pagingController =
PagingController(firstPageKey: 1);
@override
void initState() {
@ -100,40 +96,47 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
),
const ProductsTitleBarBar(title: 'Список товаров'),
Expanded(
child: PagedListView<int, GoodResponse>.separated(
physics: const BouncingScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1.0,
color: disableColor,
child: PagedListView<int, GoodResponseEntity>.separated(
physics: const BouncingScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1.0,
color: disableColor,
);
},
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<GoodResponseEntity>(
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<GoodResponse>(
itemBuilder:
(BuildContext context, GoodResponse good, int index) {
return DictionaryTile(
onPress: () {
locator<NavigatorService>()
.push(goodsEditRoute, arguments: good);
},
child: ProductTitleWidget(
name: good.name,
categoryName: good.categoryName,
ean: good.ean,
),
);
},
),
),
),
)
],
),
floatingActionButton: FloatingActionButton(
elevation: 2,
onPressed: () =>
locator<NavigatorService>()
.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<GoodsDictionaryView> {
}
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
final List<GoodResponse> newItems = await _dictionaryService.getGoods(
final List<GoodResponseEntity> newItems = await _dictionaryService.getGoods(
page: pageKey, query: query, perpage: perPage);
final isLastPage = newItems.length < _pageSize;

View File

@ -127,7 +127,7 @@ class _InputFieldState extends State<InputField> {
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: