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,10 +24,43 @@ 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 {
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() ProductDao item = new ProductDao()
..id = good.id ..id = good.id
..price = good.price ..price = good.price
@ -39,6 +78,43 @@ ThunkAction<AppState> addSellItem({Good good, String excise}) {
item.categoryId = category.id; 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) { 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> {
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);
// } // }
//
// Print QR Code using native function // class _PrinterSelectViewState extends State<PrinterSelectView> {
// ticket.qrcode('example.com'); // // PrinterBluetoothManager printerManager = PrinterBluetoothManager();
// // List<PrinterBluetooth> _devices = [];
ticket.feed(2); //
ticket.cut(); // @override
return ticket; // void initState() {
} // super.initState();
//
Future<Ticket> testTicket(PaperSize paper) async { // printerManager.scanResults.listen((devices) async {
final Ticket ticket = Ticket(paper); // // print('UI: Devices found ${devices.length}');
Uint8List encTxt4 = // setState(() {
await CharsetConverter.encode("cp866", "Russian: Привет Мир!"); // _devices = devices;
ticket.textEncoded(encTxt4, // });
styles: PosStyles(codeTable: PosCodeTable.pc866_2)); // });
// }
ticket.text('Kazakh: Сәлем Әлем!', //
styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true); // void _startScanDevices() {
// setState(() {
// Uint8List encTxt1 = // _devices = [];
// await CharsetConverter.encode("utf-8", "Kazakh: Сәлем Әлем!"); // });
// ticket.textEncoded(encTxt1, // printerManager.startScan(Duration(seconds: 4));
// 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'); // void _stopScanDevices() {
ticket.text('Special 1: àÀ èÈ éÉ ûÛ üÜ çÇ ôÔ', // printerManager.stopScan();
styles: PosStyles(codeTable: PosCodeTable.westEur)); // }
ticket.text('Special 2: blåbærgrød', //
styles: PosStyles(codeTable: PosCodeTable.westEur)); // Future<Ticket> demoReceipt(PaperSize paper) async {
// final Ticket ticket = Ticket(paper, );
ticket.text('Bold text', styles: PosStyles(bold: true)); //
ticket.text('Reverse text', styles: PosStyles(reverse: true)); // // Print image
ticket.text('Underlined text', // final ByteData data = await rootBundle.load('assets/images/aman_kassa_check.png');
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(); // final Uint8List bytes = data.buffer.asUint8List();
// Print image using alternative commands // final Im.Image image = Im.decodeImage(bytes);
// ticket.imageRaster(image); // Im.Image thumbnail = Im.copyResize(image, width: 270);
// ticket.imageRaster(image, imageFn: PosImageFn.graphics); // // ticket.image(thumbnail, align: PosAlign.center);
//
// Print barcode // //ticket.imageRaster(image, align: PosAlign.center);
final List<int> barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4]; //
ticket.barcode(Barcode.upcA(barData)); // ticket.text('AMAN-SATU',
// styles: PosStyles(
// Print mixed (chinese + latin) text. Only for printers supporting Kanji mode // align: PosAlign.center,
ticket.text( // height: PosTextSize.size2,
'hello ! 中文字 # world @ éphémère &', // width: PosTextSize.size2,
styles: PosStyles(codeTable: PosCodeTable.westEur), // ),
containsChinese: true, // linesAfter: 1);
); //
// ticket.text('889 Watson Lane', styles: PosStyles(align: PosAlign.center));
ticket.text( // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, codeTable: PosCodeTable.westEur), containsChinese: true);
'hello ! Мир # world @ éphémère &', // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontA), containsChinese: true);
styles: PosStyles(codeTable: PosCodeTable.westEur), // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontB), containsChinese: true);
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.feed(2); // ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size4), containsChinese: true);
// ticket.text('Tel: 830-221-1234', styles: PosStyles(align: PosAlign.center));
ticket.cut(); // ticket.text('Web: www.example.com',
return ticket; // styles: PosStyles(align: PosAlign.center), linesAfter: 1);
} //
// ticket.hr();
void _testPrint(PrinterBluetooth printer) async { // ticket.row([
printerManager.selectPrinter(printer); // PosColumn(text: 'Qty', width: 1),
// PosColumn(text: 'Item', width: 7),
// TODO Don't forget to choose printer's paper // PosColumn(
const PaperSize paper = PaperSize.mm58; // text: 'Price', width: 2, styles: PosStyles(align: PosAlign.right)),
// PosColumn(
// TEST PRINT // 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 = // final PosPrintResult res =
// await printerManager.printTicket(await testTicket(paper)); // await printerManager.printTicket(await testTicket(paper) , queueSleepTimeMs: 50);
//
// DEMO RECEIPT // }
final PosPrintResult res = //
await printerManager.printTicket(await testTicket(paper) , queueSleepTimeMs: 50); // @override
// Widget build(BuildContext context) {
} // return Scaffold(
// appBar: AppBar(
@override // title: Text(widget.title),
Widget build(BuildContext context) { // ),
return Scaffold( // body: ListView.builder(
appBar: AppBar( // itemCount: _devices.length,
title: Text(widget.title), // itemBuilder: (BuildContext context, int index) {
), // return InkWell(
body: ListView.builder( // onTap: () => _testPrint(_devices[index]),
itemCount: _devices.length, // child: Column(
itemBuilder: (BuildContext context, int index) { // children: <Widget>[
return InkWell( // Container(
onTap: () => _testPrint(_devices[index]), // height: 60,
child: Column( // padding: EdgeInsets.only(left: 10),
children: <Widget>[ // alignment: Alignment.centerLeft,
Container( // child: Row(
height: 60, // children: <Widget>[
padding: EdgeInsets.only(left: 10), // Icon(Icons.print),
alignment: Alignment.centerLeft, // SizedBox(width: 10),
child: Row( // Expanded(
children: <Widget>[ // child: Column(
Icon(Icons.print), // crossAxisAlignment: CrossAxisAlignment.start,
SizedBox(width: 10), // mainAxisAlignment: MainAxisAlignment.center,
Expanded( // children: <Widget>[
child: Column( // Text(_devices[index].name ?? ''),
crossAxisAlignment: CrossAxisAlignment.start, // Text(_devices[index].address),
mainAxisAlignment: MainAxisAlignment.center, // Text(
children: <Widget>[ // 'Click to print a test receipt',
Text(_devices[index].name ?? ''), // style: TextStyle(color: Colors.grey[700]),
Text(_devices[index].address), // ),
Text( // ],
'Click to print a test receipt', // ),
style: TextStyle(color: Colors.grey[700]), // )
), // ],
], // ),
), // ),
) // Divider(),
], // ],
), // ),
), // );
Divider(), // }),
], // floatingActionButton: StreamBuilder<bool>(
), // stream: printerManager.isScanningStream,
); // initialData: false,
}), // builder: (c, snapshot) {
floatingActionButton: StreamBuilder<bool>( // if (snapshot.data) {
stream: printerManager.isScanningStream, // return FloatingActionButton(
initialData: false, // child: Icon(Icons.stop),
builder: (c, snapshot) { // onPressed: _stopScanDevices,
if (snapshot.data) { // backgroundColor: Colors.red,
return FloatingActionButton( // );
child: Icon(Icons.stop), // } else {
onPressed: _stopScanDevices, // return FloatingActionButton(
backgroundColor: Colors.red, // child: Icon(Icons.search),
); // onPressed: _startScanDevices,
} else { // );
return FloatingActionButton( // }
child: Icon(Icons.search), // },
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,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/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 StoreConnector<AppState, SellState>(
converter: (store) => store.state.sellState,
builder: (_, state) {
return Scaffold( return Scaffold(
appBar: ProductsAppBar( appBar: ProductsAppBar(
title: 'Продажа', title: 'Продажа',
actions: actions(), actions: actions(),
elevation: 2.0, elevation: 2.0,
child: ProductHeaderBar( child: ProductHeaderBar(
count: 14, count: state.items.length,
sum: 25000, sum: sumProducts(state.items),
), ),
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
childHeight: 80, childHeight: 80,
@ -28,16 +36,16 @@ class SellView extends StatelessWidget {
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
physics: BouncingScrollPhysics(), physics: BouncingScrollPhysics(),
itemCount: 5, itemCount: state.items.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
ProductDao product = state.items.elementAt(index);
return ProductListItem( return ProductListItem(
ean: '1234567890123', ean: product.eanCode,
isOdd: index % 2 == 0, isOdd: index % 2 == 0,
name: name: product.productName,
'Хлеб ржаной который необходимо покупать каждый раз когда придет мысль об этом - ${index + 1}. ', price: product.price,
price: 75, count: product.count,
count: 15, categoryName: product.productName,
categoryName: 'Хлебобулочные изделия',
); );
}, },
), ),
@ -46,6 +54,8 @@ class SellView extends StatelessWidget {
), ),
); );
} }
);
}
List<Widget> actions() { List<Widget> actions() {
return [ 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" 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: