Update: 2026-05-08 02:11:29

This commit is contained in:
Hamza-Ayed
2026-05-08 02:11:29 +03:00
parent 1cd511f12e
commit b49af44139
8 changed files with 491 additions and 164 deletions

View File

@@ -67,6 +67,79 @@ class InvoiceDetailController extends GetxController {
}
Future<void> approveInvoice() async {
// First check for duplicates
try {
final dupRes = await DioClient().client.post('invoices/check-duplicate', data: {
'invoice_number': invoice['invoice_number'],
'supplier_tin': invoice['supplier_tin'],
'grand_total': invoice['grand_total'],
'invoice_date': invoice['invoice_date'],
'exclude_id': invoiceId,
});
if (dupRes.data['success'] == true) {
final matches = dupRes.data['data']?['matches'] as List? ?? [];
if (matches.isNotEmpty) {
// Show duplicate warning
final proceed = await Get.dialog<bool>(
AlertDialog(
title: const Row(
children: [
Icon(Icons.warning_amber, color: Colors.orange, size: 28),
SizedBox(width: 8),
Text('تحذير — فاتورة مكررة!', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('تم العثور على ${matches.length} فاتورة مشابهة:', style: const TextStyle(fontWeight: FontWeight.w600)),
const SizedBox(height: 12),
...matches.take(3).map((m) => Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.orange.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.orange.withValues(alpha: 0.3)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('رقم: ${m['invoice_number'] ?? ''}', style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600)),
Text('المورد: ${m['supplier_name'] ?? ''}', style: const TextStyle(fontSize: 12)),
Text('المبلغ: ${m['grand_total'] ?? ''} | نوع التطابق: ${m['match_type'] ?? ''}', style: const TextStyle(fontSize: 12, color: Colors.grey)),
],
),
)),
const SizedBox(height: 8),
const Text('هل تريد الاستمرار بالاعتماد؟', style: TextStyle(fontWeight: FontWeight.w600)),
],
),
actions: [
TextButton(
onPressed: () => Get.back(result: false),
child: const Text('إلغاء'),
),
ElevatedButton(
onPressed: () => Get.back(result: true),
style: ElevatedButton.styleFrom(backgroundColor: Colors.orange),
child: const Text('اعتماد رغم التكرار', style: TextStyle(color: Colors.white)),
),
],
),
);
if (proceed != true) return;
}
}
} catch (e) {
// If duplicate check fails, proceed with approval anyway
AppLogger.error('Duplicate check failed (proceeding)', e);
}
// Proceed with approval
try {
final res = await DioClient()
.client
@@ -130,13 +203,16 @@ class InvoiceDetailController extends GetxController {
final bytes = List<int>.from(res.data);
await file.writeAsBytes(bytes);
// Try share, fallback to success message
// Share via native sheet (share_plus v12 API)
try {
await Share.shareXFiles(
[XFile(file.path, mimeType: 'text/csv', name: fileName)],
subject: 'تصدير فواتير مُصادَق',
await SharePlus.instance.share(
ShareParams(
files: [XFile(file.path, mimeType: 'text/csv', name: fileName)],
title: 'تصدير فواتير مُصادَق',
),
);
} catch (_) {
} catch (shareErr) {
AppLogger.error('Share fallback', shareErr);
AppSnackbar.showSuccess('تم الحفظ', 'تم حفظ الملف: ${file.path}');
}
} catch (e) {