h-1.flutter.0/lib/services/shipping_label_service.dart
2026-03-04 14:55:40 +09:00

101 lines
4.8 KiB
Dart

import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:intl/intl.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import '../models/shipment_models.dart';
import 'company_repository.dart';
class ShippingLabelService {
ShippingLabelService({CompanyRepository? companyRepository})
: _companyRepository = companyRepository ?? CompanyRepository();
final CompanyRepository _companyRepository;
Future<String?> generateLabel(Shipment shipment) async {
try {
final company = await _companyRepository.getCompanyInfo();
final fontData = await rootBundle.load('assets/fonts/ipaexg.ttf');
final ipaex = pw.Font.ttf(fontData);
final dateFormat = DateFormat('yyyy/MM/dd');
final pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: PdfPageFormat.a5,
margin: const pw.EdgeInsets.all(20),
build: (context) {
return pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: [
pw.Text('出荷ラベル', style: pw.TextStyle(fontSize: 20, fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.SizedBox(height: 8),
pw.Text('発行日: ${dateFormat.format(DateTime.now())}', style: pw.TextStyle(font: ipaex)),
pw.Divider(),
pw.Text('差出人', style: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.Text(company.name, style: pw.TextStyle(font: ipaex)),
if (company.address != null) pw.Text(company.address!, style: pw.TextStyle(font: ipaex)),
if (company.tel != null) pw.Text('TEL: ${company.tel}', style: pw.TextStyle(font: ipaex)),
pw.SizedBox(height: 12),
pw.Text('宛先', style: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.Text(shipment.customerNameSnapshot ?? '取引先未設定', style: pw.TextStyle(fontSize: 16, font: ipaex)),
if (shipment.orderNumberSnapshot != null)
pw.Text('受注番号: ${shipment.orderNumberSnapshot}', style: pw.TextStyle(font: ipaex)),
pw.SizedBox(height: 12),
pw.Text('配送情報', style: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.Text('配送業者: ${shipment.carrierName ?? '-'}', style: pw.TextStyle(font: ipaex)),
pw.Text('追跡番号: ${shipment.trackingNumber ?? '-'}', style: pw.TextStyle(font: ipaex)),
if (shipment.trackingUrl != null && shipment.trackingUrl!.isNotEmpty)
pw.Text('追跡URL: ${shipment.trackingUrl}', style: pw.TextStyle(font: ipaex)),
pw.SizedBox(height: 12),
pw.Text('出荷明細', style: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.SizedBox(height: 6),
if (shipment.items.isEmpty)
pw.Text('明細登録なし', style: pw.TextStyle(font: ipaex))
else
pw.TableHelper.fromTextArray(
headers: const ['品目', '数量'],
data: shipment.items
.map(
(item) => [
item.description,
item.quantity.toString(),
],
)
.toList(),
headerStyle: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex),
cellStyle: pw.TextStyle(font: ipaex),
columnWidths: const {
0: pw.FlexColumnWidth(3),
1: pw.FlexColumnWidth(1),
},
),
if (shipment.notes?.isNotEmpty == true) ...[
pw.SizedBox(height: 12),
pw.Text('備考', style: pw.TextStyle(fontWeight: pw.FontWeight.bold, font: ipaex)),
pw.Text(shipment.notes!, style: pw.TextStyle(font: ipaex)),
],
],
);
},
),
);
final directory = await getApplicationDocumentsDirectory();
final timestamp = DateFormat('yyyyMMdd_HHmmss').format(DateTime.now());
final orderFragment = shipment.orderNumberSnapshot ?? shipment.id.substring(0, 6);
final fileName = 'shipping_label_${orderFragment}_$timestamp.pdf';
final file = File(p.join(directory.path, fileName));
await file.writeAsBytes(await pdf.save());
return file.path;
} catch (e) {
debugPrint('Shipping label generation failed: $e');
return null;
}
}
}