stocks
parent
01d6e2d808
commit
b5f9291116
|
|
@ -13,8 +13,11 @@ class BuyItemResponse {
|
|||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.unitPrice,
|
||||
required this.name,
|
||||
this.deletedAt,
|
||||
this.refOkeiId,
|
||||
this.ean13,
|
||||
this.category
|
||||
});
|
||||
|
||||
int id;
|
||||
|
|
@ -34,6 +37,9 @@ class BuyItemResponse {
|
|||
DateTime? deletedAt;
|
||||
@JsonKey(name: 'unit_price')
|
||||
double unitPrice;
|
||||
String name;
|
||||
String? ean13;
|
||||
String? category;
|
||||
|
||||
factory BuyItemResponse.fromJson(Map<String, dynamic> json) => _$BuyItemResponseFromJson(json);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,13 @@ BuyItemResponse _$BuyItemResponseFromJson(Map<String, dynamic> json) =>
|
|||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
unitPrice: (json['unit_price'] as num).toDouble(),
|
||||
name: json['name'] as String,
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
refOkeiId: json['ref_okei_id'] as int?,
|
||||
ean13: json['ean13'] as String?,
|
||||
category: json['category'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BuyItemResponseToJson(BuyItemResponse instance) =>
|
||||
|
|
@ -34,4 +37,7 @@ Map<String, dynamic> _$BuyItemResponseToJson(BuyItemResponse instance) =>
|
|||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'unit_price': instance.unitPrice,
|
||||
'name': instance.name,
|
||||
'ean13': instance.ean13,
|
||||
'category': instance.category,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class BuyInvoiceResponse {
|
|||
required this.eaccContragentId,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.name,
|
||||
this.deletedAt,
|
||||
this.summ,
|
||||
});
|
||||
|
|
@ -43,6 +44,7 @@ class BuyInvoiceResponse {
|
|||
DateTime updatedAt;
|
||||
@JsonKey(name: 'deleted_at')
|
||||
DateTime? deletedAt;
|
||||
String name;
|
||||
|
||||
factory BuyInvoiceResponse.fromJson(Map<String, dynamic> json) => _$BuyInvoiceResponseFromJson(json);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ BuyInvoiceResponse _$BuyInvoiceResponseFromJson(Map<String, dynamic> json) =>
|
|||
eaccContragentId: json['eacc_contragent_id'] as int,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
name: json['name'] as String,
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
|
|
@ -34,4 +35,5 @@ Map<String, dynamic> _$BuyInvoiceResponseToJson(BuyInvoiceResponse instance) =>
|
|||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'name': instance.name,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
part 'stock_response.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class StockResponse {
|
||||
StockResponse({
|
||||
required this.articul,
|
||||
required this.ean13,
|
||||
required this.eaccGoodId,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.cnt,
|
||||
required this.katName,
|
||||
});
|
||||
|
||||
int articul;
|
||||
String ean13;
|
||||
@JsonKey(name: 'eacc_good_id')
|
||||
int eaccGoodId;
|
||||
String name;
|
||||
double price;
|
||||
double cnt;
|
||||
String katName;
|
||||
|
||||
factory StockResponse.fromJson(Map<String, dynamic> json) => _$StockResponseFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$StockResponseToJson(this);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'stock_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
StockResponse _$StockResponseFromJson(Map<String, dynamic> json) =>
|
||||
StockResponse(
|
||||
articul: json['articul'] as int,
|
||||
ean13: json['ean13'] as String,
|
||||
eaccGoodId: json['eacc_good_id'] as int,
|
||||
name: json['name'] as String,
|
||||
price: (json['price'] as num).toDouble(),
|
||||
cnt: (json['cnt'] as num).toDouble(),
|
||||
katName: json['katName'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$StockResponseToJson(StockResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'articul': instance.articul,
|
||||
'ean13': instance.ean13,
|
||||
'eacc_good_id': instance.eaccGoodId,
|
||||
'name': instance.name,
|
||||
'price': instance.price,
|
||||
'cnt': instance.cnt,
|
||||
'katName': instance.katName,
|
||||
};
|
||||
|
|
@ -2,6 +2,7 @@ import 'package:redux/redux.dart';
|
|||
import 'package:meta/meta.dart';
|
||||
import 'package:redux_thunk/redux_thunk.dart';
|
||||
import 'package:satu/core/models/auth/auth_response.dart';
|
||||
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import 'package:satu/core/redux/state/user_state.dart';
|
||||
import 'package:satu/core/services/api_service.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
|
|
@ -13,8 +14,8 @@ import '../store.dart';
|
|||
|
||||
@immutable
|
||||
class SetUserStateAction {
|
||||
|
||||
SetUserStateAction(this.userState);
|
||||
|
||||
final UserState userState;
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +48,12 @@ ThunkAction<AppState> authenticate(String email, String password) {
|
|||
};
|
||||
}
|
||||
|
||||
ThunkAction<AppState> setDefaultContragent(ContragentResponseEntity? entity) {
|
||||
return (Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(defaultContragent: entity)));
|
||||
};
|
||||
}
|
||||
|
||||
ThunkAction<AppState> authenticateByToken(String token) {
|
||||
return (Store<AppState> store) async {
|
||||
store.dispatch(SetUserStateAction(UserState(isLoading: true)));
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@ UserState userReducer(UserState prevState, SetUserStateAction action) {
|
|||
isError: payload.isError,
|
||||
isLoading: payload.isLoading,
|
||||
auth: payload.auth,
|
||||
defaultContragent: payload.defaultContragent,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,51 +1,52 @@
|
|||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:satu/core/models/auth/auth_response.dart';
|
||||
|
||||
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
|
||||
@immutable
|
||||
class UserState {
|
||||
|
||||
factory UserState.initial(UserState? payload) => UserState(
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
auth: payload?.auth ?? (AuthResponse()..operation=false),
|
||||
auth: payload?.auth ?? (AuthResponse()..operation = false),
|
||||
defaultContragent:
|
||||
payload?.defaultContragent ?? ContragentResponseEntity(),
|
||||
);
|
||||
|
||||
UserState({this.isError, this.isLoading, this.auth, this.defaultContragent});
|
||||
|
||||
UserState(
|
||||
{this.isError,
|
||||
this.isLoading,
|
||||
this.auth,
|
||||
});
|
||||
final bool? isError;
|
||||
final bool? isLoading;
|
||||
final AuthResponse? auth;
|
||||
final ContragentResponseEntity? defaultContragent;
|
||||
|
||||
UserState copyWith({
|
||||
required bool? isError,
|
||||
required bool? isLoading,
|
||||
required AuthResponse? auth
|
||||
}) {
|
||||
UserState copyWith(
|
||||
{required bool? isError,
|
||||
required bool? isLoading,
|
||||
required AuthResponse? auth,
|
||||
required ContragentResponseEntity? defaultContragent}) {
|
||||
return UserState(
|
||||
isError: isError ?? this.isError,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
auth: auth ?? this.auth,
|
||||
);
|
||||
isError: isError ?? this.isError,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
auth: auth ?? this.auth,
|
||||
defaultContragent: defaultContragent ?? this.defaultContragent);
|
||||
}
|
||||
|
||||
static UserState? fromJson(dynamic json) {
|
||||
return json != null
|
||||
? UserState(
|
||||
auth: AuthResponse.fromMap(json['auth']),
|
||||
)
|
||||
defaultContragent: json['defaultContragent'] == null
|
||||
? null
|
||||
: ContragentResponseEntity.fromJson(json['defaultContragent']),
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
dynamic toJson() {
|
||||
return {
|
||||
'auth': auth != null ? auth!.toJson() : null,
|
||||
'defaultContragent':
|
||||
defaultContragent != null ? defaultContragent!.toJson() : null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,13 +47,6 @@ class ApiService extends BaseService {
|
|||
|
||||
final response = await http.post(Uri.https(host, url),
|
||||
body: jsonEncode(requestBody), headers: headers);
|
||||
if (requestBody != null) {
|
||||
// log.i(host);
|
||||
// log.i(url);
|
||||
// log.i(headers);
|
||||
//log.i(jsonEncode(requestBody));
|
||||
//log.i(jsonEncode(response.body));
|
||||
}
|
||||
return response.body;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +136,24 @@ class ApiService extends BaseService {
|
|||
return result;
|
||||
}
|
||||
|
||||
Future<ResponseOriginal> postRequestOriginal(String target,
|
||||
{Map<String, dynamic>? requestBody}) async {
|
||||
ResponseOriginal result;
|
||||
try {
|
||||
final Map<String, String> headers = <String, String>{
|
||||
HttpHeaders.authorizationHeader: 'Bearer $token'
|
||||
};
|
||||
|
||||
final String response =
|
||||
await _post(target, header: headers, requestBody: requestBody);
|
||||
result = ResponseOriginal.fromJson(json.decode(response));
|
||||
} catch (e, stack) {
|
||||
log.e('postRequest', e, stack);
|
||||
result = ResponseOriginal()..message = e.toString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<ResponseEntity> dictionarySave(
|
||||
String target, Map<String, dynamic>? body) async {
|
||||
ResponseEntity response;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:satu/core/base/base_service.dart';
|
||||
import 'package:satu/core/models/but_item/buy_item_response.dart';
|
||||
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import 'package:satu/core/services/api_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
|
||||
|
|
@ -15,6 +17,10 @@ class BuyService extends BaseService {
|
|||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'page': page,
|
||||
'perpage': perpage,
|
||||
'order' : {
|
||||
'col': 'doc_number',
|
||||
'desc': true
|
||||
}
|
||||
};
|
||||
|
||||
ResponseEntity categories = await _api.postRequest('/general_purchases_get',
|
||||
|
|
@ -42,8 +48,6 @@ class BuyService extends BaseService {
|
|||
'perpage': perpage,
|
||||
'id': id
|
||||
};
|
||||
log.i(requestBody);
|
||||
|
||||
ResponseEntity categories = await _api.postRequest('/general_purchases_get_items',
|
||||
requestBody: requestBody);
|
||||
if (categories.original.items != null &&
|
||||
|
|
@ -69,7 +73,6 @@ class BuyService extends BaseService {
|
|||
'price': price,
|
||||
'cnt': count
|
||||
};
|
||||
log.i(requestBody);
|
||||
|
||||
ResponseEntity response = await _api.postRequest('/general_purchases_edit_item',
|
||||
requestBody: requestBody);
|
||||
|
|
@ -86,7 +89,6 @@ class BuyService extends BaseService {
|
|||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'id': id,
|
||||
};
|
||||
log.i(requestBody);
|
||||
|
||||
ResponseEntity response = await _api.postRequest('/general_purchases_delete_item',
|
||||
requestBody: requestBody);
|
||||
|
|
@ -105,7 +107,6 @@ class BuyService extends BaseService {
|
|||
'eacc_good_id': goodId,
|
||||
'id': invoiceId,
|
||||
};
|
||||
log.i(requestBody);
|
||||
|
||||
ResponseEntity response = await _api.postRequest('/general_purchases_add_item',
|
||||
requestBody: requestBody);
|
||||
|
|
@ -116,4 +117,40 @@ class BuyService extends BaseService {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<bool> confirmInvoice(int invoiceId) async {
|
||||
bool result = false;
|
||||
try {
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'id': invoiceId,
|
||||
};
|
||||
|
||||
ResponseEntity response = await _api.postRequest('/general_purchases_confirm',
|
||||
requestBody: requestBody);
|
||||
result = response.original.status == 'success';
|
||||
log.i(response.toJson());
|
||||
} catch (e, stack) {
|
||||
log.e('getList', e, stack);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<bool> createBuy(ContragentResponseEntity contragent, DateTime date) async {
|
||||
bool result = false;
|
||||
try {
|
||||
DateFormat formatter = DateFormat('yyyy-MM-dd');
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'eacc_contragent_id': contragent.id,
|
||||
'invoice_date': formatter.format(date),
|
||||
};
|
||||
log.i('requestBody', requestBody);
|
||||
ResponseEntity response = await _api.postRequest('/general_purchases_add',
|
||||
requestBody: requestBody);
|
||||
log.i('response', response.toJson());
|
||||
result = response.original.status == 'success';
|
||||
} catch (e, stack) {
|
||||
log.e('getList', e, stack);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,6 @@ class DictionaryService extends BaseService {
|
|||
final ApiService _api = locator<ApiService>();
|
||||
final DbService _db = locator<DbService>();
|
||||
|
||||
|
||||
|
||||
Category categoryResponseToCategory(CategoryResponse response) {
|
||||
return Category()
|
||||
..id = response.id
|
||||
|
|
@ -84,7 +82,7 @@ class DictionaryService extends BaseService {
|
|||
'val': categoryId
|
||||
};
|
||||
List<GoodResponseEntity> responses =
|
||||
await getGoods(page: 1, perpage: 100, filter: filter);
|
||||
await getGoods(page: 1, perpage: 100, filter: [filter]);
|
||||
for (final GoodResponseEntity response in responses) {
|
||||
final Good good = goodResponseToGood(response);
|
||||
list.add(good);
|
||||
|
|
@ -95,24 +93,38 @@ class DictionaryService extends BaseService {
|
|||
return list;
|
||||
}
|
||||
|
||||
Future<List<Good>> getGoodsByNameOrEan(String query) async {
|
||||
Future<List<Good>> getGoodsByNameOrEan(String query, { bool onlyEan = false}) async {
|
||||
final List<Good> list = [];
|
||||
try {
|
||||
final int? appCompanyId = Redux.store?.state.userState?.auth?.companyId;
|
||||
String where =
|
||||
'( $GoodColumnAppCompanyId = ? and $GoodColumnName like ? ) ';
|
||||
final List args = [appCompanyId, '%$query%'];
|
||||
if (_isNumericInt(query) && query.length >= 8) {
|
||||
where += ' or $GoodColumnEan like ?';
|
||||
args.add('${int.parse(query).toString()}%');
|
||||
dynamic filter = [
|
||||
{
|
||||
'col': 'name',
|
||||
'action': 'like',
|
||||
'val': query,
|
||||
},
|
||||
{
|
||||
'col': 'ean13',
|
||||
'action': 'like',
|
||||
'val': query,
|
||||
}
|
||||
];
|
||||
if (onlyEan) {
|
||||
filter = [
|
||||
{
|
||||
'col': 'ean13',
|
||||
'action': 'equals',
|
||||
'val': query,
|
||||
}
|
||||
];
|
||||
}
|
||||
final List<Map<String, dynamic>> elements =
|
||||
await _db.queryRowsWithWhere(goodTableName, where, args);
|
||||
for (final Map<String, dynamic> element in elements) {
|
||||
list.add(Good.fromMap(element));
|
||||
List<GoodResponseEntity> responses =
|
||||
await getGoods(page: 1, perpage: 100, filter: filter);
|
||||
for (final GoodResponseEntity response in responses) {
|
||||
final Good good = goodResponseToGood(response);
|
||||
list.add(good);
|
||||
}
|
||||
} catch (e, stack) {
|
||||
log.e('getGoodsByCategoryId', e, stack);
|
||||
log.e('getGoods', e, stack);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
@ -172,13 +184,14 @@ class DictionaryService extends BaseService {
|
|||
}
|
||||
|
||||
Future<List<GoodResponseEntity>> getGoods(
|
||||
{required int page, required int perpage, dynamic filter}) async {
|
||||
{required int page, required int perpage, dynamic filter,bool orGate = false}) async {
|
||||
List<GoodResponseEntity> list = [];
|
||||
try {
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'page': page,
|
||||
'perpage': perpage,
|
||||
'filter': [filter]
|
||||
'filter': filter,
|
||||
'or_gate': orGate
|
||||
};
|
||||
|
||||
ResponseEntity categories =
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@ import 'package:satu/core/models/flow/sell_return/sell_return_request.dart';
|
|||
import 'package:satu/core/models/flow/transaction_state.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/state/sell_state.dart';
|
||||
import 'package:satu/core/redux/state/user_state.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import 'api_service.dart';
|
||||
import 'db_service.dart';
|
||||
import 'dialog_service.dart';
|
||||
|
|
@ -30,6 +32,7 @@ class SellService extends BaseService {
|
|||
{double card = 0, double nal = 0, double total = 0}) async {
|
||||
final SellRequest request = SellRequest();
|
||||
final SellState sellState = Redux.store!.state.sellState!;
|
||||
final UserState userState = Redux.store!.state.userState!;
|
||||
final TransactionState transactionState = sellState.transactionState!;
|
||||
final List<ProductDao> items = sellState.items!;
|
||||
for (final ProductDao item in items) {
|
||||
|
|
@ -40,10 +43,12 @@ class SellService extends BaseService {
|
|||
request.invoiceId = transactionState.uuid;
|
||||
request.section = transactionState.sectionName;
|
||||
request.contragent = transactionState.contragentName;
|
||||
ContragentResponseEntity? contragent = userState.defaultContragent;
|
||||
final OperatorBean operator = OperatorBean()
|
||||
..name = 'operator'
|
||||
..code = 1;
|
||||
request.operator = operator;
|
||||
request.contragent = contragent?.name;
|
||||
final SellResponse response = await _api.sell(request);
|
||||
if (response.operation == false) {
|
||||
_dialogService.showDialog(description: response.message);
|
||||
|
|
@ -125,7 +130,6 @@ class SellService extends BaseService {
|
|||
data.nal = nal;
|
||||
data.total = total;
|
||||
transaction.data = jsonEncode(data.toMap());
|
||||
log.i(jsonEncode(data.toMap()));
|
||||
await _db.update(transactionTableName, transaction.toMap());
|
||||
return transaction.id;
|
||||
}
|
||||
|
|
@ -157,7 +161,6 @@ class SellService extends BaseService {
|
|||
data.nal = nal;
|
||||
data.total = total;
|
||||
transaction.data = jsonEncode(data.toMap());
|
||||
log.i(jsonEncode(data.toMap()));
|
||||
return await _db.insert(transactionTableName, transaction.toMap());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:satu/core/base/base_service.dart';
|
||||
import 'package:satu/core/models/stock/stock_response.dart';
|
||||
|
||||
import '../models/response/response_entity.dart';
|
||||
import '../utils/locator.dart';
|
||||
import 'api_service.dart';
|
||||
|
||||
class StockService extends BaseService {
|
||||
final ApiService _api = locator<ApiService>();
|
||||
|
||||
Future<List<StockResponse>> getList(
|
||||
{required int page, required int perpage, String? query}) async {
|
||||
List<StockResponse> list = [];
|
||||
try {
|
||||
final Map<String, dynamic> requestBody = <String, dynamic>{
|
||||
'page': page,
|
||||
'perpage': perpage,
|
||||
'search': query ?? ''
|
||||
};
|
||||
|
||||
ResponseOriginal categories = await _api.postRequestOriginal('/get_stock_balance',
|
||||
requestBody: requestBody);
|
||||
if (categories.data != null &&
|
||||
categories.data!.isNotEmpty) {
|
||||
for (final dynamic map in categories.data!) {
|
||||
final StockResponse item =
|
||||
StockResponse.fromJson(map);
|
||||
list.add(item);
|
||||
}
|
||||
}
|
||||
} catch (e, stack) {
|
||||
log.e('getList', e, stack);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import 'package:satu/core/services/dialog_service.dart';
|
|||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
import 'package:satu/core/services/inventarization_service.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
import 'package:satu/core/services/stocks_service.dart';
|
||||
|
||||
import 'logger.dart';
|
||||
|
||||
|
|
@ -39,5 +40,7 @@ class LocatorInjector {
|
|||
_log.d('Initializing InventarizationService Service');
|
||||
locator.registerLazySingleton<InventarizationService>(
|
||||
() => InventarizationService());
|
||||
_log.d('Initializing StockService Service');
|
||||
locator.registerLazySingleton<StockService>(() => StockService());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ const String inventarizationEditRoute = 'inventarizationEditRoute';
|
|||
|
||||
//buy
|
||||
const String buyEditRoute = 'buyEditRoute';
|
||||
const String buyAddRoute = 'buyAddRoute';
|
||||
|
||||
// setting - ble printer
|
||||
const String settingPrinterBluetoothViewRoute = 'SettingPrinterBluetoothView';
|
||||
|
|
|
|||
|
|
@ -14,15 +14,16 @@ import 'package:satu/views/settings/printer_bluetooth/printer_encoding_select.da
|
|||
import 'package:satu/views/settings/printer_bluetooth/printer_paper_size_select.dart';
|
||||
import 'package:satu/views/settings/printer_bluetooth/printer_select.dart';
|
||||
import 'package:satu/views/settings/printer_bluetooth/printer_view.dart';
|
||||
import 'package:satu/views/work/tabs/buy/buy_add.dart';
|
||||
import 'package:satu/views/work/tabs/buy/buy_edit.dart';
|
||||
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||
import 'package:satu/views/work/views/add_product/add_product_view.dart';
|
||||
import 'package:satu/views/work/views/contragent/select_contragent_view.dart';
|
||||
import 'package:satu/views/work/views/payment/payment_view.dart';
|
||||
import 'package:satu/views/work/views/receipt/receipt_view.dart';
|
||||
import 'package:satu/views/work/views/select_by_scan/add_by_barcode_view.dart';
|
||||
import 'package:satu/views/work/work_view.dart';
|
||||
|
||||
import '../core/models/inventarization/response/inventarization_response.dart';
|
||||
import '../views/work/views/select_contragent/select_contragent_view.dart';
|
||||
import '../views/work/views/select_product/add_product_view.dart';
|
||||
import './route_names.dart';
|
||||
|
||||
Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
|
|
@ -46,12 +47,12 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
|||
case addProductViewRoute:
|
||||
return _getPageRoute(
|
||||
routeName: settings.name,
|
||||
viewToShow: AddProductView(),
|
||||
viewToShow: SelectProductView(),
|
||||
);
|
||||
case addByBarcodeViewRoute:
|
||||
return _getPageRoute(
|
||||
routeName: settings.name,
|
||||
viewToShow: const AddByBarcodeView(),
|
||||
viewToShow: const SelectByScanView(),
|
||||
);
|
||||
case settingPrinterBluetoothViewRoute:
|
||||
return _getPageRoute(
|
||||
|
|
@ -137,6 +138,11 @@ Route<dynamic> generateRoute(RouteSettings settings) {
|
|||
invoice: invoice,
|
||||
),
|
||||
);
|
||||
case buyAddRoute:
|
||||
return _getPageRoute(
|
||||
routeName: settings.name,
|
||||
viewToShow: BuyAddView(),
|
||||
);
|
||||
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ class _GoodsDictionaryViewState extends State<GoodsDictionaryView> {
|
|||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<GoodResponseEntity> newItems = await _dictionaryService.getGoods(
|
||||
page: pageKey,
|
||||
filter: {'col': 'name', 'action': 'like', 'val': query ?? ''},
|
||||
perpage: perPage);
|
||||
filter: [{'col': 'name', 'action': 'like', 'val': query ?? ''}],
|
||||
perpage: perPage, orGate: true);
|
||||
|
||||
final isLastPage = newItems.length < _pageSize;
|
||||
if (isLastPage) {
|
||||
|
|
|
|||
|
|
@ -108,6 +108,14 @@ class _InventarizationEditViewState extends State<InventarizationEditView> {
|
|||
},
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<GoodInventarization>(
|
||||
noItemsFoundIndicatorBuilder: (BuildContext context) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'Необходимо добавить товар',
|
||||
style: textGray11Style,
|
||||
),
|
||||
);
|
||||
},
|
||||
itemBuilder: (BuildContext context, GoodInventarization item,
|
||||
int index) {
|
||||
return GoodInventarizationListItem(
|
||||
|
|
@ -199,8 +207,25 @@ class _InventarizationEditViewState extends State<InventarizationEditView> {
|
|||
final dynamic result = await _nav.push(addByBarcodeViewRoute);
|
||||
if (result != null) {
|
||||
final List<Good> goods = await locator<DictionaryService>()
|
||||
.getGoodsByNameOrEan(result as String);
|
||||
if (goods.isNotEmpty) {}
|
||||
.getGoodsByNameOrEan(result as String, onlyEan: true);
|
||||
if (goods.isNotEmpty) {
|
||||
final Good good = goods.first;
|
||||
bool result = await _service
|
||||
.addGoodToList(widget.item.id, good.id);
|
||||
if (result) {
|
||||
_pagingController.refresh();
|
||||
} else {
|
||||
_dialogService.showDialog(
|
||||
description:
|
||||
'Товара отсутсвует в остатке или ранее не'
|
||||
' использователся в системе',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_dialogService.showDialog(
|
||||
description: 'Товар не найден',
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Icon(Icons.qr_code_rounded, size: 30, color: whiteColor),
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:satu/core/models/dialog_models.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
import 'package:satu/core/services/inventarization_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/shared_styles.dart';
|
||||
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||
|
||||
import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||
|
||||
class GoodInventarizationListItem extends StatefulWidget {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import 'package:satu/views/work/work_view.dart';
|
|||
import 'package:satu/widgets/drawer/app_drawer.dart';
|
||||
|
||||
import '../dictionaries/contragents/contragents_view.dart';
|
||||
import '../stocks/stocks_view.dart';
|
||||
|
||||
class MainView extends StatefulWidget {
|
||||
@override
|
||||
|
|
@ -30,6 +31,7 @@ class _MainViewState extends State<MainView> {
|
|||
final _contragentDictView = ContragentsDictionaryView();
|
||||
final _analyticsView = const AnalyticsView();
|
||||
final _inventarizationView = InventarizationView();
|
||||
final _stocksView = StocksView();
|
||||
|
||||
Widget _body(Type viewClass) {
|
||||
if(viewClass == WorkView) {
|
||||
|
|
@ -53,6 +55,9 @@ class _MainViewState extends State<MainView> {
|
|||
if(viewClass == AnalyticsView) {
|
||||
return _analyticsView;
|
||||
}
|
||||
if(viewClass == StocksView) {
|
||||
return _stocksView;
|
||||
}
|
||||
return _workView;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:satu/core/models/inventarization/response/inventarization_response.dart';
|
||||
import 'package:satu/core/models/stock/stock_response.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
import 'package:satu/core/services/stocks_service.dart';
|
||||
import 'package:satu/views/inventarization/widget/good_inventarization_list_item.dart';
|
||||
import 'package:satu/views/stocks/widget/stock_tile.dart';
|
||||
|
||||
import '../../../core/entity/goods_entity.dart';
|
||||
import '../../../core/models/inventarization/good_item/good_item.dart';
|
||||
import '../../../core/services/dictionary_service.dart';
|
||||
import '../../../core/services/inventarization_service.dart';
|
||||
import '../../../core/services/navigator_service.dart';
|
||||
import '../../../core/utils/locator.dart';
|
||||
import '../../../routes/route_names.dart';
|
||||
import '../../../shared/app_colors.dart';
|
||||
import '../../../shared/shared_styles.dart';
|
||||
import '../../../shared/ui_helpers.dart';
|
||||
import '../../../widgets/bar/products_app_bar.dart';
|
||||
import '../../widgets/fields/input_field.dart';
|
||||
|
||||
class StocksView extends StatefulWidget {
|
||||
const StocksView({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StocksView> createState() => _StocksViewState();
|
||||
}
|
||||
|
||||
class _StocksViewState extends State<StocksView> {
|
||||
final StockService _service = locator<StockService>();
|
||||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
String query = '';
|
||||
Timer? _debounce;
|
||||
|
||||
static const _pageSize = 20;
|
||||
bool _isLastPage = false;
|
||||
|
||||
final PagingController<int, StockResponse> _pagingController =
|
||||
PagingController(firstPageKey: 1);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchTextController = TextEditingController();
|
||||
_searchTextController.addListener(() {
|
||||
setState(() {
|
||||
query = _searchTextController.text;
|
||||
});
|
||||
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||
_pagingController.refresh();
|
||||
});
|
||||
});
|
||||
|
||||
_pagingController.addPageRequestListener((pageKey) {
|
||||
_fetchData(pageKey, _pageSize, query);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
;
|
||||
_debounce?.cancel();
|
||||
_pagingController.dispose();
|
||||
_searchTextController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: const ProductsAppBar(
|
||||
title: 'Остатки',
|
||||
drawerShow: true,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
InputField(
|
||||
placeholder: 'Поиск по наименованию товара или штрих-код',
|
||||
search: true,
|
||||
controller: _searchTextController,
|
||||
fieldFocusNode: _searchFocusNode,
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15.0),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Text(
|
||||
'Список товара',
|
||||
style: textGray11Style,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'Количество',
|
||||
style: textGray11Style,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
'Сумма',
|
||||
style: textGray11Style,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
verticalSpaceSmall,
|
||||
Expanded(
|
||||
child: PagedListView<int, StockResponse>.separated(
|
||||
//physics: const BouncingScrollPhysics(),
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Divider(
|
||||
height: 1.0,
|
||||
color: disableColor,
|
||||
);
|
||||
},
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<StockResponse>(
|
||||
noItemsFoundIndicatorBuilder: (BuildContext context) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'В данном списке нет товаров',
|
||||
style: textGray11Style,
|
||||
),
|
||||
);
|
||||
},
|
||||
itemBuilder:
|
||||
(BuildContext context, StockResponse item, int index) {
|
||||
return StockTile(
|
||||
key: Key(
|
||||
'good_stock_${item.eaccGoodId}',
|
||||
),
|
||||
name: item.name,
|
||||
categoryName: item.katName,
|
||||
count: item.cnt,
|
||||
price: item.price,
|
||||
ean: item.ean13,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<StockResponse> newItems = await _service.getList(
|
||||
page: pageKey,
|
||||
perpage: perPage,
|
||||
query: query,
|
||||
);
|
||||
_isLastPage = newItems.length < _pageSize;
|
||||
|
||||
if (_isLastPage) {
|
||||
_pagingController.appendLastPage(newItems);
|
||||
} else {
|
||||
final nextPageKey = pageKey + 1;
|
||||
_pagingController.appendPage(newItems, nextPageKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
|
||||
import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||
|
||||
class StockTile extends StatefulWidget {
|
||||
const StockTile({
|
||||
required Key key,
|
||||
required this.price,
|
||||
required this.count,
|
||||
this.name = '',
|
||||
this.ean,
|
||||
this.categoryName,
|
||||
|
||||
}) : super(key: key);
|
||||
final String name;
|
||||
final String? ean;
|
||||
final String? categoryName;
|
||||
final double price;
|
||||
final double count;
|
||||
|
||||
|
||||
|
||||
@override
|
||||
_StockTileState createState() =>
|
||||
_StockTileState();
|
||||
}
|
||||
|
||||
class _StockTileState
|
||||
extends State<StockTile> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
key: widget.key!,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0),
|
||||
title: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: ProductTitleWidget(
|
||||
name: widget.name,
|
||||
ean: widget.ean,
|
||||
categoryName: widget.categoryName,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
formatDecimal(widget.count),
|
||||
style: const TextStyle(fontSize: 12, color: textColor),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
formatDecimal(widget.price),
|
||||
style: const TextStyle(fontSize: 12, color: textColor),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)),
|
||||
],
|
||||
),
|
||||
tileColor: whiteColor,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import 'package:satu/widgets/fields/line_tile.dart';
|
||||
|
||||
import '../../../../core/services/buy_service.dart';
|
||||
import '../../../../core/services/navigator_service.dart';
|
||||
import '../../../../core/utils/locator.dart';
|
||||
import '../../../../routes/route_names.dart';
|
||||
import '../../../../widgets/bar/products_app_bar.dart';
|
||||
import '../../../../widgets/buttons/busy_button.dart';
|
||||
|
||||
class BuyAddView extends StatefulWidget {
|
||||
const BuyAddView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<BuyAddView> createState() => _BuyAddViewState();
|
||||
}
|
||||
|
||||
class _BuyAddViewState extends State<BuyAddView> {
|
||||
ContragentResponseEntity? _contragent;
|
||||
DateTime _date = DateTime.now();
|
||||
final BuyService _service = locator<BuyService>();
|
||||
DateFormat _dateFormat = DateFormat('dd.MM.yyyy');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: const ProductsAppBar(
|
||||
title: 'Новая накладная покупки',
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
LineTile(
|
||||
key: const Key('BuyAddView_Contragent'),
|
||||
_contragent?.name ?? 'Выберите контрагента',
|
||||
onTap: () async {
|
||||
ContragentResponseEntity? entity =
|
||||
await locator<NavigatorService>()
|
||||
.push(contragentSelectViewRoute)
|
||||
as ContragentResponseEntity?;
|
||||
if (entity != null) {
|
||||
setState(() {
|
||||
_contragent = entity;
|
||||
});
|
||||
}
|
||||
},
|
||||
labelText: 'Контрагент',
|
||||
),
|
||||
LineTile(
|
||||
key: const Key('BuyAddView_Date'),
|
||||
_dateFormat.format(_date),
|
||||
onTap: () async {
|
||||
|
||||
DateTime? pickedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: DateTime.now(), //get today's date
|
||||
firstDate:DateTime(2000), //DateTime.now() - not to allow to choose before today.
|
||||
lastDate: DateTime(2101)
|
||||
);
|
||||
if (pickedDate != null) {
|
||||
setState(() {
|
||||
_date = pickedDate;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
labelText: 'Дата накладной',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 45, vertical: 30),
|
||||
child: BusyButton(
|
||||
title: 'СОЗДАТЬ',
|
||||
busy: false,
|
||||
onPressed: () async {
|
||||
|
||||
if (_contragent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool result = await _service.createBuy(_contragent!, _date);
|
||||
if (result) {
|
||||
locator<NavigatorService>().pop(result);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@ import 'dart:developer';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:satu/core/models/but_item/buy_item_response.dart';
|
||||
import 'package:satu/core/models/dialog_models.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
import 'package:satu/shared/shared_styles.dart';
|
||||
import 'package:satu/views/work/tabs/buy/component/product_buy_tile.dart';
|
||||
|
||||
|
||||
import '../../../../core/entity/goods_entity.dart';
|
||||
import '../../../../core/models/buy_invoice/buy_invoice_response.dart';
|
||||
import '../../../../core/services/buy_service.dart';
|
||||
|
|
@ -34,10 +35,11 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
static const _pageSize = 20;
|
||||
|
||||
final PagingController<int, BuyItemResponse> _pagingController =
|
||||
PagingController(firstPageKey: 1);
|
||||
PagingController(firstPageKey: 1);
|
||||
|
||||
bool editable = false;
|
||||
|
||||
bool itemsExist = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -46,7 +48,7 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
_fetchData(pageKey, _pageSize);
|
||||
});
|
||||
log('refBuyInvoiceStatusId: ${widget.invoice.refBuyInvoiceStatusId}');
|
||||
if(widget.invoice.refBuyInvoiceStatusId == 1){
|
||||
if (widget.invoice.refBuyInvoiceStatusId == 1) {
|
||||
editable = true;
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +57,6 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
|
||||
_pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -79,15 +80,23 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
},
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<BuyItemResponse>(
|
||||
itemBuilder: (BuildContext context, BuyItemResponse item,
|
||||
int index) {
|
||||
noItemsFoundIndicatorBuilder: (BuildContext context) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'Необходимо добавить товар',
|
||||
style: textGray11Style,
|
||||
),
|
||||
);
|
||||
},
|
||||
itemBuilder:
|
||||
(BuildContext context, BuyItemResponse item, int index) {
|
||||
return ProductBuyTile(
|
||||
key: ValueKey(item.id),
|
||||
ean: '1234567890123',
|
||||
name: 'Картофель',
|
||||
ean: item.ean13,
|
||||
name: item.name,
|
||||
price: item.price,
|
||||
count: item.cnt,
|
||||
categoryName: 'Овощи',
|
||||
categoryName: item.category,
|
||||
editable: editable,
|
||||
invoiceId: widget.invoice.id,
|
||||
id: item.id,
|
||||
|
|
@ -115,14 +124,29 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Visibility(
|
||||
visible: false,
|
||||
visible: itemsExist,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: FloatingActionButton(
|
||||
mini: true,
|
||||
elevation: 2,
|
||||
backgroundColor: successColor,
|
||||
onPressed: () {},
|
||||
onPressed: () async {
|
||||
DialogResponse confirm =
|
||||
await _dialogService.showConfirmationDialog(
|
||||
title: 'Подтверждение',
|
||||
description: 'Вы действительно хотите завершить покупку?',
|
||||
confirmationTitle: 'Да',
|
||||
cancelTitle: 'Нет',
|
||||
);
|
||||
if (confirm.confirmed) {
|
||||
bool result =
|
||||
await _service.confirmInvoice(widget.invoice.id);
|
||||
if (result) {
|
||||
locator<NavigatorService>().pop(result);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
Icons.check,
|
||||
color: whiteColor,
|
||||
|
|
@ -141,13 +165,12 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
.push(addProductViewRoute) as Good?;
|
||||
if (good != null && good.id != null) {
|
||||
bool result =
|
||||
await _service.addItem(widget.invoice.id, good.id!);
|
||||
await _service.addItem(widget.invoice.id, good.id!);
|
||||
if (result) {
|
||||
_pagingController.refresh();
|
||||
} else {
|
||||
_dialogService.showDialog(
|
||||
description:
|
||||
'Товара отсутсвует в остатке или ранее не'
|
||||
description: 'Товара отсутсвует в остатке или ранее не'
|
||||
' использователся в системе',
|
||||
);
|
||||
}
|
||||
|
|
@ -168,8 +191,25 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
final dynamic result = await _nav.push(addByBarcodeViewRoute);
|
||||
if (result != null) {
|
||||
final List<Good> goods = await locator<DictionaryService>()
|
||||
.getGoodsByNameOrEan(result as String);
|
||||
if (goods.isNotEmpty) {}
|
||||
.getGoodsByNameOrEan(result as String, onlyEan: true);
|
||||
if (goods.isNotEmpty) {
|
||||
final Good good = goods.first;
|
||||
bool result = await _service.addItem(
|
||||
widget.invoice.id, good.id!);
|
||||
if (result) {
|
||||
_pagingController.refresh();
|
||||
} else {
|
||||
_dialogService.showDialog(
|
||||
description: 'Товара отсутсвует в остатке или ранее не'
|
||||
' использователся в системе',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_dialogService.showDialog(
|
||||
description: 'Товара отсутсвует в остатке или ранее не'
|
||||
' использователся в системе',
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Icon(Icons.qr_code_rounded, size: 30, color: whiteColor),
|
||||
|
|
@ -191,16 +231,21 @@ class _BuyEditViewState extends State<BuyEditView> {
|
|||
final nextPageKey = pageKey + 1;
|
||||
_pagingController.appendPage(newItems, nextPageKey);
|
||||
}
|
||||
if ((_pagingController.value.itemList ?? []).isNotEmpty) {
|
||||
setState(() {
|
||||
itemsExist = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _editData(int id, double price, double count) {
|
||||
final List<BuyItemResponse> oldList =
|
||||
_pagingController.value.itemList ?? [];
|
||||
oldList..firstWhere((element) => element.id == id).price = price
|
||||
oldList
|
||||
..firstWhere((element) => element.id == id).price = price
|
||||
..firstWhere((element) => element.id == id).cnt = count;
|
||||
setState(() {
|
||||
_pagingController.itemList = oldList;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,15 +21,13 @@ class BuyView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _BuyViewState extends State<BuyView> {
|
||||
|
||||
|
||||
final BuyService _service = locator<BuyService>();
|
||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
|
||||
static const _pageSize = 20;
|
||||
|
||||
final PagingController<int, BuyInvoiceResponse> _pagingController =
|
||||
PagingController(firstPageKey: 1);
|
||||
PagingController(firstPageKey: 1);
|
||||
|
||||
final DateFormat formatterDay = DateFormat('dd.MM.yyyy');
|
||||
|
||||
|
|
@ -43,7 +41,6 @@ class _BuyViewState extends State<BuyView> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
|
||||
_pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
|
@ -68,8 +65,8 @@ class _BuyViewState extends State<BuyView> {
|
|||
},
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<BuyInvoiceResponse>(
|
||||
itemBuilder: (BuildContext context, BuyInvoiceResponse item,
|
||||
int index) {
|
||||
itemBuilder:
|
||||
(BuildContext context, BuyInvoiceResponse item, int index) {
|
||||
return DictionaryTile(
|
||||
key: Key('category_${item.id}'),
|
||||
onPress: () async {
|
||||
|
|
@ -82,29 +79,41 @@ class _BuyViewState extends State<BuyView> {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.name}',
|
||||
style: textBlack12Style,
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
Text(
|
||||
'Номер: ${item.docNumber.toString()}',
|
||||
style: textGray11Style,
|
||||
),
|
||||
],
|
||||
)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${item.eaccContragentId.toString()}',
|
||||
'${formatterDay.format(item.invoiceDate)}',
|
||||
style: textBlack12Style,
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
Text(
|
||||
'Статус: ${item.refBuyInvoiceStatusId.toString()}',
|
||||
'Статус: ${item.refBuyInvoiceStatusId == 1 ? 'Новая' : 'Обработана'}',
|
||||
style: textGray11Style,
|
||||
),
|
||||
],
|
||||
)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'${formatterDay.format(item.invoiceDate)}',
|
||||
style: textBlack12Style,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
|
|
@ -127,12 +136,22 @@ class _BuyViewState extends State<BuyView> {
|
|||
)
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () async {
|
||||
final dynamic result = await _navigatorService.push(buyAddRoute);
|
||||
if (result != null && true == (result as bool)) {
|
||||
_pagingController.refresh();
|
||||
}
|
||||
},
|
||||
mini: true,
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _fetchData(int pageKey, int perPage) async {
|
||||
final List<BuyInvoiceResponse> newItems = await _service
|
||||
.getList(page: pageKey, perpage: perPage);
|
||||
final List<BuyInvoiceResponse> newItems =
|
||||
await _service.getList(page: pageKey, perpage: perPage);
|
||||
final isLastPage = newItems.length < _pageSize;
|
||||
if (isLastPage) {
|
||||
_pagingController.appendLastPage(newItems);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:satu/core/models/dialog_models.dart';
|
||||
import 'package:satu/core/redux/actions/sell_actions.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/buy_service.dart';
|
||||
import 'package:satu/core/services/dialog_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/shared_styles.dart';
|
||||
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||
import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||
|
||||
class ProductBuyTile extends StatefulWidget {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:satu/core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import 'package:satu/core/redux/actions/user_actions.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/routes/route_names.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
|
||||
class ContragentSelectBar extends StatelessWidget {
|
||||
|
||||
const ContragentSelectBar({required this.value, Key? key}) : super(key: key);
|
||||
final String value;
|
||||
|
||||
|
|
@ -17,11 +19,16 @@ class ContragentSelectBar extends StatelessWidget {
|
|||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
locator<NavigatorService>().push(contragentSelectViewRoute);
|
||||
onTap: () async {
|
||||
ContragentResponseEntity? entity =
|
||||
await locator<NavigatorService>()
|
||||
.push(contragentSelectViewRoute) as ContragentResponseEntity?;
|
||||
if (entity != null) {
|
||||
Redux.store?.dispatch(setDefaultContragent(entity));
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical:08.w, horizontal: 15.w),
|
||||
padding: EdgeInsets.symmetric(vertical: 08.w, horizontal: 15.w),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ import 'package:satu/core/utils/locator.dart';
|
|||
import 'package:satu/core/utils/utils_parse.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/shared_styles.dart';
|
||||
import 'package:satu/views/work/views/add_by_barcode/add_by_barcode_view.dart';
|
||||
import 'package:satu/widgets/ui/product_title_widget.dart';
|
||||
|
||||
import '../../../views/select_by_scan/add_by_barcode_view.dart';
|
||||
|
||||
|
||||
class ProductSellTile extends StatefulWidget {
|
||||
const ProductSellTile(
|
||||
|
|
@ -42,7 +43,7 @@ class _ProductSellTileState extends State<ProductSellTile> {
|
|||
|
||||
void _onItemTapped(BuildContext context) {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (BuildContext context) => const AddByBarcodeView()));
|
||||
builder: (BuildContext context) => const SelectByScanView()));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|||
import 'package:redux/src/store.dart';
|
||||
import 'package:satu/core/models/flow/dao/product_dao.dart';
|
||||
import 'package:satu/core/redux/state/sell_state.dart';
|
||||
import 'package:satu/core/redux/state/user_state.dart';
|
||||
import 'package:satu/core/redux/store.dart';
|
||||
import 'package:satu/core/services/navigator_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
|
|
@ -34,15 +35,20 @@ class SellView extends StatelessWidget {
|
|||
backgroundColor: backgroundColor,
|
||||
childHeight: 60,
|
||||
child: ProductHeaderBar(
|
||||
count: state.items!.length,
|
||||
count: state.items!.length,
|
||||
sum: sumProducts(state.items!),
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
const ContragentSelectBar(
|
||||
value: 'Частное лицо',
|
||||
),
|
||||
StoreConnector<AppState, UserState>(
|
||||
converter: (store) => store.state.userState!,
|
||||
builder: (_, uState) {
|
||||
return ContragentSelectBar(
|
||||
value: (uState.defaultContragent?.name ??
|
||||
'Выберите контрагента'),
|
||||
);
|
||||
}),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
|
|
@ -120,11 +126,11 @@ class SellView extends StatelessWidget {
|
|||
elevation: 2,
|
||||
mini: true,
|
||||
onPressed: () async {
|
||||
final Good? good = await locator<NavigatorService>().push(addProductViewRoute) as Good?;
|
||||
if(good !=null) {
|
||||
final Good? good = await locator<NavigatorService>()
|
||||
.push(addProductViewRoute) as Good?;
|
||||
if (good != null) {
|
||||
Redux.store!.dispatch(addSellItem(good: good));
|
||||
}
|
||||
|
||||
},
|
||||
child: Icon(
|
||||
Icons.add_rounded,
|
||||
|
|
@ -144,7 +150,7 @@ class SellView extends StatelessWidget {
|
|||
if (result != null) {
|
||||
final List<Good> goods =
|
||||
await locator<DictionaryService>()
|
||||
.getGoodsByNameOrEan(result as String);
|
||||
.getGoodsByNameOrEan(result as String, onlyEan: true);
|
||||
if (goods.isNotEmpty) {
|
||||
Redux.store
|
||||
?.dispatch(addSellItem(good: goods.first));
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:satu/core/entity/category_entity.dart';
|
||||
import 'package:satu/core/entity/goods_entity.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/ui_helpers.dart';
|
||||
import 'package:satu/widgets/bar/products_app_bar.dart';
|
||||
import 'package:satu/widgets/bar/products_title_bar.dart';
|
||||
import 'package:satu/widgets/fields/input_field.dart';
|
||||
|
||||
import 'companent/contragent_list_item.dart';
|
||||
|
||||
class SelectContragentView extends StatefulWidget {
|
||||
@override
|
||||
_SelectContragentViewState createState() => _SelectContragentViewState();
|
||||
}
|
||||
|
||||
class _SelectContragentViewState extends State<SelectContragentView> {
|
||||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = new FocusNode();
|
||||
|
||||
final List<Category> _contragents = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchTextController = TextEditingController();
|
||||
_searchTextController.addListener(() {
|
||||
if (_searchTextController.text.isNotEmpty) {
|
||||
searchByField(_searchTextController.text);
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchTextController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: const ProductsAppBar(
|
||||
title: 'Контрагент',
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
InputField(
|
||||
placeholder: 'Поиск по наименованию или коду товара',
|
||||
search: true,
|
||||
controller: _searchTextController,
|
||||
fieldFocusNode: _searchFocusNode,
|
||||
),
|
||||
verticalSpaceTiny,
|
||||
const ProductsTitleBarBar(
|
||||
title: 'Выберите контрагента',
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemCount: _contragents.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final Category category = _contragents[index];
|
||||
return ContragentListItem(
|
||||
name: category.name,
|
||||
key: Key('category_${category.id}'),
|
||||
onPress: () => () {},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Divider(
|
||||
height: 1.0,
|
||||
color: disableColor,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
}
|
||||
|
||||
void searchByField(String query) async {
|
||||
|
||||
List<Good> goods = await _dictionaryService.getGoodsByNameOrEan(query);
|
||||
setState(() {
|
||||
goods;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -5,17 +5,17 @@ import 'package:satu/core/utils/locator.dart';
|
|||
import 'package:satu/widgets/bar/products_app_bar.dart';
|
||||
import 'package:satu/widgets/tools/app_barcode_scanner_widget.dart';
|
||||
|
||||
class AddByBarcodeView extends StatefulWidget {
|
||||
class SelectByScanView extends StatefulWidget {
|
||||
|
||||
const AddByBarcodeView({
|
||||
const SelectByScanView({
|
||||
Key? key
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AddByBarcodeViewState createState() => _AddByBarcodeViewState();
|
||||
_SelectByScanViewState createState() => _SelectByScanViewState();
|
||||
}
|
||||
|
||||
class _AddByBarcodeViewState extends State<AddByBarcodeView> {
|
||||
class _SelectByScanViewState extends State<SelectByScanView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
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/entity/goods_entity.dart';
|
||||
import 'package:satu/core/services/dictionary_service.dart';
|
||||
import 'package:satu/core/utils/locator.dart';
|
||||
import 'package:satu/shared/app_colors.dart';
|
||||
import 'package:satu/shared/ui_helpers.dart';
|
||||
import 'package:satu/widgets/bar/products_app_bar.dart';
|
||||
import 'package:satu/widgets/bar/products_title_bar.dart';
|
||||
import 'package:satu/widgets/fields/input_field.dart';
|
||||
|
||||
import '../../../../core/models/dictionary/contragent/contragent_response_entity.dart';
|
||||
import '../../../../core/services/navigator_service.dart';
|
||||
import '../../../dictionaries/component/dictionary_list_tile.dart';
|
||||
import 'companent/contragent_list_item.dart';
|
||||
|
||||
class SelectContragentView extends StatefulWidget {
|
||||
@override
|
||||
_SelectContragentViewState createState() => _SelectContragentViewState();
|
||||
}
|
||||
|
||||
class _SelectContragentViewState extends State<SelectContragentView> {
|
||||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
late TextEditingController _searchTextController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
|
||||
late List<ContragentResponseEntity> items = [];
|
||||
static const _pageSize = 20;
|
||||
|
||||
final PagingController<int, ContragentResponseEntity> _pagingController =
|
||||
PagingController(firstPageKey: 0);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_searchTextController = TextEditingController();
|
||||
_searchTextController.addListener(() {
|
||||
if (_searchTextController.text.isNotEmpty) {
|
||||
//searchByField(_searchTextController.text);
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
});
|
||||
_pagingController.addPageRequestListener((pageKey) {
|
||||
_fetchData(pageKey, _pageSize, null);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> initQuery() async {
|
||||
//searchByField('');
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchTextController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ProductsAppBar(
|
||||
title: 'Контрагенты',
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
InputField(
|
||||
placeholder: 'Поиск по наименованию',
|
||||
search: true,
|
||||
controller: _searchTextController,
|
||||
fieldFocusNode: _searchFocusNode,
|
||||
),
|
||||
const ProductsTitleBarBar(title: 'Список контрагентов'),
|
||||
Expanded(
|
||||
child: PagedListView<int, ContragentResponseEntity>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate:
|
||||
PagedChildBuilderDelegate<ContragentResponseEntity>(
|
||||
itemBuilder: (BuildContext context,
|
||||
ContragentResponseEntity entity, int index) {
|
||||
return DictionaryTile(
|
||||
key: Key('contragent_${entity.id}'),
|
||||
onPress: () async {
|
||||
_navigatorService.pop(entity);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
entity.name ?? '',
|
||||
style: const TextStyle(fontSize: 12, color: textColor),
|
||||
),
|
||||
Text('БИН/ИИН: ${entity.biniin}',
|
||||
style: const TextStyle(
|
||||
fontSize: 10, color: placeholderColor)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_searchTextController.clear();
|
||||
}
|
||||
|
||||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<ContragentResponseEntity> newItems = await _dictionaryService
|
||||
.getContragents(page: pageKey, query: query, perpage: perPage);
|
||||
|
||||
final isLastPage = newItems.length < _pageSize;
|
||||
if (isLastPage) {
|
||||
_pagingController.appendLastPage(newItems);
|
||||
} else {
|
||||
final nextPageKey = pageKey + newItems.length;
|
||||
_pagingController.appendPage(newItems, nextPageKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,12 +15,12 @@ import 'package:satu/widgets/fields/input_field.dart';
|
|||
import '../../../../core/models/dictionary/good/good_response_entity.dart';
|
||||
import 'component/add_product_list_item.dart';
|
||||
|
||||
class AddProductView extends StatefulWidget {
|
||||
class SelectProductView extends StatefulWidget {
|
||||
@override
|
||||
_AddProductViewState createState() => _AddProductViewState();
|
||||
_SelectProductViewState createState() => _SelectProductViewState();
|
||||
}
|
||||
|
||||
class _AddProductViewState extends State<AddProductView> {
|
||||
class _SelectProductViewState extends State<SelectProductView> {
|
||||
final DictionaryService _dictionaryService = locator<DictionaryService>();
|
||||
final NavigatorService _navigatorService = locator<NavigatorService>();
|
||||
late TextEditingController _searchTextController;
|
||||
|
|
@ -121,8 +121,12 @@ class _AddProductViewState extends State<AddProductView> {
|
|||
Future<void> _fetchData(int pageKey, int perPage, String? query) async {
|
||||
final List<GoodResponseEntity> newItems = await _dictionaryService.getGoods(
|
||||
page: pageKey,
|
||||
filter: {'col': 'name', 'action': 'like', 'val': query ?? ''},
|
||||
perpage: perPage);
|
||||
filter: [{'col': 'name', 'action': 'like', 'val': query ?? ''}, {
|
||||
'col': 'ean13',
|
||||
'action': 'like',
|
||||
'val': query ?? ''
|
||||
}],
|
||||
perpage: perPage, orGate: true);
|
||||
|
||||
List<Good> items = newItems.map((e) => goodResponseToGood(e)).toList();
|
||||
final isLastPage = newItems.length < _pageSize;
|
||||
|
|
@ -14,6 +14,7 @@ import 'package:satu/views/dictionaries/category/category_view.dart';
|
|||
import 'package:satu/views/dictionaries/contragents/contragents_view.dart';
|
||||
import 'package:satu/views/dictionaries/goods/goods_view.dart';
|
||||
import 'package:satu/views/settings/setting_view.dart';
|
||||
import 'package:satu/views/stocks/stocks_view.dart';
|
||||
import 'package:satu/views/work/work_view.dart';
|
||||
|
||||
import '../../views/inventarization/view/inventarization_view.dart';
|
||||
|
|
@ -50,9 +51,8 @@ class AppDrawer extends StatelessWidget {
|
|||
text: 'Остатки',
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
Redux.store!.dispatch(navigateDrawer(AnalyticsView));
|
||||
},
|
||||
disable: true,
|
||||
Redux.store!.dispatch(navigateDrawer(StocksView));
|
||||
}
|
||||
),
|
||||
_createDrawerItem(
|
||||
svgFile: 'inventarization',
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import 'note_text.dart';
|
|||
|
||||
class LineTile extends StatelessWidget {
|
||||
const LineTile(this.text,
|
||||
{required this.onTap, this.labelText, this.placeholder = 'Выберите'});
|
||||
{required this.onTap, this.labelText, this.placeholder = 'Выберите', Key? key}) : super(key: key);
|
||||
|
||||
final String text;
|
||||
final String placeholder;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+1
|
||||
version: 1.0.1+2
|
||||
|
||||
|
||||
environment:
|
||||
|
|
|
|||
Loading…
Reference in New Issue