Compare commits
3 Commits
9df4b79a66
...
2ff639fc42
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ff639fc42 | ||
|
|
1cfdd2c0c6 | ||
| ff25363a19 |
@@ -38,11 +38,11 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
printing: 54ff03f28fe9ba3aa93358afb80a8595a071dd07
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
||||
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
|
||||
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
|
||||
printing: 233e1b73bd1f4a05615548e9b5a324c98588640b
|
||||
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
|
||||
|
||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||
|
||||
|
||||
210
lib/core/services/sunmi_service.dart
Normal file
210
lib/core/services/sunmi_service.dart
Normal file
@@ -0,0 +1,210 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:sunmi_printer_plus/sunmi_printer_plus.dart';
|
||||
|
||||
/// Service for printing to Sunmi thermal printers
|
||||
class SunmiService {
|
||||
/// Print warehouse export form to Sunmi printer
|
||||
static Future<void> printWarehouseExport({
|
||||
required BuildContext context,
|
||||
required String warehouseName,
|
||||
required int productId,
|
||||
required String productCode,
|
||||
required String productName,
|
||||
String? stageName,
|
||||
required double passedKg,
|
||||
required int passedPcs,
|
||||
required double issuedKg,
|
||||
required int issuedPcs,
|
||||
String? responsibleName,
|
||||
String? receiverName,
|
||||
String? barcodeData,
|
||||
}) async {
|
||||
try {
|
||||
// Format current date
|
||||
final dt = DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now());
|
||||
|
||||
// Title - PHIẾU XUẤT KHO
|
||||
await SunmiPrinter.printText(
|
||||
'PHIEU XUAT KHO',
|
||||
style: SunmiTextStyle(
|
||||
align: SunmiPrintAlign.CENTER,
|
||||
bold: true,
|
||||
fontSize: 48,
|
||||
),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Company name
|
||||
await SunmiPrinter.printText(
|
||||
'Cong ty TNHH Co Khi Chinh Xac Minh Thu',
|
||||
style: SunmiTextStyle(
|
||||
align: SunmiPrintAlign.CENTER,
|
||||
fontSize: 32,
|
||||
),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Warehouse name
|
||||
await SunmiPrinter.printText(
|
||||
warehouseName,
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.CENTER),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Date
|
||||
await SunmiPrinter.printText(
|
||||
'Ngay: $dt',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.CENTER),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(2);
|
||||
|
||||
// Separator line
|
||||
await SunmiPrinter.line();
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Product information
|
||||
await SunmiPrinter.printText(
|
||||
'THONG TIN SAN PHAM',
|
||||
style: SunmiTextStyle(
|
||||
align: SunmiPrintAlign.LEFT,
|
||||
bold: true,
|
||||
),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// ProductId
|
||||
await SunmiPrinter.printText(
|
||||
'ProductId: $productId',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Product Code
|
||||
await SunmiPrinter.printText(
|
||||
'Ma san pham: $productCode',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Product Name
|
||||
await SunmiPrinter.printText(
|
||||
'Ten san pham: $productName',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Stage Name
|
||||
await SunmiPrinter.printText(
|
||||
'Cong doan: ${stageName ?? '-'}',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(2);
|
||||
|
||||
// Separator line
|
||||
await SunmiPrinter.line();
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Quantities
|
||||
await SunmiPrinter.printText(
|
||||
'SO LUONG',
|
||||
style: SunmiTextStyle(
|
||||
align: SunmiPrintAlign.LEFT,
|
||||
bold: true,
|
||||
),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Table header
|
||||
await SunmiPrinter.printText(
|
||||
'Loai KG PCS',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.line();
|
||||
|
||||
// Passed quantity (Hàng đạt)
|
||||
final passedLine =
|
||||
'Hang dat ${passedKg.toStringAsFixed(2).padLeft(7)} ${passedPcs.toString().padLeft(5)}';
|
||||
await SunmiPrinter.printText(
|
||||
passedLine,
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
|
||||
// Issued quantity (Hàng lỗi)
|
||||
final issuedLine =
|
||||
'Hang loi ${issuedKg.toStringAsFixed(2).padLeft(7)} ${issuedPcs.toString().padLeft(5)}';
|
||||
await SunmiPrinter.printText(
|
||||
issuedLine,
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(2);
|
||||
|
||||
// Separator line
|
||||
await SunmiPrinter.line();
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Responsible person
|
||||
await SunmiPrinter.printText(
|
||||
'Nhan vien kho: ${responsibleName ?? '-'}',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(1);
|
||||
|
||||
// Receiver
|
||||
await SunmiPrinter.printText(
|
||||
'Nhan vien tiep nhan: ${receiverName ?? '-'}',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.LEFT),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(2);
|
||||
|
||||
// Barcode
|
||||
if (barcodeData != null && barcodeData.isNotEmpty) {
|
||||
await SunmiPrinter.line();
|
||||
await SunmiPrinter.printBarCode(
|
||||
barcodeData,
|
||||
style: SunmiBarcodeStyle(
|
||||
type: SunmiBarcodeType.CODE128,
|
||||
textPos: SunmiBarcodeTextPos.TEXT_UNDER,
|
||||
height: 100,
|
||||
align: SunmiPrintAlign.CENTER,
|
||||
),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(2);
|
||||
}
|
||||
|
||||
// Footer
|
||||
await SunmiPrinter.line();
|
||||
await SunmiPrinter.printText(
|
||||
'Nguoi nhan',
|
||||
style: SunmiTextStyle(align: SunmiPrintAlign.CENTER),
|
||||
);
|
||||
await SunmiPrinter.lineWrap(4);
|
||||
|
||||
// Cut paper
|
||||
await SunmiPrinter.cutPaper();
|
||||
|
||||
// Show success message
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Đã in thành công!'),
|
||||
backgroundColor: Colors.green,
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// Show error message
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Lỗi khi in: ${e.toString()}'),
|
||||
backgroundColor: Colors.red,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class ProductsRemoteDataSourceImpl implements ProductsRemoteDataSource {
|
||||
// The API returns a list of stages for the product
|
||||
final list = json as List;
|
||||
if (list.isEmpty) {
|
||||
throw const ServerException('Product stages not found');
|
||||
throw const ServerException('Không tìm thấy sản phẩm');
|
||||
}
|
||||
// Parse all stages from the list
|
||||
return list
|
||||
|
||||
@@ -4,8 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
|
||||
import '../../../../core/di/providers.dart';
|
||||
import '../../../../core/router/app_router.dart';
|
||||
import '../../../../core/services/print_service.dart';
|
||||
import '../../../../core/services/sunmi_service.dart';
|
||||
import '../../../../core/storage/secure_storage.dart';
|
||||
import '../../../../core/utils/text_utils.dart';
|
||||
import '../../../users/domain/entities/user_entity.dart';
|
||||
@@ -94,7 +93,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
// Get stored current user ID from secure storage
|
||||
final secureStorage = SecureStorage();
|
||||
final currentUserId = await secureStorage.getCurrentUserId();
|
||||
print('user $currentUserId');
|
||||
|
||||
if (currentUserId == null) {
|
||||
return;
|
||||
}
|
||||
@@ -419,7 +418,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Error',
|
||||
'Lỗi',
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
@@ -730,7 +729,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
: 'P${stage.productId}';
|
||||
|
||||
try {
|
||||
await PrintService.printWarehouseExport(
|
||||
await SunmiService.printWarehouseExport(
|
||||
context: context,
|
||||
warehouseName: widget.warehouseName,
|
||||
productId: stage.productId,
|
||||
@@ -749,7 +748,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Error printing: ${e.toString()}'),
|
||||
content: Text('Lỗi khi in: ${e.toString()}'),
|
||||
backgroundColor: Colors.red,
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
@@ -789,8 +788,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print before saving to API
|
||||
await _printQuantities(stage);
|
||||
|
||||
|
||||
// Show loading dialog
|
||||
showDialog(
|
||||
@@ -864,6 +862,9 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
||||
),
|
||||
);
|
||||
|
||||
// Print before saving to API
|
||||
await _printQuantities(stage);
|
||||
|
||||
// Refresh the product detail to show updated quantities
|
||||
await ref.read(productDetailProvider(_providerKey).notifier).refreshProductDetail(
|
||||
widget.warehouseId,
|
||||
|
||||
@@ -33,7 +33,7 @@ class MyApp extends ConsumerWidget {
|
||||
final router = ref.watch(appRouterProvider);
|
||||
|
||||
return MaterialApp.router(
|
||||
title: 'Warehouse Manager',
|
||||
title: 'MinhThu',
|
||||
theme: AppTheme.lightTheme,
|
||||
darkTheme: AppTheme.darkTheme,
|
||||
themeMode: ThemeMode.system,
|
||||
|
||||
@@ -1029,6 +1029,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
sunmi_printer_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sunmi_printer_plus
|
||||
sha256: "77293b7da16bdf3805c5a24ea41731978e8a31da99c3fca38a658a0778450b78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -42,6 +42,7 @@ dependencies:
|
||||
pdf: ^3.11.3
|
||||
barcode_widget: ^2.0.4
|
||||
google_fonts: ^6.2.1
|
||||
sunmi_printer_plus: ^4.1.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user