asdasdasd
This commit is contained in:
2151
assets/fonts/NotoSans-Bold.ttf
Normal file
2151
assets/fonts/NotoSans-Bold.ttf
Normal file
File diff suppressed because one or more lines are too long
2151
assets/fonts/NotoSans-Regular.ttf
Normal file
2151
assets/fonts/NotoSans-Regular.ttf
Normal file
File diff suppressed because one or more lines are too long
@@ -21,16 +21,25 @@ class PrintService {
|
|||||||
String? responsibleName,
|
String? responsibleName,
|
||||||
String? barcodeData,
|
String? barcodeData,
|
||||||
}) async {
|
}) async {
|
||||||
|
// Load Vietnamese-compatible fonts using PdfGoogleFonts
|
||||||
|
// Noto Sans has excellent Vietnamese character support
|
||||||
|
final fontRegular = await PdfGoogleFonts.notoSansRegular();
|
||||||
|
final fontBold = await PdfGoogleFonts.notoSansBold();
|
||||||
|
|
||||||
final pdf = pw.Document();
|
final pdf = pw.Document();
|
||||||
|
|
||||||
// Format current date
|
// Format current date
|
||||||
final dt = DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now());
|
final dt = DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now());
|
||||||
|
|
||||||
// Add page to PDF
|
// Add page to PDF with theme for Vietnamese font support
|
||||||
pdf.addPage(
|
pdf.addPage(
|
||||||
pw.Page(
|
pw.Page(
|
||||||
pageFormat: PdfPageFormat.a4,
|
pageFormat: PdfPageFormat.a4,
|
||||||
margin: const pw.EdgeInsets.all(12),
|
margin: const pw.EdgeInsets.all(12),
|
||||||
|
theme: pw.ThemeData.withFont(
|
||||||
|
base: fontRegular,
|
||||||
|
bold: fontBold,
|
||||||
|
),
|
||||||
build: (pw.Context pdfContext) {
|
build: (pw.Context pdfContext) {
|
||||||
return pw.Container(
|
return pw.Container(
|
||||||
padding: const pw.EdgeInsets.all(12),
|
padding: const pw.EdgeInsets.all(12),
|
||||||
|
|||||||
@@ -362,12 +362,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
title: 'Thêm số lượng mới',
|
title: 'Thêm số lượng mới',
|
||||||
icon: Icons.add_circle_outline,
|
icon: Icons.add_circle_outline,
|
||||||
children: [
|
children: [
|
||||||
_buildTextField(
|
|
||||||
label: 'Số lượng đạt',
|
|
||||||
controller: _passedQuantityController,
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
theme: theme,
|
|
||||||
),
|
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Khối lượng đạt (kg)',
|
label: 'Khối lượng đạt (kg)',
|
||||||
controller: _passedWeightController,
|
controller: _passedWeightController,
|
||||||
@@ -375,8 +370,8 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
_buildTextField(
|
_buildTextField(
|
||||||
label: 'Số lượng lỗi',
|
label: 'Số lượng đạt',
|
||||||
controller: _issuedQuantityController,
|
controller: _passedQuantityController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
@@ -386,13 +381,20 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
|
_buildTextField(
|
||||||
|
label: 'Số lượng lỗi',
|
||||||
|
controller: _issuedQuantityController,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
theme: theme,
|
||||||
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
_buildSectionCard(theme: theme, title: "Nhân viên", icon: Icons.people, children: [
|
_buildSectionCard(theme: theme, title: "Nhân viên", icon: Icons.people, children: [
|
||||||
// Warehouse User Dropdown
|
// Warehouse User Dropdown (Required)
|
||||||
_buildUserDropdown(
|
_buildUserDropdown(
|
||||||
label: 'Người dùng kho',
|
label: 'Người dùng kho *',
|
||||||
value: _selectedWarehouseUser,
|
value: _selectedWarehouseUser,
|
||||||
users: ref.watch(usersListProvider)
|
users: ref.watch(usersListProvider)
|
||||||
.where((user) => user.isWareHouseUser)
|
.where((user) => user.isWareHouseUser)
|
||||||
@@ -405,9 +407,9 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
theme: theme,
|
theme: theme,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
// All Employees Dropdown
|
// All Employees Dropdown (Required)
|
||||||
_buildUserDropdown(
|
_buildUserDropdown(
|
||||||
label: 'Nhân viên',
|
label: 'Nhân viên *',
|
||||||
value: _selectedEmployee,
|
value: _selectedEmployee,
|
||||||
users: ref.watch(usersListProvider),
|
users: ref.watch(usersListProvider),
|
||||||
onChanged: (user) {
|
onChanged: (user) {
|
||||||
@@ -448,6 +450,18 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _printQuantities(ProductStageEntity stage) async {
|
Future<void> _printQuantities(ProductStageEntity stage) async {
|
||||||
|
// Validate that both users are selected
|
||||||
|
if (_selectedEmployee == null || _selectedWarehouseUser == null) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Vui lòng chọn cả Nhân viên và Người dùng kho trước khi in'),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
duration: Duration(seconds: 3),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the current quantity values (entered by user or use current values)
|
// Get the current quantity values (entered by user or use current values)
|
||||||
final passedQuantity = int.tryParse(_passedQuantityController.text) ?? 0;
|
final passedQuantity = int.tryParse(_passedQuantityController.text) ?? 0;
|
||||||
final passedWeight = double.tryParse(_passedWeightController.text) ?? 0.0;
|
final passedWeight = double.tryParse(_passedWeightController.text) ?? 0.0;
|
||||||
@@ -461,9 +475,7 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
final finalIssuedKg = issuedWeight > 0.0 ? issuedWeight : stage.issuedQuantityWeight;
|
final finalIssuedKg = issuedWeight > 0.0 ? issuedWeight : stage.issuedQuantityWeight;
|
||||||
|
|
||||||
// Get responsible user name
|
// Get responsible user name
|
||||||
final responsibleName = _selectedWarehouseUser != null
|
final responsibleName = '${_selectedWarehouseUser!.name} ${_selectedWarehouseUser!.firstName}';
|
||||||
? '${_selectedWarehouseUser!.name} ${_selectedWarehouseUser!.firstName}'
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Generate barcode data (using product code or product ID)
|
// Generate barcode data (using product code or product ID)
|
||||||
final barcodeData = stage.productCode.isNotEmpty
|
final barcodeData = stage.productCode.isNotEmpty
|
||||||
@@ -521,8 +533,9 @@ class _ProductDetailPageState extends ConsumerState<ProductDetailPage> {
|
|||||||
if (_selectedEmployee == null || _selectedWarehouseUser == null) {
|
if (_selectedEmployee == null || _selectedWarehouseUser == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text('Vui lòng chọn cả Nhân viên và Người dùng kho'),
|
content: Text('Vui lòng chọn cả Nhân viên và Người dùng kho trước khi lưu'),
|
||||||
backgroundColor: Colors.orange,
|
backgroundColor: Colors.orange,
|
||||||
|
duration: Duration(seconds: 3),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -480,6 +480,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "13.2.5"
|
version: "13.2.5"
|
||||||
|
google_fonts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_fonts
|
||||||
|
sha256: "517b20870220c48752eafa0ba1a797a092fb22df0d89535fd9991e86ee2cdd9c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.3.2"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ dependencies:
|
|||||||
printing: ^5.13.4
|
printing: ^5.13.4
|
||||||
pdf: ^3.11.3
|
pdf: ^3.11.3
|
||||||
barcode_widget: ^2.0.4
|
barcode_widget: ^2.0.4
|
||||||
|
google_fonts: ^6.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -63,6 +64,7 @@ flutter:
|
|||||||
# Assets
|
# Assets
|
||||||
assets:
|
assets:
|
||||||
- assets/app_icon.jpg
|
- assets/app_icon.jpg
|
||||||
|
- assets/fonts/
|
||||||
|
|
||||||
# Flutter Launcher Icons Configuration
|
# Flutter Launcher Icons Configuration
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
|
|||||||
Reference in New Issue
Block a user