asdasdasd

This commit is contained in:
Phuoc Nguyen
2025-10-29 16:31:04 +07:00
parent c12869b01f
commit efcc6306b0
6 changed files with 4351 additions and 17 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -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),

View File

@@ -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;

View File

@@ -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:

View File

@@ -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: