Aidra Driver 1.3.5+68
Aidra Driver - Your path to green energy
Loading...
Searching...
No Matches
delivery_voucher_pdf.dart
Go to the documentation of this file.
1import 'dart:convert';
2import 'dart:developer';
3import 'dart:io';
4import 'package:aidra_drive/core/constants/assets.dart';
5import 'package:flutter/services.dart';
6import 'package:open_file/open_file.dart';
7import 'package:path_provider/path_provider.dart';
8import 'package:pdf/pdf.dart';
9import 'package:pdf/widgets.dart' as pw;
10
11import '../../common/models/manifest_document.dart';
12
14 ManifestDocument manifest,
15) async {
16 final pdf = pw.Document();
17 pw.MemoryImage? driverSignatureImage;
18 pw.MemoryImage? warehouseSignatureImage;
19 try {
20 final String? driverSignatureBase64 = manifest.driverSignature;
21 final String? warehouseSignatureBase64 = manifest.warehouseSignature;
22 if (warehouseSignatureBase64!= null && warehouseSignatureBase64.isNotEmpty) {
23 final Uint8List signatureData = base64Decode(warehouseSignatureBase64);
24 warehouseSignatureImage = pw.MemoryImage(signatureData);
25 }
26 if (driverSignatureBase64 != null && driverSignatureBase64.isNotEmpty) {
27 final Uint8List signatureData = base64Decode(driverSignatureBase64);
28 driverSignatureImage = pw.MemoryImage(signatureData);
29 }
30 } catch (e) {
31 log('Error loading signature: $e');
32 }
33
34 final ByteData logoBytes = await rootBundle.load(Assets.tajmielogo);
35 final Uint8List logoData = logoBytes.buffer.asUint8List();
36 final pw.MemoryImage logoImage = pw.MemoryImage(logoData);
37
38 final fontData = await rootBundle.load('assets/fonts/cairo_regular_font.ttf');
39 final ttf = pw.Font.ttf(fontData);
40
41 final theme = pw.ThemeData.withFont(
42 base: ttf,
43 bold: ttf,
44 italic: ttf,
45 boldItalic: ttf,
46 );
47
48 String formatDate(DateTime? date) {
49 if (date == null) return '--';
50 return '${date.day}/${date.month}/${date.year}';
51 }
52
53 pdf.addPage(
54 pw.Page(
55 theme: theme,
56 pageFormat: PdfPageFormat.a4,
57 build: (pw.Context context) {
58 return pw.Column(
59 crossAxisAlignment: pw.CrossAxisAlignment.start,
60 children: [
61 // Header
62 pw.Row(
63 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
64 children: [
65 pw.Image(logoImage, width: 80, height: 80),
66 pw.Column(
67 children: [
68 pw.Text(
69 'DELIVERY VOUCHER',
70 style: pw.TextStyle(
71 fontSize: 24,
72 fontWeight: pw.FontWeight.bold,
73 ),
74 ),
75 pw.SizedBox(height: 10),
76 pw.Text(
77 'Document Number: WB-2515422',
78 style: pw.TextStyle(
79 fontSize: 14,
80 fontWeight: pw.FontWeight.bold,
81 ),
82 ),
83 ],
84 ),
85 ],
86 ),
87 pw.SizedBox(height: 20),
88
89 // Main table with left column
90 pw.Container(
91 decoration: pw.BoxDecoration(
92 border: pw.Border.all(),
93 ),
94 child: pw.Row(
95 crossAxisAlignment: pw.CrossAxisAlignment.start,
96 children: [
97 // Left column (approximately 40% of width)
98 pw.Expanded(
99 flex: 2,
100 child: pw.Column(
101 children: [
102 _buildTableRowForSide([
103 pw.Text('Weighbridge Ticket', style: pw.TextStyle(fontSize: 10)),
104 ], isHeader: true),
105 pw.Container(
106 height: 80,
107 decoration: pw.BoxDecoration(
108 color: PdfColors.white,
109 border: pw.Border.all(width: 0),
110 borderRadius:
111 const pw.BorderRadius.all(pw.Radius.zero),
112 ),
113 ),
114 _buildTableRowForSide([
115 pw.Text('Delivery Instructions Comments', style: pw.TextStyle(fontSize: 10)),
116 ], isHeader: true),
117 pw.Container(
118 height: 80,
119 decoration: pw.BoxDecoration(
120 color: PdfColors.white,
121 border: pw.Border.all(width: 0),
122 borderRadius:
123 const pw.BorderRadius.all(pw.Radius.zero),
124 ),
125 ),
126 pw.Container(
127 height: 200,
128 decoration: pw.BoxDecoration(
129 color: PdfColors.white,
130 border: pw.Border.all(width: 0),
131 borderRadius:
132 const pw.BorderRadius.all(pw.Radius.zero),
133 ),
134 child: pw.Column(
135 mainAxisAlignment: pw.MainAxisAlignment.center,
136 children: [
137 pw.Text(
138 'Oil Collection for Waste Transfer Company (ORTCP)',
139 style: pw.TextStyle(
140 fontWeight: pw.FontWeight.bold),
141 textAlign: pw.TextAlign.center,
142 ),
143 pw.SizedBox(height: 5),
144 pw.Text('Al-Karj Road, Riyadh'),
145 pw.Text('H.O.: P.O. Box 14339'),
146 pw.Text('Riyadh City 14339 - Saudi Arabia'),
147 pw.Text('Tel: 011 240 3700'),
148 ],
149 ),
150 ),
151 ],
152 ),
153 ),
154
155 // Right column (approximately 60% of width)
156 pw.Expanded(
157 flex: 3,
158 child: pw.Column(
159 children: [
160 // First row - Weights and Date
161 _buildTableRowForSide([
162 pw.Text('1st Weight', style: pw.TextStyle(fontSize: 10)),
163 pw.Text('2nd Weight', style: pw.TextStyle(fontSize: 10)),
164 pw.Text('Date/Time', style: pw.TextStyle(fontSize: 10)),
165 pw.Text('In / Out', style: pw.TextStyle(fontSize: 10)),
166 ], isHeader: true),
167
168 _buildTableRowForSide([
169 pw.Text('${manifest.firstWeight ?? ''}', style: pw.TextStyle(fontSize: 9)),
170 pw.Text('${manifest.secondWeight ?? ''}', style: pw.TextStyle(fontSize: 9)),
171 pw.Text(formatDate(manifest.collectionDate), style: pw.TextStyle(fontSize: 9)),
172 pw.Text('In', style: pw.TextStyle(fontSize: 9)),
173 ]),
174
175 // Second row - Transporter info
176 pw.Container(
177 height: 40,
178 decoration: pw.BoxDecoration(
179 color: PdfColors.grey200,
180 border: pw.Border.all(width: 0),
181 borderRadius:
182 const pw.BorderRadius.all(pw.Radius.zero),
183 ),
184 child: pw.Row(
185 children: [
186 pw.Expanded(
187 flex: 1,
188 child: pw.Container(
189 alignment: pw.Alignment.center,
190 decoration: pw.BoxDecoration(
191 border: pw.Border(
192 right: pw.BorderSide(),
193 bottom: pw.BorderSide()),
194 ),
195 child: pw.Text(
196 'Transporter',
197 style: pw.TextStyle(fontSize: 10),
198 ),
199 ),
200 ),
201 pw.Expanded(
202 flex: 1,
203 child: pw.Container(
204 alignment: pw.Alignment.center,
205 decoration: pw.BoxDecoration(
206 border: pw.Border(
207 right: pw.BorderSide(),
208 bottom: pw.BorderSide()),
209 ),
210 child: pw.Text(
211 'Transaction No.',
212 style: pw.TextStyle(fontSize: 10),
213 ),
214 ),
215 ),
216 pw.Expanded(
217 flex: 2,
218 child: pw.Container(
219 alignment: pw.Alignment.center,
220 decoration: pw.BoxDecoration(
221 border: pw.Border(bottom: pw.BorderSide()),
222 ),
223 child: pw.Text(
224 'Truck No.',
225 style: pw.TextStyle(fontSize: 10),
226 ),
227 ),
228 ),
229 ],
230 ),
231 ),
232
233 // Empty row for the transporter section
234 pw.Container(
235 height: 40,
236 decoration: pw.BoxDecoration(
237 color: PdfColors.white,
238 border: pw.Border.all(width: 0),
239 ),
240 child: pw.Row(
241 children: [
242 pw.Expanded(
243 flex: 1,
244 child: pw.Container(
245 alignment: pw.Alignment.center,
246 decoration: pw.BoxDecoration(
247 border: pw.Border(
248 right: pw.BorderSide(),
249 bottom: pw.BorderSide()),
250 ),
251 child: pw.Text('', style: pw.TextStyle(fontSize: 9)),
252 ),
253 ),
254 pw.Expanded(
255 flex: 1,
256 child: pw.Container(
257 alignment: pw.Alignment.center,
258 decoration: pw.BoxDecoration(
259 border: pw.Border(
260 right: pw.BorderSide(),
261 bottom: pw.BorderSide()),
262 ),
263 child: pw.Text(manifest.reference ?? '', style: pw.TextStyle(fontSize: 9)),
264 ),
265 ),
266 pw.Expanded(
267 flex: 2,
268 child: pw.Container(
269 alignment: pw.Alignment.center,
270 decoration: pw.BoxDecoration(
271 border: pw.Border(bottom: pw.BorderSide()),
272 ),
273 child: pw.Text(manifest.vehiclePlate ?? '', style: pw.TextStyle(fontSize: 9)),
274 ),
275 ),
276 ],
277 ),
278 ),
279
280 // Raw Material section
281 _buildTableRowForSide([
282 pw.Text('Raw Material', style: pw.TextStyle(fontSize: 9)),
283 pw.Text('Net Weight', style: pw.TextStyle(fontSize: 10)),
284 pw.Text('Price/Tonne', style: pw.TextStyle(fontSize: 10)),
285 pw.Text('Total Price', style: pw.TextStyle(fontSize: 10)),
286 ], isHeader: true),
287
288 _buildTableRowForSide([
289 pw.Text(manifest.productName?.get('en_US') ?? '', style: pw.TextStyle(fontSize: 9)),
290 pw.Text('${manifest.totalQuantity ?? ''}', style: pw.TextStyle(fontSize: 9)),
291 pw.Text('', style: pw.TextStyle(fontSize: 9)),
292 pw.Text('', style: pw.TextStyle(fontSize: 9)),
293 ]),
294
295 // Rest of the form - Signatures
296 pw.Container(
297 child: pw.Column(
298 children: [
299 // Driver section
300 _buildTableRowForSide([
301 pw.Text('Driver Name', style: pw.TextStyle(fontSize: 10)),
302 pw.Text('Driver Signature', style: pw.TextStyle(fontSize: 10)),
303 ], columnSpans: [
304 1,
305 1
306 ], isHeader: true),
307
308 _buildTableRowForSide([
309 pw.Text(manifest.driver?.name ?? '', style: pw.TextStyle(fontSize: 9)),
310 pw.Container(
311 child: pw.Image(driverSignatureImage!)
312 ),
313 ], columnSpans: [
314 1,
315 1
316 ], rowHeight: 60),
317
318 // Operator section
319 _buildTableRowForSide([
320 pw.Text('Weighbridge Operator', style: pw.TextStyle(fontSize: 10)),
321 pw.Text('Operator Signature', style: pw.TextStyle(fontSize: 10)),
322 ], columnSpans: [
323 1,
324 1
325 ], isHeader: true),
326
327 _buildTableRowForSide([
328 pw.Text(manifest.warehouseResponsible ?? 'N/A', style: pw.TextStyle(fontSize: 9)),
329 pw.Container(
330 child: pw.Image(warehouseSignatureImage!)
331 ),
332 ], columnSpans: [
333 1,
334 1
335 ], rowHeight: 60),
336 ],
337 ),
338 ),
339 ],
340 ),
341 ),
342 ],
343 ),
344 ),
345 ],
346 );
347 },
348 ),
349 );
350
351 final output = await getTemporaryDirectory();
352 final file = File('${output.path}/delivery_voucher.pdf');
353 await file.writeAsBytes(await pdf.save());
354 OpenFile.open(file.path);
355}
356
357pw.Widget _buildTableRowForSide(
358 List<pw.Widget> cells, {
359 List<int>? columnSpans,
360 bool isHeader = false,
361 double rowHeight = 40,
362}) {
363 final spans = columnSpans ?? List.filled(cells.length, 1);
364
365 return pw.Container(
366 height: rowHeight,
367 decoration: pw.BoxDecoration(
368 color: isHeader ? PdfColors.grey200 : PdfColors.white,
369 border: pw.Border(bottom: pw.BorderSide()),
370 ),
371 child: pw.Row(
372 children: List.generate(
373 cells.length,
374 (index) => pw.Expanded(
375 flex: spans[index],
376 child: pw.Container(
377 alignment: pw.Alignment.center,
378 decoration: pw.BoxDecoration(
379 border: index < cells.length - 1
380 ? pw.Border(right: pw.BorderSide())
381 : null,
382 ),
383 child: pw.Padding(
384 padding: pw.EdgeInsets.all(5),
385 child: cells[index],
386 // child: pw.Text(
387 // cells[index],
388 // style: pw.TextStyle(
389 // fontWeight: isHeader ? pw.FontWeight.bold : null,
390 // fontSize: 10,
391 // ),
392 // ),
393 ),
394 ),
395 ),
396 ),
397 ),
398 );
399}
class App extends StatefulWidget build(BuildContext context)
Definition app.dart:31
static const String tajmielogo
Definition assets.dart:4
final String driverSignature
final String warehouseSignature
final Widget child
final EdgeInsets padding
class Partner String
Future< void > generateDeliveryVoucher(ManifestDocument manifest,) async
final Color color
Definition failures.dart:1
final String date