قرار المالك 2026-07-27: باك إند سيرو PHP هو المعتمد، وتطبيقاته المجرّبة ميدانياً تحل محل إعادة البناء المؤرشفة. سيرو نفسه لم يُمسّ. الخريطة: backend · payment_server · loction_server · ride_server · passenger_server · docker · dashboard · stress_test → الجذر siro_rider → apps/rider siro_driver → apps/driver siro_admin → dashboards/admin siro_service → dashboards/service android_bot → apps/android_bot socialBot → apps/socialBot نُسخ المتعقَّب في git سيرو فقط عبر `git archive` (3,198 ملفاً / ~169 م.ب) لا `cp -r` — فاستُثنيت مخلفات البناء تلقائياً. بلا أي تعديل محتوى عمداً: كل ما يلي يصير فرقاً مقروءاً مقابل المصدر. لم يُستورد وسببه: siromove.com (الموقع التسويقي يبقى marketing/ في تريبز، سيرو فيه 8 ملفات) · docs و planning (تريبز له docs/ الخاص) · deploy.sh (ليس نشراً على سيرفر بل `git add . && git push origin --all` — فخّ في مستودع آخر) · transit_dashboard (بانتظار قرار مصير backend-transit و dashboards/transit-web). ⚠️ لا يبني بعد — ثلاثة نواقص متوقعة ومقصودة: 1. `.env` و `lib/env/env.g.dart` غير متعقَّبين في سيرو (أسرار لكل مستأجر): كل تطبيق فلاتر يحتاج .env خاصاً ثم توليد env.g.dart بـ build_runner. 2. إعدادات Firebase (9 ملفات google-services.json و GoogleService-Info.plist) يستبعدها .gitignore تريبز — ولكل مستأجر مشروع Firebase خاص أصلاً. 3. apps/driver في سيرو يشير إلى `../../Intaleq/packages/get` خارج المستودع → يجب ضمّ الحزم داخله أسوة بـ apps/rider. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
140 lines
4.4 KiB
Dart
140 lines
4.4 KiB
Dart
import 'dart:convert';
|
|
import 'package:siro_rider/constant/table_names.dart';
|
|
import 'package:siro_rider/main.dart';
|
|
|
|
class DbSql {
|
|
static final DbSql instance = DbSql._();
|
|
DbSql._();
|
|
|
|
// Helper to read data as a list of maps from GetStorage
|
|
List<Map<String, dynamic>> _readTable(String table) {
|
|
String? dataString = box.read(table);
|
|
if (dataString == null) return [];
|
|
try {
|
|
List<dynamic> parsed = jsonDecode(dataString);
|
|
return parsed.map((e) => Map<String, dynamic>.from(e)).toList();
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// Helper to write data back to GetStorage
|
|
void _writeTable(String table, List<Map<String, dynamic>> data) {
|
|
box.write(table, jsonEncode(data));
|
|
}
|
|
|
|
Future<List<Map<String, dynamic>>> getAllData(String table) async {
|
|
return _readTable(table);
|
|
}
|
|
|
|
Future<List<Map<String, dynamic>>> getCustomQuery(String query) async {
|
|
String q = query.toLowerCase();
|
|
String targetTable = TableName.recentLocations; // Default target
|
|
|
|
// Determine the table
|
|
if (q.contains(TableName.recentLocations.toLowerCase())) {
|
|
targetTable = TableName.recentLocations;
|
|
} else if (q.contains(TableName.carLocations.toLowerCase())) {
|
|
targetTable = TableName.carLocations;
|
|
} else if (q.contains(TableName.placesFavorite.toLowerCase())) {
|
|
targetTable = TableName.placesFavorite;
|
|
}
|
|
|
|
List<Map<String, dynamic>> data = _readTable(targetTable);
|
|
|
|
// Apply DISTINCT logic if needed based on query
|
|
if (q.contains('distinct latitude, longitude, name, rate')) {
|
|
// Manual distinct by name and location
|
|
Map<String, Map<String, dynamic>> distinctMap = {};
|
|
for (var item in data) {
|
|
String key = '${item['latitude']}_${item['longitude']}_${item['name']}';
|
|
if (!distinctMap.containsKey(key)) {
|
|
distinctMap[key] = item;
|
|
}
|
|
}
|
|
data = distinctMap.values.toList();
|
|
}
|
|
|
|
// Apply ORDER BY createdAt DESC logic
|
|
if (q.contains('order by createdat desc')) {
|
|
data.sort((a, b) {
|
|
String dateA = a['createdAt'] ?? '';
|
|
String dateB = b['createdAt'] ?? '';
|
|
return dateB.compareTo(dateA);
|
|
});
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
Future<int> insertData(Map<String, dynamic> map, String table) async {
|
|
List<Map<String, dynamic>> data = _readTable(table);
|
|
// Generate simple ID
|
|
int newId = data.isEmpty ? 1 : (data.last['id'] as int? ?? 0) + 1;
|
|
Map<String, dynamic> newMap = Map<String, dynamic>.from(map);
|
|
newMap['id'] = newId;
|
|
data.add(newMap);
|
|
_writeTable(table, data);
|
|
return newId;
|
|
}
|
|
|
|
Future<int> insertMapLocation(Map<String, dynamic> map, String table) async {
|
|
List<Map<String, dynamic>> data = _readTable(table);
|
|
|
|
// Check if exists
|
|
int existingIndex = data.indexWhere((element) =>
|
|
element['latitude'] == map['latitude'] &&
|
|
element['longitude'] == map['longitude'] &&
|
|
element['name'] == map['name']);
|
|
|
|
if (existingIndex != -1) {
|
|
// Update
|
|
data[existingIndex] = Map<String, dynamic>.from(data[existingIndex]);
|
|
data[existingIndex]['createdAt'] = DateTime.now().toIso8601String();
|
|
for (var key in map.keys) {
|
|
if (key != 'latitude' && key != 'longitude' && key != 'name') {
|
|
data[existingIndex][key] = map[key];
|
|
}
|
|
}
|
|
_writeTable(table, data);
|
|
return data[existingIndex]['id'] as int? ?? 1;
|
|
} else {
|
|
// Insert
|
|
int newId = data.isEmpty ? 1 : ((data.last['id'] as int?) ?? 0) + 1;
|
|
Map<String, dynamic> newMap = Map<String, dynamic>.from(map);
|
|
newMap['id'] = newId;
|
|
newMap['createdAt'] = DateTime.now().toIso8601String();
|
|
data.add(newMap);
|
|
_writeTable(table, data);
|
|
return newId;
|
|
}
|
|
}
|
|
|
|
Future<int> updateData(Map<String, dynamic> map, String table, int id) async {
|
|
List<Map<String, dynamic>> data = _readTable(table);
|
|
int index = data.indexWhere((element) => element['id'] == id);
|
|
if (index != -1) {
|
|
data[index] = {...data[index], ...map};
|
|
_writeTable(table, data);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Future<int> deleteData(String table, int id) async {
|
|
List<Map<String, dynamic>> data = _readTable(table);
|
|
int initialLength = data.length;
|
|
data.removeWhere((element) => element['id'] == id);
|
|
if (data.length < initialLength) {
|
|
_writeTable(table, data);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Future<int> deleteAllData(String table) async {
|
|
_writeTable(table, []);
|
|
return 1;
|
|
}
|
|
}
|