Справочники

категории + товары + каонтрагенты
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/base/base_service.dart';
import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/entity/category_entity.dart';
import 'package:satu/core/entity/goods_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/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/models/dictionary/response/dict_response_entity.dart';
import 'package:satu/core/redux/store.dart'; import 'package:satu/core/redux/store.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
@ -15,11 +15,7 @@ class DictionaryService extends BaseService {
final ApiService _api = locator<ApiService>(); final ApiService _api = locator<ApiService>();
final DbService _db = locator<DbService>(); final DbService _db = locator<DbService>();
Future<void> refreshFull() async { Future<void> refreshFull() async {}
}
Future<List<Category>> getCategoryByParentId(int parentId) async { Future<List<Category>> getCategoryByParentId(int parentId) async {
final List<Category> list = []; final List<Category> list = [];
@ -56,8 +52,6 @@ class DictionaryService extends BaseService {
return result; return result;
} }
Future<List<Good>> getGoodsByCategoryId(int categoryId) async { Future<List<Good>> getGoodsByCategoryId(int categoryId) async {
final List<Good> list = []; final List<Good> list = [];
try { try {
@ -104,7 +98,8 @@ class DictionaryService extends BaseService {
return int.tryParse(str) != null; 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 = []; List<CategoryResponse> list = [];
try { try {
final Map<String, dynamic> requestBody = <String, dynamic>{ final Map<String, dynamic> requestBody = <String, dynamic>{
@ -115,12 +110,12 @@ class DictionaryService extends BaseService {
] ]
}; };
DictResponseEntity categories = DictResponseEntity categories = await _api
await _api.dictionaries('/goods_categories_get', requestBody: requestBody); .dictionaries('/goods_categories_get', requestBody: requestBody);
if (categories.original.data != null && if (categories.original.data != null &&
categories.original.data!.isNotEmpty) { categories.original.data!.isNotEmpty) {
for (final dynamic map in categories.original.data!) { for (final dynamic map in categories.original.data!) {
final CategoryResponse good = CategoryResponse.fromMap(map); final CategoryResponse good = CategoryResponse.fromJson(map);
list.add(good); list.add(good);
} }
} }
@ -130,9 +125,31 @@ class DictionaryService extends BaseService {
return list; return list;
} }
Future<List<GoodResponse>> getGoods( Future<String?> saveCategory(CategoryResponse category) async {
{required int page, String? query, required int perpage}) async { DictResponseEntity? status;
List<GoodResponse> list = []; 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 { try {
final Map<String, dynamic> requestBody = <String, dynamic>{ final Map<String, dynamic> requestBody = <String, dynamic>{
'page': page, 'page': page,
@ -147,7 +164,7 @@ class DictionaryService extends BaseService {
if (categories.original.data != null && if (categories.original.data != null &&
categories.original.data!.isNotEmpty) { categories.original.data!.isNotEmpty) {
for (final dynamic map in categories.original.data!) { for (final dynamic map in categories.original.data!) {
final GoodResponse good = GoodResponse.fromMap(map); final GoodResponseEntity good = GoodResponseEntity.fromJson(map);
list.add(good); list.add(good);
} }
} }
@ -157,6 +174,27 @@ class DictionaryService extends BaseService {
return list; 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( Future<List<ContragentResponseEntity>> getContragents(
{int? page, int? perpage, String? query}) async { {int? page, int? perpage, String? query}) async {
final List<ContragentResponseEntity> list = []; final List<ContragentResponseEntity> list = [];

View File

@ -1,9 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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/category_row_data.dart';
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.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/good_row_data.dart';
import 'package:satu/views/dictionaries/category/category_edit.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/category/category_select_view.dart';
import 'package:satu/views/dictionaries/contragents/contragents_edit.dart'; import 'package:satu/views/dictionaries/contragents/contragents_edit.dart';
@ -102,7 +100,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
viewToShow: CategorySelectView(), viewToShow: CategorySelectView(),
); );
case goodsEditRoute: case goodsEditRoute:
final GoodResponse good = settings.arguments! as GoodResponse; final GoodResponseEntity good = settings.arguments! as GoodResponseEntity;
return _getPageRoute( return _getPageRoute(
routeName: settings.name, routeName: settings.name,
viewToShow: GoodEdit( viewToShow: GoodEdit(

View File

@ -1,9 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:logger/logger.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/dialog_models.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/category_row_data.dart';
import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dialog_service.dart';
import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
@ -53,6 +51,28 @@ class _CategoryEditState extends State<CategoryEdit> {
super.dispose(); 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 @override
@ -83,7 +103,9 @@ class _CategoryEditState extends State<CategoryEdit> {
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0), const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0),
child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {}), child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {
save();
}),
), ),
if (widget.category.id != null) if (widget.category.id != null)
Padding( Padding(
@ -99,8 +121,10 @@ class _CategoryEditState extends State<CategoryEdit> {
'Вы уверены, что хотите удалить категорию?', 'Вы уверены, что хотите удалить категорию?',
confirmationTitle: 'Удалить', confirmationTitle: 'Удалить',
cancelTitle: 'Отмена'); cancelTitle: 'Отмена');
if(response.confirmed){
delete();
}
return response.confirmed;
}, },
isDanger: true, isDanger: true,
), ),

View File

@ -2,9 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.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/category_response.dart';
import 'package:satu/core/models/dictionary/category_response.dart';
import 'package:satu/core/models/dictionary/category_row_data.dart';
import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';

View File

@ -2,10 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.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/category_response.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/services/dictionary_service.dart'; import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
@ -27,7 +24,6 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
late TextEditingController _searchTextController; late TextEditingController _searchTextController;
final FocusNode _searchFocusNode = new FocusNode(); final FocusNode _searchFocusNode = new FocusNode();
static const _pageSize = 20; static const _pageSize = 20;
String query = ''; String query = '';
Timer? _debounce; Timer? _debounce;
@ -93,8 +89,13 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
int index) { int index) {
return DictionaryTile( return DictionaryTile(
key: Key('category_${category.id}'), key: Key('category_${category.id}'),
onPress: () => _navigatorService.push(categoryEditRoute, onPress: () async {
arguments: category), final dynamic result = await _navigatorService
.push(categoryEditRoute, arguments: category);
if (result != null && true == (result as bool)) {
_pagingController.refresh();
}
},
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -120,8 +121,8 @@ class _CategoryDictionaryViewState extends State<CategoryDictionaryView> {
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
elevation: 2, elevation: 2,
onPressed: () => locator<NavigatorService>() onPressed: () => _navigatorService.push(categoryEditRoute,
.push(categoryEditRoute, arguments: CategoryRowDao('', '', null)), arguments: CategoryResponse()),
child: const Icon( child: const Icon(
Icons.add_rounded, Icons.add_rounded,
size: 34.0, size: 34.0,

View File

@ -103,21 +103,37 @@ class _ContragentEditState extends State<ContragentEdit> {
controller: _controllerName, controller: _controllerName,
labelText: 'Наименование', labelText: 'Наименование',
placeholder: 'Введите наименование контрагента', placeholder: 'Введите наименование контрагента',
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controllerBinIin, controller: _controllerBinIin,
labelText: 'БИН/ИИН>', labelText: 'БИН/ИИН>',
placeholder: 'Введите БИН/ИИН', placeholder: 'Введите БИН/ИИН',
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controllerPhone, controller: _controllerPhone,
labelText: 'Телефон', labelText: 'Телефон',
placeholder: 'Введите номер телефона', placeholder: 'Введите номер телефона',
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controllerMail, controller: _controllerMail,
labelText: 'E-mail"', labelText: 'E-mail"',
placeholder: 'Введите электронную почту', placeholder: 'Введите электронную почту',
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputCheckBox('НДС', value: _isNds, labelText: 'Плательщик НДС', InputCheckBox('НДС', value: _isNds, labelText: 'Плательщик НДС',
onChanged: (value) { onChanged: (value) {

View File

@ -1,9 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.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/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/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
@ -88,7 +85,7 @@ class _ContragentsDictionaryViewState extends State<ContragentsDictionaryView> {
final dynamic result = await _navigatorService final dynamic result = await _navigatorService
.push(contragentEditRoute, arguments: entity); .push(contragentEditRoute, arguments: entity);
if (result != null && true == (result as bool)) { if (result != null && true == (result as bool)) {
//searchByField(''); _pagingController.refresh();
} }
}, },
child: Column( child: Column(

View File

@ -1,14 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:logger/logger.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/dialog_models.dart';
import 'package:satu/core/models/dictionary/good_response.dart'; import 'package:satu/core/models/dictionary/category/category_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/core/services/dialog_service.dart'; import 'package:satu/core/services/dialog_service.dart';
import 'package:satu/core/services/dictionary_service.dart'; import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
import 'package:satu/core/utils/logger.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/routes/route_names.dart';
import 'package:satu/shared/ui_helpers.dart'; import 'package:satu/shared/ui_helpers.dart';
import 'package:satu/widgets/bar/products_app_bar.dart'; import 'package:satu/widgets/bar/products_app_bar.dart';
@ -21,7 +21,7 @@ class GoodEdit extends StatefulWidget {
required this.good, required this.good,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
final GoodResponse good; final GoodResponseEntity good;
@override @override
_GoodEditState createState() => _GoodEditState(); _GoodEditState createState() => _GoodEditState();
@ -32,9 +32,18 @@ class _GoodEditState extends State<GoodEdit> {
final DictionaryService _dictionaryService = locator<DictionaryService>(); final DictionaryService _dictionaryService = locator<DictionaryService>();
final DialogService _dialogService = locator<DialogService>(); final DialogService _dialogService = locator<DialogService>();
final Logger log = getLogger('_GoodEditState'); 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; int? parentCategoryId;
@override @override
@ -42,35 +51,64 @@ class _GoodEditState extends State<GoodEdit> {
super.initState(); super.initState();
if (widget.good.categoryId != null) { if (widget.good.categoryId != null) {
parentCategoryId = widget.good.categoryId; parentCategoryId = widget.good.categoryId;
parentCategoryName = widget.good.categoryName ?? ''; parentCategoryName = widget.good.categoryName;
} }
_controller = TextEditingController(text: widget.good.name); _controllerArticle =
TextEditingController(text: widget.good.articul?.toString() ?? '');
//getAndStateCategoryName(parentCategoryId); _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 @override
void dispose() { void dispose() {
_controller.dispose(); _controllerArticle.dispose();
_controllerName.dispose();
_controllerPrice.dispose();
_controllerOptPrice.dispose();
_controllerBasePrice.dispose();
_controllerEan.dispose();
_controllerDescription.dispose();
super.dispose(); super.dispose();
} }
// Future<void> getAndStateCategoryName(int? id) async { void save() async {
// String name = ''; GoodResponseEntity good = widget.good;
// if (id == null) { good.name = _controllerName.text;
// } else if (id == 0) { good.price = parseNumeric(_controllerPrice.text);
// name = 'Корневая категория'; good.optPrice = parseNumeric(_controllerOptPrice.text);
// } else { good.basePrice = parseNumeric(_controllerBasePrice.text);
// final Category? category = await _dictionaryService.getCategoryById(id); good.ean13 = _controllerEan.text;
// if (category != null) { good.description = _controllerDescription.text;
// name = category.name; String? message = await _dictionaryService.saveGood(good);
// } if (message != null) {
// } _dialogService.showDialog(description: message);
// setState(() { } else {
// parentCategoryName = name; _navigatorService.pop(true);
// parentCategoryId = id; }
// }); }
// }
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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -88,52 +126,91 @@ class _GoodEditState extends State<GoodEdit> {
verticalSpaceSmall, verticalSpaceSmall,
InputField( InputField(
isReadOnly: true, isReadOnly: true,
controller: _controller, controller: _controllerArticle,
labelText: 'Номенклатурный номер', labelText: 'Номенклатурный номер',
placeholder: 'Не присвоен', placeholder: 'Не присвоен',
), ),
LineTile( LineTile(
parentCategoryName, parentCategoryName ?? '',
onTap: selectCategory, onTap: selectCategory,
labelText: 'Категория', labelText: 'Категория',
placeholder: 'Выберите категорию', placeholder: 'Выберите категорию',
), ),
verticalSpaceSmall, verticalSpaceSmall,
InputField( InputField(
controller: _controller, controller: _controllerName,
labelText: 'Наименование', labelText: 'Наименование',
placeholder: 'Введите наименование товара', placeholder: 'Введите наименование товара',
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controller, controller: _controllerPrice,
labelText: 'Розничная цена', labelText: 'Розничная цена',
placeholder: 'Введите розничную цену', placeholder: 'Введите розничную цену',
suffixText: '',
textInputType:
const TextInputType.numberWithOptions(decimal: true),
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controller, controller: _controllerOptPrice,
labelText: 'Оптовая цена', labelText: 'Оптовая цена',
placeholder: 'Введите оптовую цену', placeholder: 'Введите оптовую цену',
suffixText: '',
textInputType:
const TextInputType.numberWithOptions(decimal: true),
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controller, controller: _controllerBasePrice,
labelText: labelText:
'Закупочная цена для автоматически пополняемого товара', 'Закупочная цена для автоматически пополняемого товара',
placeholder: 'Введите закупочную цену', placeholder: 'Введите закупочную цену',
suffixText: '',
textInputType:
const TextInputType.numberWithOptions(decimal: true),
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controller, controller: _controllerEan,
labelText: 'EAN Штрих-код', labelText: 'EAN Штрих-код',
placeholder: 'Введите EAN', placeholder: 'Введите EAN',
textInputType:
const TextInputType.numberWithOptions(decimal: false),
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
InputField( InputField(
controller: _controller, controller: _controllerDescription,
labelText: 'Наименование', labelText: 'Описание',
placeholder: 'Введите наименование товара', placeholder: 'Введите описание товара',
multiline: true,
textInputType: TextInputType.multiline,
enterPressed: (){
FocusManager.instance.primaryFocus?.unfocus();
},
textInputAction: TextInputAction.done,
), ),
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0), const EdgeInsets.symmetric(horizontal: 45.0, vertical: 20.0),
child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {}), child: BusyButton(title: 'СОХРАНИТЬ', onPressed: () {
save();
}),
), ),
if (widget.good.id != null) if (widget.good.id != null)
Padding( Padding(
@ -150,7 +227,9 @@ class _GoodEditState extends State<GoodEdit> {
confirmationTitle: 'Удалить', confirmationTitle: 'Удалить',
cancelTitle: 'Отмена'); cancelTitle: 'Отмена');
return response.confirmed; if(response.confirmed){
delete();
}
}, },
isDanger: true, isDanger: true,
), ),
@ -164,8 +243,10 @@ class _GoodEditState extends State<GoodEdit> {
Future<void> selectCategory() async { Future<void> selectCategory() async {
final dynamic result = final dynamic result =
await _navigatorService.push(categorySelectViewRoute); await _navigatorService.push(categorySelectViewRoute);
if (result != null) { CategoryResponse? category = result as CategoryResponse?;
//getAndStateCategoryName(result as int); setState(() {
} parentCategoryId = category?.id;
parentCategoryName = category?.name;
});
} }
} }

View File

@ -3,11 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:satu/core/entity/category_entity.dart'; import 'package:satu/core/models/dictionary/good/good_response_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/services/dictionary_service.dart'; import 'package:satu/core/services/dictionary_service.dart';
import 'package:satu/core/services/navigator_service.dart'; import 'package:satu/core/services/navigator_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
@ -33,7 +29,7 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
String query = ''; String query = '';
Timer? _debounce; Timer? _debounce;
final PagingController<int, GoodResponse> _pagingController = final PagingController<int, GoodResponseEntity> _pagingController =
PagingController(firstPageKey: 1); PagingController(firstPageKey: 1);
@override @override
@ -100,7 +96,7 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
), ),
const ProductsTitleBarBar(title: 'Список товаров'), const ProductsTitleBarBar(title: 'Список товаров'),
Expanded( Expanded(
child: PagedListView<int, GoodResponse>.separated( child: PagedListView<int, GoodResponseEntity>.separated(
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
separatorBuilder: (BuildContext context, int index) { separatorBuilder: (BuildContext context, int index) {
return const Divider( return const Divider(
@ -109,18 +105,21 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
); );
}, },
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<GoodResponse>( builderDelegate: PagedChildBuilderDelegate<GoodResponseEntity>(
itemBuilder: itemBuilder:
(BuildContext context, GoodResponse good, int index) { (BuildContext context, GoodResponseEntity good, int index) {
return DictionaryTile( return DictionaryTile(
onPress: () { onPress: () async {
locator<NavigatorService>() final dynamic result = await _navigatorService
.push(goodsEditRoute, arguments: good); .push(goodsEditRoute, arguments: good);
if (result != null && true == (result as bool)) {
_pagingController.refresh();
}
}, },
child: ProductTitleWidget( child: ProductTitleWidget(
name: good.name, name: good.name,
categoryName: good.categoryName, categoryName: good.categoryName,
ean: good.ean, ean: good.ean13,
), ),
); );
}, },
@ -131,9 +130,13 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
elevation: 2, elevation: 2,
onPressed: () => onPressed: () async {
locator<NavigatorService>() final dynamic result = await _navigatorService.push(goodsEditRoute,
.push(goodsEditRoute, arguments: GoodRowDao('', '')), arguments: GoodResponseEntity());
if (result != null && true == (result as bool)) {
_pagingController.refresh();
}
},
child: const Icon( child: const Icon(
Icons.add_rounded, Icons.add_rounded,
size: 34.0, size: 34.0,
@ -148,7 +151,7 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
} }
Future<void> _fetchData(int pageKey, int perPage, String? query) async { 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); page: pageKey, query: query, perpage: perPage);
final isLastPage = newItems.length < _pageSize; final isLastPage = newItems.length < _pageSize;

View File

@ -127,7 +127,7 @@ class _InputFieldState extends State<InputField> {
keyboardType: widget.textInputType, keyboardType: widget.textInputType,
focusNode: widget.fieldFocusNode, focusNode: widget.fieldFocusNode,
textInputAction: widget.textInputAction, textInputAction: widget.textInputAction,
maxLines: widget.multiline ? null : 1, maxLines: widget.multiline ? 5 : 1,
onChanged: widget.onChanged, onChanged: widget.onChanged,
initialValue: widget.initialValue, initialValue: widget.initialValue,
inputFormatters: inputFormatters: