add logic

null-safety-migration
suvaissov 2021-05-07 01:18:56 +06:00
parent 1d31dce7be
commit c76bc5f9d2
16 changed files with 591 additions and 464 deletions

View File

@ -4,6 +4,7 @@ const String TransactionColumnUuid = 'uuid';
const String TransactionColumnType = 'type'; const String TransactionColumnType = 'type';
const String TransactionColumnStatus = 'status'; const String TransactionColumnStatus = 'status';
const String TransactionColumnData = 'data'; const String TransactionColumnData = 'data';
const String TransactionColumnAppCompanyId = 'appCompanyId';
const String TransactionColumnCreatedAt = 'createdAt'; const String TransactionColumnCreatedAt = 'createdAt';
const int TransactionTypeSell = 1; const int TransactionTypeSell = 1;
@ -18,6 +19,7 @@ class Transaction {
int type; int type;
int status; int status;
String data; String data;
int appCompanyId;
String createdAt; String createdAt;
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
@ -26,6 +28,7 @@ class Transaction {
TransactionColumnType: type, TransactionColumnType: type,
TransactionColumnStatus: status, TransactionColumnStatus: status,
TransactionColumnData: data, TransactionColumnData: data,
TransactionColumnAppCompanyId: appCompanyId,
TransactionColumnCreatedAt: createdAt, TransactionColumnCreatedAt: createdAt,
}; };
if (id != null) { if (id != null) {
@ -41,6 +44,7 @@ class Transaction {
uuid = map[TransactionColumnUuid]; uuid = map[TransactionColumnUuid];
type = map[TransactionColumnType]; type = map[TransactionColumnType];
status = map[TransactionColumnStatus]; status = map[TransactionColumnStatus];
appCompanyId = map[TransactionColumnAppCompanyId];
data = map[TransactionColumnData]; data = map[TransactionColumnData];
createdAt = map[TransactionColumnCreatedAt]; createdAt = map[TransactionColumnCreatedAt];
} }

View File

@ -8,4 +8,35 @@ class ProductDao {
String eanCode; String eanCode;
int article; int article;
String excise; String excise;
Map<String, dynamic> toMap() {
var map = <String, dynamic>{
'id': id,
'categoryId': categoryId,
'count': count,
'price': price,
'productName': productName,
'categoryName': categoryName,
'eanCode': eanCode,
'article': article,
'excise': excise,
};
return map;
}
ProductDao();
ProductDao.fromMap(Map<String, dynamic> map) {
id = map['id'];
categoryId = map['categoryId'];
count = map['count'];
price = map['price'];
productName = map['productName'];
categoryName = map['categoryName'];
eanCode = map['eanCode'];
article = map['article'];
excise = map['excise'];
}
} }

View File

@ -0,0 +1,3 @@
class TransactionState {
String uuid;
}

View File

@ -1,13 +1,19 @@
import 'dart:convert';
import 'package:logger/logger.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:redux/redux.dart'; import 'package:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart'; import 'package:redux_thunk/redux_thunk.dart';
import 'package:satu/core/entity/Category.dart'; import 'package:satu/core/entity/Category.dart';
import 'package:satu/core/entity/Goods.dart'; import 'package:satu/core/entity/Goods.dart';
import 'package:satu/core/entity/Transaction.dart';
import 'package:satu/core/models/flow/product_dao.dart'; import 'package:satu/core/models/flow/product_dao.dart';
import 'package:satu/core/models/flow/transaction_state.dart';
import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/redux/state/sell_state.dart';
import 'package:satu/core/services/db_service.dart'; import 'package:satu/core/services/db_service.dart';
import 'package:satu/core/services/dialog_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:uuid/uuid.dart';
import '../store.dart'; import '../store.dart';
@ -18,27 +24,97 @@ class SetSellStateAction {
SetSellStateAction(this.sellState); SetSellStateAction(this.sellState);
} }
final Logger log = getLogger('SetSellStateAction');
final DbService _dbService = locator<DbService>(); final DbService _dbService = locator<DbService>();
ThunkAction<AppState> addSellItem({Good good, String excise}) { ThunkAction<AppState> addSellItem({Good good, String excise}) {
return (Store<AppState> store) async { return (Store<AppState> store) async {
ProductDao item = new ProductDao() log.i('addSellItem');
..id = good.id int appCompanyId = store.state.userState.auth.companyId;
..price = good.price String uuid = store.state.sellState.transactionState.uuid;
..article = good.articul
..count = 1.0 Transaction transaction;
..eanCode = good.ean
..productName = good.name if (uuid != null && good !=null) {
..excise = excise; List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
//category add logic TransactionTableName,
if (good.categoryId != null) { '$TransactionColumnAppCompanyId = ? and $TransactionColumnStatus = ? and ${TransactionColumnType} = ?',
List<Map<String, dynamic>> set = [appCompanyId, TransactionStatusPrepare, TransactionTypeSell],
await _dbService.queryRowsWithWhere(CategoryTableName, 'id = ?', [good.categoryId]); orderBy: '$TransactionColumnCreatedAt desc');
if (set.isNotEmpty) { if (set.isNotEmpty) {
Category category = Category.fromMap(set.first); for(Map<String, dynamic> map in set) {
item.categoryId = category.id; Transaction _transaction = Transaction.fromMap(map);
ProductDao _product = ProductDao.fromMap(jsonDecode(_transaction.data));
if(_product.id == good.id) {
transaction = _transaction;
break;
}
}
} }
} }
store.dispatch(SetSellStateAction(SellState()));
if(transaction !=null) {
ProductDao item = ProductDao.fromMap(jsonDecode(transaction.data));
item..count = item.count + 1;
transaction.data = jsonEncode(item.toMap());
transaction.createdAt = DateTime.now().toIso8601String();
_dbService.update(TransactionTableName, transaction.toMap());
} else {
ProductDao item = new ProductDao()
..id = good.id
..price = good.price
..article = good.articul
..count = 1.0
..eanCode = good.ean
..productName = good.name
..excise = excise;
//category add logic
if (good.categoryId != null) {
List<Map<String, dynamic>> set =
await _dbService.queryRowsWithWhere(CategoryTableName, 'id = ?', [good.categoryId]);
if (set.isNotEmpty) {
Category category = Category.fromMap(set.first);
item.categoryId = category.id;
}
}
if (uuid == null) {
var uuidTool = Uuid();
;
uuid = uuidTool.v4();
}
transaction = new Transaction()
..uuid = uuid
..status = TransactionStatusPrepare
..appCompanyId = appCompanyId
..type = TransactionTypeSell
..createdAt = DateTime.now().toIso8601String()
..data = jsonEncode(item.toMap());
await _dbService.insert(TransactionTableName, transaction.toMap());
}
await loadSellData(store);
}; };
} }
Future<void> loadSellData(Store<AppState> store) async {
try {
int appCompanyId = store.state.userState.auth.companyId;
List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
TransactionTableName,
'$TransactionColumnAppCompanyId = ? and $TransactionColumnStatus = ? and ${TransactionColumnType} = ?',
[appCompanyId, TransactionStatusPrepare, TransactionTypeSell],
orderBy: '$TransactionColumnCreatedAt desc');
List<ProductDao> list = [];
String uuid;
for (Map<String, dynamic> map in set) {
Transaction transaction = Transaction.fromMap(map);
uuid = transaction.uuid;
list.add(ProductDao.fromMap(jsonDecode(transaction.data)));
}
store.dispatch(SetSellStateAction(SellState(items: list, transactionState: TransactionState()..uuid = uuid)));
} catch (e, stack) {
log.e('loadSellData', e, stack);
}
}

View File

@ -6,6 +6,7 @@ import 'package:satu/core/redux/state/user_state.dart';
sellReducer(SellState prevState, SetSellStateAction action) { sellReducer(SellState prevState, SetSellStateAction action) {
final payload = action.sellState; final payload = action.sellState;
return prevState.copyWith( return prevState.copyWith(
items: payload.items items: payload.items,
transactionState: payload.transactionState
); );
} }

View File

@ -1,20 +1,23 @@
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:satu/core/models/auth/auth_response.dart'; import 'package:satu/core/models/auth/auth_response.dart';
import 'package:satu/core/models/flow/product_dao.dart'; import 'package:satu/core/models/flow/product_dao.dart';
import 'package:satu/core/models/flow/transaction_state.dart';
@immutable @immutable
class SellState { class SellState {
final List<ProductDao> items; final List<ProductDao> items;
final TransactionState transactionState;
SellState({ SellState({this.items, this.transactionState});
this.items,
});
factory SellState.initial() => SellState( factory SellState.initial() => SellState(
items: [], items: [],
transactionState: TransactionState(),
); );
SellState copyWith({@required List<ProductDao> items}) { SellState copyWith({@required List<ProductDao> items, @required TransactionState transactionState}) {
return SellState(items: items ?? this.items); return SellState(items: items ?? this.items, transactionState: transactionState ?? this.transactionState);
} }
} }

View File

@ -5,7 +5,9 @@ import 'package:redux_persist_flutter/redux_persist_flutter.dart';
import 'package:redux_thunk/redux_thunk.dart'; import 'package:redux_thunk/redux_thunk.dart';
import 'package:redux_persist/redux_persist.dart'; import 'package:redux_persist/redux_persist.dart';
import 'package:satu/core/redux/actions/nav_actions.dart'; import 'package:satu/core/redux/actions/nav_actions.dart';
import 'package:satu/core/redux/actions/sell_actions.dart';
import 'package:satu/core/redux/reducers/nav_reducer.dart'; import 'package:satu/core/redux/reducers/nav_reducer.dart';
import 'package:satu/core/redux/reducers/sell_reducer.dart';
import 'package:satu/core/redux/reducers/user_reducer.dart'; import 'package:satu/core/redux/reducers/user_reducer.dart';
import 'package:satu/core/redux/state/nav_state.dart'; import 'package:satu/core/redux/state/nav_state.dart';
import 'package:satu/core/redux/state/sell_state.dart'; import 'package:satu/core/redux/state/sell_state.dart';
@ -24,6 +26,10 @@ AppState appReducer(AppState state, dynamic action) {
/** NavAction **/ /** NavAction **/
final nextState = navReducer(state.navState, action); final nextState = navReducer(state.navState, action);
return state.copyWith(navState: nextState); return state.copyWith(navState: nextState);
} else if (action is SetSellStateAction) {
/** NavAction **/
final nextState = sellReducer(state.sellState, action);
return state.copyWith(sellState: nextState);
} }
return state; return state;
} }

View File

@ -77,6 +77,8 @@ class DbService extends BaseService {
$TransactionColumnId integer primary key autoincrement, $TransactionColumnId integer primary key autoincrement,
$TransactionColumnUuid text, $TransactionColumnUuid text,
$TransactionColumnType integer not null, $TransactionColumnType integer not null,
$TransactionColumnAppCompanyId integer not null,
$TransactionColumnStatus integer not null,
$TransactionColumnData text, $TransactionColumnData text,
$TransactionColumnCreatedAt text not null $TransactionColumnCreatedAt text not null
); );
@ -98,15 +100,20 @@ class DbService extends BaseService {
return await db.query(table); return await db.query(table);
} }
Future<List<Map<String, dynamic>>> queryRaw(String sql, List<dynamic> args) async {
Database db = await instance.database;
return await db.rawQuery(sql, args );
}
Future<List<Map<String, dynamic>>> queryAllRowsOrderBy(String table, String orderBy) async { Future<List<Map<String, dynamic>>> queryAllRowsOrderBy(String table, String orderBy) async {
Database db = await instance.database; Database db = await instance.database;
return await db.query(table, orderBy: orderBy); return await db.query(table, orderBy: orderBy);
} }
Future<List<Map<String, dynamic>>> queryRowsWithWhere( Future<List<Map<String, dynamic>>> queryRowsWithWhere(
String table, String where, List<dynamic> args) async { String table, String where, List<dynamic> args, { String orderBy }) async {
Database db = await instance.database; Database db = await instance.database;
return await db.query(table, where: where, whereArgs: args); return await db.query(table, where: where, whereArgs: args, orderBy: orderBy);
} }
// All of the methods (insert, query, update, delete) can also be done using // All of the methods (insert, query, update, delete) can also be done using

View File

@ -1,6 +1,4 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:satu/core/base/base_service.dart'; import 'package:satu/core/base/base_service.dart';
import 'package:satu/core/entity/Category.dart'; import 'package:satu/core/entity/Category.dart';
import 'package:satu/core/entity/Goods.dart'; import 'package:satu/core/entity/Goods.dart';
@ -49,7 +47,7 @@ class DictionaryService extends BaseService {
List<Category> list = []; List<Category> list = [];
try { try {
int appCompanyId = Redux.store.state.userState.auth.companyId; int appCompanyId = Redux.store.state.userState.auth.companyId;
List<Map<String, dynamic>> elements = await _db.queryRowsWithWhere(CategoryTableName, '$CategoryColumnParentIn = ?', [parentId]); List<Map<String, dynamic>> elements = await _db.queryRowsWithWhere(CategoryTableName, '$CategoryColumnAppCompanyId = ? and $CategoryColumnParentIn = ?', [appCompanyId, parentId]);
elements.forEach((element) { elements.forEach((element) {
list.add(Category.fromMap(element)); list.add(Category.fromMap(element));
}); });

View File

@ -40,7 +40,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
case SettingPrinterBluetoothViewRoute: case SettingPrinterBluetoothViewRoute:
return _getPageRoute( return _getPageRoute(
routeName: settings.name, routeName: settings.name,
viewToShow: PrinterSelectView(title: 'Принтер печати чеков',), //viewToShow: PrinterSelectView(title: 'Принтер печати чеков',),
); );
// case ImageShowRoute: // case ImageShowRoute:
// ImageShowModel data = settings.arguments as ImageShowModel; // ImageShowModel data = settings.arguments as ImageShowModel;

View File

@ -9,10 +9,8 @@ import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:satu/core/redux/actions/user_actions.dart'; import 'package:satu/core/redux/actions/user_actions.dart';
import 'package:satu/core/redux/constants/auth_type_const.dart';
import 'package:satu/core/redux/state/user_state.dart'; import 'package:satu/core/redux/state/user_state.dart';
import 'package:satu/core/redux/store.dart'; import 'package:satu/core/redux/store.dart';
import 'package:satu/core/services/api_service.dart';
import 'package:satu/core/services/dialog_service.dart'; import 'package:satu/core/services/dialog_service.dart';
import 'package:satu/core/utils/locator.dart'; import 'package:satu/core/utils/locator.dart';
import 'package:satu/shared/app_colors.dart'; import 'package:satu/shared/app_colors.dart';

View File

@ -1,366 +1,366 @@
import 'dart:convert'; // import 'dart:convert';
import 'dart:typed_data'; // import 'dart:typed_data';
//
import 'package:charset_converter/charset_converter.dart'; // import 'package:charset_converter/charset_converter.dart';
import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart'; // import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart';
import 'package:esc_pos_utils/esc_pos_utils.dart'; // import 'package:esc_pos_utils/esc_pos_utils.dart';
import 'package:flutter/material.dart' hide Image; // import 'package:flutter/material.dart' hide Image;
import 'package:image/image.dart' as Im; // import 'package:image/image.dart' as Im;
import 'package:flutter/services.dart'; // import 'package:flutter/services.dart';
import 'package:intl/intl.dart'; // import 'package:intl/intl.dart';
//
class PrinterSelectView extends StatefulWidget { // class PrinterSelectView extends StatefulWidget {
PrinterSelectView({Key key, this.title}) : super(key: key); // PrinterSelectView({Key key, this.title}) : super(key: key);
final String title; // final String title;
//
@override // @override
_PrinterSelectViewState createState() => _PrinterSelectViewState(); // _PrinterSelectViewState createState() => _PrinterSelectViewState();
} // }
//
class _PrinterSelectViewState extends State<PrinterSelectView> { // class _PrinterSelectViewState extends State<PrinterSelectView> {
PrinterBluetoothManager printerManager = PrinterBluetoothManager(); // // PrinterBluetoothManager printerManager = PrinterBluetoothManager();
List<PrinterBluetooth> _devices = []; // // List<PrinterBluetooth> _devices = [];
//
@override // @override
void initState() { // void initState() {
super.initState(); // super.initState();
//
printerManager.scanResults.listen((devices) async { // printerManager.scanResults.listen((devices) async {
// print('UI: Devices found ${devices.length}'); // // print('UI: Devices found ${devices.length}');
setState(() { // setState(() {
_devices = devices; // _devices = devices;
}); // });
}); // });
} // }
//
void _startScanDevices() { // void _startScanDevices() {
setState(() { // setState(() {
_devices = []; // _devices = [];
}); // });
printerManager.startScan(Duration(seconds: 4)); // printerManager.startScan(Duration(seconds: 4));
} // }
//
void _stopScanDevices() { // void _stopScanDevices() {
printerManager.stopScan(); // printerManager.stopScan();
} // }
//
Future<Ticket> demoReceipt(PaperSize paper) async { // Future<Ticket> demoReceipt(PaperSize paper) async {
final Ticket ticket = Ticket(paper, ); // final Ticket ticket = Ticket(paper, );
//
// Print image // // Print image
final ByteData data = await rootBundle.load('assets/images/aman_kassa_check.png'); // final ByteData data = await rootBundle.load('assets/images/aman_kassa_check.png');
final Uint8List bytes = data.buffer.asUint8List(); // final Uint8List bytes = data.buffer.asUint8List();
final Im.Image image = Im.decodeImage(bytes); // final Im.Image image = Im.decodeImage(bytes);
Im.Image thumbnail = Im.copyResize(image, width: 270); // Im.Image thumbnail = Im.copyResize(image, width: 270);
// ticket.image(thumbnail, align: PosAlign.center); // // ticket.image(thumbnail, align: PosAlign.center);
//
//ticket.imageRaster(image, align: PosAlign.center); // //ticket.imageRaster(image, align: PosAlign.center);
//
ticket.text('AMAN-SATU', // ticket.text('AMAN-SATU',
styles: PosStyles( // styles: PosStyles(
align: PosAlign.center, // align: PosAlign.center,
height: PosTextSize.size2, // height: PosTextSize.size2,
width: PosTextSize.size2, // width: PosTextSize.size2,
), // ),
linesAfter: 1); // linesAfter: 1);
//
ticket.text('889 Watson Lane', styles: PosStyles(align: PosAlign.center)); // ticket.text('889 Watson Lane', styles: PosStyles(align: PosAlign.center));
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, codeTable: PosCodeTable.westEur), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, codeTable: PosCodeTable.westEur), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontA), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontA), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontB), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontB), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, height: PosTextSize.size1), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, height: PosTextSize.size1), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size2), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size2), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size3), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size3), containsChinese: true);
ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size4), containsChinese: true); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size4), containsChinese: true);
ticket.text('Tel: 830-221-1234', styles: PosStyles(align: PosAlign.center)); // ticket.text('Tel: 830-221-1234', styles: PosStyles(align: PosAlign.center));
ticket.text('Web: www.example.com', // ticket.text('Web: www.example.com',
styles: PosStyles(align: PosAlign.center), linesAfter: 1); // styles: PosStyles(align: PosAlign.center), linesAfter: 1);
//
ticket.hr(); // ticket.hr();
ticket.row([ // ticket.row([
PosColumn(text: 'Qty', width: 1), // PosColumn(text: 'Qty', width: 1),
PosColumn(text: 'Item', width: 7), // PosColumn(text: 'Item', width: 7),
PosColumn( // PosColumn(
text: 'Price', width: 2, styles: PosStyles(align: PosAlign.right)), // text: 'Price', width: 2, styles: PosStyles(align: PosAlign.right)),
PosColumn( // PosColumn(
text: 'Total', width: 2, styles: PosStyles(align: PosAlign.right)), // text: 'Total', width: 2, styles: PosStyles(align: PosAlign.right)),
]); // ]);
//
ticket.row([ // ticket.row([
PosColumn(text: '2', width: 1), // PosColumn(text: '2', width: 1),
PosColumn(text: 'ONION RINGS', width: 7), // PosColumn(text: 'ONION RINGS', width: 7),
PosColumn( // PosColumn(
text: '0.99', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '0.99', width: 2, styles: PosStyles(align: PosAlign.right)),
PosColumn( // PosColumn(
text: '1.98', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '1.98', width: 2, styles: PosStyles(align: PosAlign.right)),
]); // ]);
ticket.row([ // ticket.row([
PosColumn(text: '1', width: 1), // PosColumn(text: '1', width: 1),
PosColumn(text: 'PIZZA', width: 7), // PosColumn(text: 'PIZZA', width: 7),
PosColumn( // PosColumn(
text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)),
PosColumn( // PosColumn(
text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)),
]); // ]);
ticket.row([ // ticket.row([
PosColumn(text: '1', width: 1), // PosColumn(text: '1', width: 1),
PosColumn(text: 'SPRING ROLLS', width: 7), // PosColumn(text: 'SPRING ROLLS', width: 7),
PosColumn( // PosColumn(
text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)),
PosColumn( // PosColumn(
text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)),
]); // ]);
ticket.row([ // ticket.row([
PosColumn(text: '3', width: 1), // PosColumn(text: '3', width: 1),
PosColumn(text: 'CRUNCHY STICKS', width: 7), // PosColumn(text: 'CRUNCHY STICKS', width: 7),
PosColumn( // PosColumn(
text: '0.85', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '0.85', width: 2, styles: PosStyles(align: PosAlign.right)),
PosColumn( // PosColumn(
text: '2.55', width: 2, styles: PosStyles(align: PosAlign.right)), // text: '2.55', width: 2, styles: PosStyles(align: PosAlign.right)),
]); // ]);
ticket.hr(); // ticket.hr();
//
ticket.row([ // ticket.row([
PosColumn( // PosColumn(
text: 'TOTAL', // text: 'TOTAL',
width: 6, // width: 6,
styles: PosStyles( // styles: PosStyles(
height: PosTextSize.size2, // height: PosTextSize.size2,
width: PosTextSize.size2, // width: PosTextSize.size2,
)), // )),
PosColumn( // PosColumn(
text: '\$10.97', // text: '\$10.97',
width: 6, // width: 6,
styles: PosStyles( // styles: PosStyles(
align: PosAlign.right, // align: PosAlign.right,
height: PosTextSize.size2, // height: PosTextSize.size2,
width: PosTextSize.size2, // width: PosTextSize.size2,
)), // )),
]); // ]);
//
ticket.hr(ch: '=', linesAfter: 1); // ticket.hr(ch: '=', linesAfter: 1);
//
ticket.row([ // ticket.row([
PosColumn( // PosColumn(
text: 'Cash', // text: 'Cash',
width: 7, // width: 7,
styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), // styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)),
PosColumn( // PosColumn(
text: '\$15.00', // text: '\$15.00',
width: 5, // width: 5,
styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), // styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)),
]); // ]);
ticket.row([ // ticket.row([
PosColumn( // PosColumn(
text: 'Change', // text: 'Change',
width: 7, // width: 7,
styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), // styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)),
PosColumn( // PosColumn(
text: '\$4.03', // text: '\$4.03',
width: 5, // width: 5,
styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), // styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)),
]); // ]);
//
ticket.feed(2); // ticket.feed(2);
ticket.text('Thank you!', // ticket.text('Thank you!',
styles: PosStyles(align: PosAlign.center, bold: true)); // styles: PosStyles(align: PosAlign.center, bold: true));
//
final now = DateTime.now(); // final now = DateTime.now();
final formatter = DateFormat('MM/dd/yyyy H:m'); // final formatter = DateFormat('MM/dd/yyyy H:m');
final String timestamp = formatter.format(now); // final String timestamp = formatter.format(now);
ticket.text(timestamp, // ticket.text(timestamp,
styles: PosStyles(align: PosAlign.center), linesAfter: 2); // styles: PosStyles(align: PosAlign.center), linesAfter: 2);
//
// Print QR Code from image // // Print QR Code from image
// try { // // try {
// const String qrData = 'example.com'; // // const String qrData = 'example.com';
// const double qrSize = 200; // // const double qrSize = 200;
// final uiImg = await QrPainter( // // final uiImg = await QrPainter(
// data: qrData, // // data: qrData,
// version: QrVersions.auto, // // version: QrVersions.auto,
// gapless: false, // // gapless: false,
// ).toImageData(qrSize); // // ).toImageData(qrSize);
// final dir = await getTemporaryDirectory(); // // final dir = await getTemporaryDirectory();
// final pathName = '${dir.path}/qr_tmp.png'; // // final pathName = '${dir.path}/qr_tmp.png';
// final qrFile = File(pathName); // // final qrFile = File(pathName);
// final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List()); // // final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List());
// final img = decodeImage(imgFile.readAsBytesSync()); // // final img = decodeImage(imgFile.readAsBytesSync());
//
// ticket.image(img); // // ticket.image(img);
// } catch (e) { // // } catch (e) {
// print(e); // // print(e);
// } // // }
//
// Print QR Code using native function // // Print QR Code using native function
// ticket.qrcode('example.com'); // // ticket.qrcode('example.com');
//
ticket.feed(2); // ticket.feed(2);
ticket.cut(); // ticket.cut();
return ticket; // return ticket;
} // }
//
Future<Ticket> testTicket(PaperSize paper) async { // Future<Ticket> testTicket(PaperSize paper) async {
final Ticket ticket = Ticket(paper); // final Ticket ticket = Ticket(paper);
Uint8List encTxt4 = // Uint8List encTxt4 =
await CharsetConverter.encode("cp866", "Russian: Привет Мир!"); // await CharsetConverter.encode("cp866", "Russian: Привет Мир!");
ticket.textEncoded(encTxt4, // ticket.textEncoded(encTxt4,
styles: PosStyles(codeTable: PosCodeTable.pc866_2)); // styles: PosStyles(codeTable: PosCodeTable.pc866_2));
//
ticket.text('Kazakh: Сәлем Әлем!', // ticket.text('Kazakh: Сәлем Әлем!',
styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true); // styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true);
//
// Uint8List encTxt1 = // // Uint8List encTxt1 =
// await CharsetConverter.encode("utf-8", "Kazakh: Сәлем Әлем!"); // // await CharsetConverter.encode("utf-8", "Kazakh: Сәлем Әлем!");
// ticket.textEncoded(encTxt1, // // ticket.textEncoded(encTxt1,
// styles: PosStyles(codeTable: PosCodeTable.pc866_2)); // // styles: PosStyles(codeTable: PosCodeTable.pc866_2));
ticket.text( // ticket.text(
'Regular: aA bB cC dD eE fF gG hH iI jJ kK lL mM nN oO pP qQ rR sS tT uU vV wW xX yY zZ'); // 'Regular: aA bB cC dD eE fF gG hH iI jJ kK lL mM nN oO pP qQ rR sS tT uU vV wW xX yY zZ');
ticket.text('Special 1: àÀ èÈ éÉ ûÛ üÜ çÇ ôÔ', // ticket.text('Special 1: àÀ èÈ éÉ ûÛ üÜ çÇ ôÔ',
styles: PosStyles(codeTable: PosCodeTable.westEur)); // styles: PosStyles(codeTable: PosCodeTable.westEur));
ticket.text('Special 2: blåbærgrød', // ticket.text('Special 2: blåbærgrød',
styles: PosStyles(codeTable: PosCodeTable.westEur)); // styles: PosStyles(codeTable: PosCodeTable.westEur));
//
ticket.text('Bold text', styles: PosStyles(bold: true)); // ticket.text('Bold text', styles: PosStyles(bold: true));
ticket.text('Reverse text', styles: PosStyles(reverse: true)); // ticket.text('Reverse text', styles: PosStyles(reverse: true));
ticket.text('Underlined text', // ticket.text('Underlined text',
styles: PosStyles(underline: true), linesAfter: 1); // styles: PosStyles(underline: true), linesAfter: 1);
ticket.text('Align left', styles: PosStyles(align: PosAlign.left)); // ticket.text('Align left', styles: PosStyles(align: PosAlign.left));
ticket.text('Align center', styles: PosStyles(align: PosAlign.center)); // ticket.text('Align center', styles: PosStyles(align: PosAlign.center));
ticket.text('Align right', // ticket.text('Align right',
styles: PosStyles(align: PosAlign.right), linesAfter: 1); // styles: PosStyles(align: PosAlign.right), linesAfter: 1);
//
ticket.row([ // ticket.row([
PosColumn( // PosColumn(
text: 'col3', // text: 'col3',
width: 3, // width: 3,
styles: PosStyles(align: PosAlign.center, underline: true), // styles: PosStyles(align: PosAlign.center, underline: true),
), // ),
PosColumn( // PosColumn(
text: 'col6', // text: 'col6',
width: 6, // width: 6,
styles: PosStyles(align: PosAlign.center, underline: true), // styles: PosStyles(align: PosAlign.center, underline: true),
), // ),
PosColumn( // PosColumn(
text: 'col3', // text: 'col3',
width: 3, // width: 3,
styles: PosStyles(align: PosAlign.center, underline: true), // styles: PosStyles(align: PosAlign.center, underline: true),
), // ),
]); // ]);
//
ticket.text('Text size 200%', // ticket.text('Text size 200%',
styles: PosStyles( // styles: PosStyles(
height: PosTextSize.size2, // height: PosTextSize.size2,
width: PosTextSize.size2, // width: PosTextSize.size2,
)); // ));
//
// Print image // // Print image
//final ByteData data = await rootBundle.load('assets/images/logo.png'); // //final ByteData data = await rootBundle.load('assets/images/logo.png');
//final Uint8List bytes = data.buffer.asUint8List(); // //final Uint8List bytes = data.buffer.asUint8List();
// Print image using alternative commands // // Print image using alternative commands
// ticket.imageRaster(image); // // ticket.imageRaster(image);
// ticket.imageRaster(image, imageFn: PosImageFn.graphics); // // ticket.imageRaster(image, imageFn: PosImageFn.graphics);
//
// Print barcode // // Print barcode
final List<int> barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4]; // final List<int> barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4];
ticket.barcode(Barcode.upcA(barData)); // ticket.barcode(Barcode.upcA(barData));
//
// Print mixed (chinese + latin) text. Only for printers supporting Kanji mode // // Print mixed (chinese + latin) text. Only for printers supporting Kanji mode
ticket.text( // ticket.text(
'hello ! 中文字 # world @ éphémère &', // 'hello ! 中文字 # world @ éphémère &',
styles: PosStyles(codeTable: PosCodeTable.westEur), // styles: PosStyles(codeTable: PosCodeTable.westEur),
containsChinese: true, // containsChinese: true,
); // );
//
ticket.text( // ticket.text(
'hello ! Мир # world @ éphémère &', // 'hello ! Мир # world @ éphémère &',
styles: PosStyles(codeTable: PosCodeTable.westEur), // styles: PosStyles(codeTable: PosCodeTable.westEur),
containsChinese: true, // containsChinese: true,
); // );
//
ticket.feed(2); // ticket.feed(2);
//
ticket.cut(); // ticket.cut();
return ticket; // return ticket;
} // }
//
void _testPrint(PrinterBluetooth printer) async { // void _testPrint(PrinterBluetooth printer) async {
printerManager.selectPrinter(printer); // printerManager.selectPrinter(printer);
//
// TODO Don't forget to choose printer's paper // // TODO Don't forget to choose printer's paper
const PaperSize paper = PaperSize.mm58; // const PaperSize paper = PaperSize.mm58;
//
// TEST PRINT // // TEST PRINT
// final PosPrintResult res = // // final PosPrintResult res =
// await printerManager.printTicket(await testTicket(paper)); // // await printerManager.printTicket(await testTicket(paper));
//
// DEMO RECEIPT // // DEMO RECEIPT
final PosPrintResult res = // final PosPrintResult res =
await printerManager.printTicket(await testTicket(paper) , queueSleepTimeMs: 50); // await printerManager.printTicket(await testTicket(paper) , queueSleepTimeMs: 50);
//
} // }
//
@override // @override
Widget build(BuildContext context) { // Widget build(BuildContext context) {
return Scaffold( // return Scaffold(
appBar: AppBar( // appBar: AppBar(
title: Text(widget.title), // title: Text(widget.title),
), // ),
body: ListView.builder( // body: ListView.builder(
itemCount: _devices.length, // itemCount: _devices.length,
itemBuilder: (BuildContext context, int index) { // itemBuilder: (BuildContext context, int index) {
return InkWell( // return InkWell(
onTap: () => _testPrint(_devices[index]), // onTap: () => _testPrint(_devices[index]),
child: Column( // child: Column(
children: <Widget>[ // children: <Widget>[
Container( // Container(
height: 60, // height: 60,
padding: EdgeInsets.only(left: 10), // padding: EdgeInsets.only(left: 10),
alignment: Alignment.centerLeft, // alignment: Alignment.centerLeft,
child: Row( // child: Row(
children: <Widget>[ // children: <Widget>[
Icon(Icons.print), // Icon(Icons.print),
SizedBox(width: 10), // SizedBox(width: 10),
Expanded( // Expanded(
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ // children: <Widget>[
Text(_devices[index].name ?? ''), // Text(_devices[index].name ?? ''),
Text(_devices[index].address), // Text(_devices[index].address),
Text( // Text(
'Click to print a test receipt', // 'Click to print a test receipt',
style: TextStyle(color: Colors.grey[700]), // style: TextStyle(color: Colors.grey[700]),
), // ),
], // ],
), // ),
) // )
], // ],
), // ),
), // ),
Divider(), // Divider(),
], // ],
), // ),
); // );
}), // }),
floatingActionButton: StreamBuilder<bool>( // floatingActionButton: StreamBuilder<bool>(
stream: printerManager.isScanningStream, // stream: printerManager.isScanningStream,
initialData: false, // initialData: false,
builder: (c, snapshot) { // builder: (c, snapshot) {
if (snapshot.data) { // if (snapshot.data) {
return FloatingActionButton( // return FloatingActionButton(
child: Icon(Icons.stop), // child: Icon(Icons.stop),
onPressed: _stopScanDevices, // onPressed: _stopScanDevices,
backgroundColor: Colors.red, // backgroundColor: Colors.red,
); // );
} else { // } else {
return FloatingActionButton( // return FloatingActionButton(
child: Icon(Icons.search), // child: Icon(Icons.search),
onPressed: _startScanDevices, // onPressed: _startScanDevices,
); // );
} // }
}, // },
), // ),
); // );
} // }
//
} // }

View File

@ -1,4 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:satu/core/models/flow/product_dao.dart';
import 'package:satu/core/redux/state/sell_state.dart';
import 'package:satu/core/redux/store.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/routes/route_names.dart'; import 'package:satu/routes/route_names.dart';
@ -6,44 +10,50 @@ import 'package:satu/shared/app_colors.dart';
import 'package:satu/views/work/tabs/component/product_list_item.dart'; import 'package:satu/views/work/tabs/component/product_list_item.dart';
import 'package:satu/views/work/tabs/component/products_app_bar.dart'; import 'package:satu/views/work/tabs/component/products_app_bar.dart';
import 'package:satu/views/work/tabs/component/products_header_bar.dart'; import 'package:satu/views/work/tabs/component/products_header_bar.dart';
import 'package:satu/views/work/tabs/utils/ProductUtils.dart';
class SellView extends StatelessWidget { class SellView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return StoreConnector<AppState, SellState>(
appBar: ProductsAppBar( converter: (store) => store.state.sellState,
title: 'Продажа', builder: (_, state) {
actions: actions(), return Scaffold(
elevation: 2.0, appBar: ProductsAppBar(
child: ProductHeaderBar( title: 'Продажа',
count: 14, actions: actions(),
sum: 25000, elevation: 2.0,
), child: ProductHeaderBar(
backgroundColor: backgroundColor, count: state.items.length,
childHeight: 80, sum: sumProducts(state.items),
),
body: Column(
children: [
//ProductHeaderBar(count: 14, sum: 25000,),
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return ProductListItem(
ean: '1234567890123',
isOdd: index % 2 == 0,
name:
'Хлеб ржаной который необходимо покупать каждый раз когда придет мысль об этом - ${index + 1}. ',
price: 75,
count: 15,
categoryName: 'Хлебобулочные изделия',
);
},
), ),
backgroundColor: backgroundColor,
childHeight: 80,
), ),
], body: Column(
), children: [
//ProductHeaderBar(count: 14, sum: 25000,),
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: state.items.length,
itemBuilder: (BuildContext context, int index) {
ProductDao product = state.items.elementAt(index);
return ProductListItem(
ean: product.eanCode,
isOdd: index % 2 == 0,
name: product.productName,
price: product.price,
count: product.count,
categoryName: product.productName,
);
},
),
),
],
),
);
}
); );
} }

View File

@ -0,0 +1,12 @@
import 'package:satu/core/models/flow/product_dao.dart';
num sumProducts(List<ProductDao> list) {
num result = 0.0;
if (list.isNotEmpty) {
list.forEach((product) {
result += (product.price * product.count);
});
}
return result;
}

View File

@ -127,20 +127,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
esc_pos_bluetooth:
dependency: "direct main"
description:
name: esc_pos_bluetooth
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.8"
esc_pos_utils: esc_pos_utils:
dependency: "direct main" dependency: "direct main"
description: description:
name: esc_pos_utils name: esc_pos_utils
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.6" version: "1.0.0"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -174,13 +167,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_bluetooth_basic:
dependency: transitive
description:
name: flutter_bluetooth_basic
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.5"
flutter_redux: flutter_redux:
dependency: "direct main" dependency: "direct main"
description: description:
@ -218,7 +204,7 @@ packages:
name: get_it name: get_it
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.1" version: "7.1.2"
hex: hex:
dependency: transitive dependency: transitive
description: description:
@ -239,7 +225,7 @@ packages:
name: http name: http
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.13.2" version: "0.13.3"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -275,13 +261,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.3" version: "0.6.3"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
logger: logger:
dependency: "direct main" dependency: "direct main"
description: description:
@ -471,13 +450,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.1" version: "0.4.1"
rxdart:
dependency: transitive
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.23.1"
searchable_dropdown: searchable_dropdown:
dependency: "direct main" dependency: "direct main"
description: description:
@ -644,6 +616,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.0.1+3" version: "0.0.1+3"
uuid:
dependency: "direct main"
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.2"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:

View File

@ -36,16 +36,15 @@ dependencies:
responsive_builder: ^0.4.1 responsive_builder: ^0.4.1
provider: ^5.0.0 provider: ^5.0.0
logger: ^1.0.0 logger: ^1.0.0
get_it: ^6.1.1 get_it: ^7.1.2
equatable: ^2.0.0 equatable: ^2.0.0
http: ^0.13.2 http: ^0.13.3
sqflite: ^2.0.0+3 sqflite: ^2.0.0+3
path_provider: ^2.0.1 path_provider: ^2.0.1
material_design_icons_flutter: ^4.0.5955 material_design_icons_flutter: ^4.0.5955
intl: ^0.17.0 intl: ^0.17.0
barcode_scan: ^3.0.1 barcode_scan: ^3.0.1
device_info: ^2.0.0 device_info: ^2.0.0
#esys_flutter_share: ^1.0.2
auto_size_text: ^2.1.0 auto_size_text: ^2.1.0
url_launcher: ^5.7.10 url_launcher: ^5.7.10
qr_flutter: ^4.0.0 qr_flutter: ^4.0.0
@ -55,8 +54,8 @@ dependencies:
searchable_dropdown: ^1.1.3 searchable_dropdown: ^1.1.3
material_floating_search_bar: ^0.3.4 material_floating_search_bar: ^0.3.4
implicitly_animated_reorderable_list: ^0.4.0 implicitly_animated_reorderable_list: ^0.4.0
esc_pos_bluetooth: ^0.2.8 esc_pos_utils: ^1.0.0
esc_pos_utils: ^0.3.6 # for esc_pos_bluetooth: ^0.2.8 uuid: ^2.2.2 #for esc_pos_utils: ^1.0.0
charset_converter: ^2.0.0 charset_converter: ^2.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: