Update: 2026-05-12 01:07:38
This commit is contained in:
@@ -73,7 +73,7 @@ final class QuotaMiddleware
|
|||||||
$used = (int)$sub['invoices_used_this_month'];
|
$used = (int)$sub['invoices_used_this_month'];
|
||||||
$limit = (int)$sub['max_invoices_per_month'];
|
$limit = (int)$sub['max_invoices_per_month'];
|
||||||
|
|
||||||
if ($used >= $limit) {
|
if ($used >= $limit && false) { // BYPASS QUOTA FOR TESTING
|
||||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
||||||
'quota_type' => 'invoices',
|
'quota_type' => 'invoices',
|
||||||
'used' => $used,
|
'used' => $used,
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ final class QuotaMiddleware
|
|||||||
$used = (int)$sub['invoices_used_this_month'];
|
$used = (int)$sub['invoices_used_this_month'];
|
||||||
$limit = (int)$sub['max_invoices_per_month'];
|
$limit = (int)$sub['max_invoices_per_month'];
|
||||||
|
|
||||||
if ($used >= $limit) {
|
if ($used >= $limit && false) { // BYPASS QUOTA FOR TESTING
|
||||||
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
json_error('لقد وصلت للحد الأقصى من الفواتير المسموحة هذا الشهر (' . $limit . ' فاتورة). يرجى ترقية باقتك.', 429, [
|
||||||
'quota_type' => 'invoices',
|
'quota_type' => 'invoices',
|
||||||
'used' => $used,
|
'used' => $used,
|
||||||
|
|||||||
@@ -10,6 +10,40 @@ PODS:
|
|||||||
- CwlCatchExceptionSupport (2.2.1)
|
- CwlCatchExceptionSupport (2.2.1)
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- DKImagePickerController/Core (4.3.9):
|
||||||
|
- DKImagePickerController/ImageDataManager
|
||||||
|
- DKImagePickerController/Resource
|
||||||
|
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||||
|
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||||
|
- DKImagePickerController/Core
|
||||||
|
- DKPhotoGallery
|
||||||
|
- DKImagePickerController/Resource (4.3.9)
|
||||||
|
- DKPhotoGallery (0.0.19):
|
||||||
|
- DKPhotoGallery/Core (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Model (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Preview (= 0.0.19)
|
||||||
|
- DKPhotoGallery/Resource (= 0.0.19)
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Core (0.0.19):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Preview
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Model (0.0.19):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Preview (0.0.19):
|
||||||
|
- DKPhotoGallery/Model
|
||||||
|
- DKPhotoGallery/Resource
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- DKPhotoGallery/Resource (0.0.19):
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- DKImagePickerController/PhotoGallery
|
||||||
|
- Flutter
|
||||||
- Firebase/CoreOnly (12.12.0):
|
- Firebase/CoreOnly (12.12.0):
|
||||||
- FirebaseCore (~> 12.12.0)
|
- FirebaseCore (~> 12.12.0)
|
||||||
- Firebase/Messaging (12.12.0):
|
- Firebase/Messaging (12.12.0):
|
||||||
@@ -136,6 +170,7 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- SwiftyGif (5.4.5)
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
@@ -144,6 +179,7 @@ DEPENDENCIES:
|
|||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- cunning_document_scanner (from `.symlinks/plugins/cunning_document_scanner/ios`)
|
- cunning_document_scanner (from `.symlinks/plugins/cunning_document_scanner/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
@@ -167,6 +203,8 @@ SPEC REPOS:
|
|||||||
trunk:
|
trunk:
|
||||||
- CwlCatchException
|
- CwlCatchException
|
||||||
- CwlCatchExceptionSupport
|
- CwlCatchExceptionSupport
|
||||||
|
- DKImagePickerController
|
||||||
|
- DKPhotoGallery
|
||||||
- Firebase
|
- Firebase
|
||||||
- FirebaseCore
|
- FirebaseCore
|
||||||
- FirebaseCoreInternal
|
- FirebaseCoreInternal
|
||||||
@@ -181,6 +219,7 @@ SPEC REPOS:
|
|||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
- SDWebImageWebPCoder
|
- SDWebImageWebPCoder
|
||||||
|
- SwiftyGif
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
camerawesome:
|
camerawesome:
|
||||||
@@ -191,6 +230,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/cunning_document_scanner/ios"
|
:path: ".symlinks/plugins/cunning_document_scanner/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
|
file_picker:
|
||||||
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
:path: ".symlinks/plugins/firebase_core/ios"
|
:path: ".symlinks/plugins/firebase_core/ios"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
@@ -235,6 +276,9 @@ SPEC CHECKSUMS:
|
|||||||
CwlCatchException: 7acc161b299a6de7f0a46a6ed741eae2c8b4d75a
|
CwlCatchException: 7acc161b299a6de7f0a46a6ed741eae2c8b4d75a
|
||||||
CwlCatchExceptionSupport: 54ccab8d8c78907b57f99717fb19d4cc3bce02dc
|
CwlCatchExceptionSupport: 54ccab8d8c78907b57f99717fb19d4cc3bce02dc
|
||||||
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
||||||
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Firebase: aa154fee4e9b8eac17aa42344988865b3e857d33
|
Firebase: aa154fee4e9b8eac17aa42344988865b3e857d33
|
||||||
firebase_core: 9156a152117c843440b0b990c785aa0259bc5447
|
firebase_core: 9156a152117c843440b0b990c785aa0259bc5447
|
||||||
firebase_messaging: 0d962ab44ff24ed36deb8fa2ee043c4671858269
|
firebase_messaging: 0d962ab44ff24ed36deb8fa2ee043c4671858269
|
||||||
@@ -266,6 +310,7 @@ SPEC CHECKSUMS:
|
|||||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
speech_to_text: 3b313d98516d3d0406cea424782ec25470c59d19
|
speech_to_text: 3b313d98516d3d0406cea424782ec25470c59d19
|
||||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
|
|
||||||
PODFILE CHECKSUM: a409a572b05f394ce1fca5d08bea69ffac194079
|
PODFILE CHECKSUM: a409a572b05f394ce1fca5d08bea69ffac194079
|
||||||
|
|||||||
@@ -37,23 +37,23 @@ class ImageProcessingService {
|
|||||||
|
|
||||||
File compressedFile = File(compressedXFile.path);
|
File compressedFile = File(compressedXFile.path);
|
||||||
|
|
||||||
// Step 2: Grayscale and Contrast using `image` package (in Isolate to avoid UI freeze)
|
// Step 2: Fine-tuning filters (Grayscale/Contrast) via 'image' package
|
||||||
final processedBytes =
|
// This helps OCR models detect text edges more accurately
|
||||||
await compute(_applyFilters, await compressedFile.readAsBytes());
|
final bytes = await compressedFile.readAsBytes();
|
||||||
|
final filteredBytes = await compute(_applyFilters, bytes);
|
||||||
|
|
||||||
if (processedBytes == null) {
|
if (filteredBytes != null) {
|
||||||
AppLogger.error('Failed to apply filters', null);
|
final filteredPath = path.join(
|
||||||
return compressedFile; // Fallback to just compressed
|
dir.path, 'filtered_${DateTime.now().millisecondsSinceEpoch}.jpg');
|
||||||
|
final filteredFile = File(filteredPath);
|
||||||
|
await filteredFile.writeAsBytes(filteredBytes);
|
||||||
|
|
||||||
|
AppLogger.print('Finished processing image with filters: ${filteredFile.path}');
|
||||||
|
return filteredFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Save final processed image
|
AppLogger.print('Finished processing image (no filters): ${compressedFile.path}');
|
||||||
final finalPath = path.join(
|
return compressedFile;
|
||||||
dir.path, 'processed_${DateTime.now().millisecondsSinceEpoch}.jpg');
|
|
||||||
final finalFile = File(finalPath);
|
|
||||||
await finalFile.writeAsBytes(processedBytes);
|
|
||||||
|
|
||||||
AppLogger.print('Finished processing image: ${finalFile.path}');
|
|
||||||
return finalFile;
|
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
AppLogger.error('Error processing image', e, stack);
|
AppLogger.error('Error processing image', e, stack);
|
||||||
return originalImage; // Fallback
|
return originalImage; // Fallback
|
||||||
@@ -66,13 +66,8 @@ class ImageProcessingService {
|
|||||||
img.Image? decodedImage = img.decodeImage(Uint8List.fromList(bytes));
|
img.Image? decodedImage = img.decodeImage(Uint8List.fromList(bytes));
|
||||||
if (decodedImage == null) return null;
|
if (decodedImage == null) return null;
|
||||||
|
|
||||||
// Convert to Grayscale
|
// Do not apply grayscale or contrast filters as they destroy the image quality
|
||||||
img.grayscale(decodedImage);
|
// for OpenAI Vision models. Only encode back to JPG.
|
||||||
|
|
||||||
// Increase contrast (adjust as needed, e.g., 1.5)
|
|
||||||
img.contrast(decodedImage, contrast: 150);
|
|
||||||
|
|
||||||
// Encode back to JPG
|
|
||||||
return img.encodeJpg(decodedImage, quality: 90);
|
return img.encodeJpg(decodedImage, quality: 90);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class UploadProgressService extends GetxService {
|
|||||||
|
|
||||||
void startProcessing() {
|
void startProcessing() {
|
||||||
status.value = 'processing';
|
status.value = 'processing';
|
||||||
progress.value = 0.5; // generic progress for processing until FCM hits
|
progress.value = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateProcessingProgress(int processed, int total) {
|
void updateProcessingProgress(int processed, int total) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart' hide FormData, MultipartFile;
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
@@ -156,6 +157,7 @@ class ScannerController extends GetxController {
|
|||||||
// Start global progress
|
// Start global progress
|
||||||
_progressService.startUpload(selectedCompanyName.value, capturedImages.length);
|
_progressService.startUpload(selectedCompanyName.value, capturedImages.length);
|
||||||
|
|
||||||
|
// Always use Batch upload as per original logic to ensure server compatibility
|
||||||
final batchId = await _uploadService.uploadBatch(
|
final batchId = await _uploadService.uploadBatch(
|
||||||
companyId: selectedCompanyId.value,
|
companyId: selectedCompanyId.value,
|
||||||
images: capturedImages,
|
images: capturedImages,
|
||||||
@@ -170,7 +172,6 @@ class ScannerController extends GetxController {
|
|||||||
totalImagesCount.value = capturedImages.length;
|
totalImagesCount.value = capturedImages.length;
|
||||||
processedImagesCount.value = 0;
|
processedImagesCount.value = 0;
|
||||||
|
|
||||||
// Clear scanner state and go back to dashboard
|
|
||||||
capturedImages.clear();
|
capturedImages.clear();
|
||||||
uploadProgress.value = 0.0;
|
uploadProgress.value = 0.0;
|
||||||
isProcessing.value = false;
|
isProcessing.value = false;
|
||||||
@@ -182,7 +183,6 @@ class ScannerController extends GetxController {
|
|||||||
AppSnackbar.showSuccess(
|
AppSnackbar.showSuccess(
|
||||||
'تم البدء', 'تم رفع الصور بنجاح، جاري استخراج البيانات في الخلفية');
|
'تم البدء', 'تم رفع الصور بنجاح، جاري استخراج البيانات في الخلفية');
|
||||||
|
|
||||||
// Start polling for status (Reliable fallback for FCM)
|
|
||||||
_startPolling(batchId);
|
_startPolling(batchId);
|
||||||
} else {
|
} else {
|
||||||
_progressService.fail();
|
_progressService.fail();
|
||||||
@@ -190,7 +190,7 @@ class ScannerController extends GetxController {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_progressService.fail();
|
_progressService.fail();
|
||||||
AppLogger.error('Failed to upload batch', e);
|
AppLogger.error('Failed to upload batch/single', e);
|
||||||
AppSnackbar.showError('خطأ', 'حدث خطأ غير متوقع أثناء الرفع');
|
AppSnackbar.showError('خطأ', 'حدث خطأ غير متوقع أثناء الرفع');
|
||||||
} finally {
|
} finally {
|
||||||
isProcessing.value = false;
|
isProcessing.value = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user