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

View File

@ -8,4 +8,35 @@ class ProductDao {
String eanCode;
int article;
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:redux/redux.dart';
import 'package:redux_thunk/redux_thunk.dart';
import 'package:satu/core/entity/Category.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/transaction_state.dart';
import 'package:satu/core/redux/state/sell_state.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/logger.dart';
import 'package:uuid/uuid.dart';
import '../store.dart';
@ -18,10 +24,43 @@ class SetSellStateAction {
SetSellStateAction(this.sellState);
}
final Logger log = getLogger('SetSellStateAction');
final DbService _dbService = locator<DbService>();
ThunkAction<AppState> addSellItem({Good good, String excise}) {
return (Store<AppState> store) async {
log.i('addSellItem');
int appCompanyId = store.state.userState.auth.companyId;
String uuid = store.state.sellState.transactionState.uuid;
Transaction transaction;
if (uuid != null && good !=null) {
List<Map<String, dynamic>> set = await _dbService.queryRowsWithWhere(
TransactionTableName,
'$TransactionColumnAppCompanyId = ? and $TransactionColumnStatus = ? and ${TransactionColumnType} = ?',
[appCompanyId, TransactionStatusPrepare, TransactionTypeSell],
orderBy: '$TransactionColumnCreatedAt desc');
if (set.isNotEmpty) {
for(Map<String, dynamic> map in set) {
Transaction _transaction = Transaction.fromMap(map);
ProductDao _product = ProductDao.fromMap(jsonDecode(_transaction.data));
if(_product.id == good.id) {
transaction = _transaction;
break;
}
}
}
}
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
@ -39,6 +78,43 @@ ThunkAction<AppState> addSellItem({Good good, String excise}) {
item.categoryId = category.id;
}
}
store.dispatch(SetSellStateAction(SellState()));
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) {
final payload = action.sellState;
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:satu/core/models/auth/auth_response.dart';
import 'package:satu/core/models/flow/product_dao.dart';
import 'package:satu/core/models/flow/transaction_state.dart';
@immutable
class SellState {
final List<ProductDao> items;
final TransactionState transactionState;
SellState({
this.items,
});
SellState({this.items, this.transactionState});
factory SellState.initial() => SellState(
items: [],
transactionState: TransactionState(),
);
SellState copyWith({@required List<ProductDao> items}) {
return SellState(items: items ?? this.items);
SellState copyWith({@required List<ProductDao> items, @required TransactionState transactionState}) {
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_persist/redux_persist.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/sell_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/sell_state.dart';
@ -24,6 +26,10 @@ AppState appReducer(AppState state, dynamic action) {
/** NavAction **/
final nextState = navReducer(state.navState, action);
return state.copyWith(navState: nextState);
} else if (action is SetSellStateAction) {
/** NavAction **/
final nextState = sellReducer(state.sellState, action);
return state.copyWith(sellState: nextState);
}
return state;
}

View File

@ -77,6 +77,8 @@ class DbService extends BaseService {
$TransactionColumnId integer primary key autoincrement,
$TransactionColumnUuid text,
$TransactionColumnType integer not null,
$TransactionColumnAppCompanyId integer not null,
$TransactionColumnStatus integer not null,
$TransactionColumnData text,
$TransactionColumnCreatedAt text not null
);
@ -98,15 +100,20 @@ class DbService extends BaseService {
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 {
Database db = await instance.database;
return await db.query(table, orderBy: orderBy);
}
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;
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

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/entity/Category.dart';
import 'package:satu/core/entity/Goods.dart';
@ -49,7 +47,7 @@ class DictionaryService extends BaseService {
List<Category> list = [];
try {
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) {
list.add(Category.fromMap(element));
});

View File

@ -40,7 +40,7 @@ Route<dynamic> generateRoute(RouteSettings settings) {
case SettingPrinterBluetoothViewRoute:
return _getPageRoute(
routeName: settings.name,
viewToShow: PrinterSelectView(title: 'Принтер печати чеков',),
//viewToShow: PrinterSelectView(title: 'Принтер печати чеков',),
);
// case ImageShowRoute:
// 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:material_design_icons_flutter/material_design_icons_flutter.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/store.dart';
import 'package:satu/core/services/api_service.dart';
import 'package:satu/core/services/dialog_service.dart';
import 'package:satu/core/utils/locator.dart';
import 'package:satu/shared/app_colors.dart';

View File

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

View File

@ -1,4 +1,8 @@
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/utils/locator.dart';
import 'package:satu/routes/route_names.dart';
@ -6,18 +10,22 @@ 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/products_app_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 {
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, SellState>(
converter: (store) => store.state.sellState,
builder: (_, state) {
return Scaffold(
appBar: ProductsAppBar(
title: 'Продажа',
actions: actions(),
elevation: 2.0,
child: ProductHeaderBar(
count: 14,
sum: 25000,
count: state.items.length,
sum: sumProducts(state.items),
),
backgroundColor: backgroundColor,
childHeight: 80,
@ -28,16 +36,16 @@ class SellView extends StatelessWidget {
Expanded(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: 5,
itemCount: state.items.length,
itemBuilder: (BuildContext context, int index) {
ProductDao product = state.items.elementAt(index);
return ProductListItem(
ean: '1234567890123',
ean: product.eanCode,
isOdd: index % 2 == 0,
name:
'Хлеб ржаной который необходимо покупать каждый раз когда придет мысль об этом - ${index + 1}. ',
price: 75,
count: 15,
categoryName: 'Хлебобулочные изделия',
name: product.productName,
price: product.price,
count: product.count,
categoryName: product.productName,
);
},
),
@ -46,6 +54,8 @@ class SellView extends StatelessWidget {
),
);
}
);
}
List<Widget> actions() {
return [

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"
source: hosted
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:
dependency: "direct main"
description:
name: esc_pos_utils
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.6"
version: "1.0.0"
fake_async:
dependency: transitive
description:
@ -174,13 +167,6 @@ packages:
description: flutter
source: sdk
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:
dependency: "direct main"
description:
@ -218,7 +204,7 @@ packages:
name: get_it
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.1"
version: "7.1.2"
hex:
dependency: transitive
description:
@ -239,7 +225,7 @@ packages:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.2"
version: "0.13.3"
http_parser:
dependency: transitive
description:
@ -275,13 +261,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
logger:
dependency: "direct main"
description:
@ -471,13 +450,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.1"
rxdart:
dependency: transitive
description:
name: rxdart
url: "https://pub.dartlang.org"
source: hosted
version: "0.23.1"
searchable_dropdown:
dependency: "direct main"
description:
@ -644,6 +616,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
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:
dependency: transitive
description:

View File

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