cashumit/lib/services/account_mirror_service.dart

155 lines
5.0 KiB
Dart

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
import '../models/firefly_account.dart';
class AccountMirrorService {
static const String _accountsKey = 'mirrored_accounts';
static const String _lastSyncKey = 'accounts_last_sync';
static const String _lastSyncTimeKey = 'accounts_last_sync_time';
/// Simpan semua akun ke local storage untuk offline usage
static Future<void> mirrorAccounts(List<FireflyAccount> accounts) async {
final prefs = await SharedPreferences.getInstance();
// Konversi akun ke JSON string
final accountsJson = accounts.map((account) => account.toJson()).toList();
await prefs.setStringList(
_accountsKey, accountsJson.map((json) => jsonEncode(json)).toList());
await prefs.setInt(_lastSyncTimeKey, DateTime.now().millisecondsSinceEpoch);
await prefs.setBool(
_lastSyncKey, true); // Menandakan bahwa akun pernah di-sync
}
/// Ambil semua akun yang telah di-mirror dari local storage
static Future<List<FireflyAccount>> getMirroredAccounts() async {
final prefs = await SharedPreferences.getInstance();
final accountsJsonList = prefs.getStringList(_accountsKey) ?? [];
if (accountsJsonList.isEmpty) {
return [];
}
return accountsJsonList
.map((jsonString) => FireflyAccount.fromJson(json.decode(jsonString)))
.toList();
}
/// Ambil akun berdasarkan tipe (revenue, asset, dll)
static Future<List<FireflyAccount>> getMirroredAccountsByType(
String type) async {
final allAccounts = await getMirroredAccounts();
return allAccounts.where((account) => account.type == type).toList();
}
/// Ambil akun berdasarkan ID
static Future<FireflyAccount?> getAccountById(String id) async {
final allAccounts = await getMirroredAccounts();
return allAccounts.firstWhere(
(account) => account.id == id,
orElse: () => FireflyAccount(id: '', name: '', type: ''),
);
}
/// Periksa apakah akun sudah pernah di-mirror
static Future<bool> hasMirroredAccounts() async {
final prefs = await SharedPreferences.getInstance();
return prefs.containsKey(_accountsKey);
}
/// Ambil waktu terakhir sync
static Future<DateTime?> getLastSyncTime() async {
final prefs = await SharedPreferences.getInstance();
final timestamp = prefs.getInt(_lastSyncTimeKey);
return timestamp != null
? DateTime.fromMillisecondsSinceEpoch(timestamp)
: null;
}
/// Ambil status sync terakhir
static Future<bool> getLastSyncStatus() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(_lastSyncKey) ?? false;
}
/// Hapus semua data mirror (untuk testing atau reset)
static Future<void> clearMirror() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_accountsKey);
await prefs.remove(_lastSyncTimeKey);
await prefs.remove(_lastSyncKey);
}
/// Update mirror dari server dan simpan ke local storage
static Future<void> updateMirrorFromServer(
List<FireflyAccount> accounts) async {
await mirrorAccounts(accounts);
}
/// Dapatkan akun dengan prioritas: mirror terbaru > empty list
static Future<List<FireflyAccount>> getAccountsWithFallback(
Future<List<FireflyAccount>> Function() serverFetchFunction,
) async {
// Coba ambil dari mirror terlebih dahulu
final mirroredAccounts = await getMirroredAccounts();
if (mirroredAccounts.isNotEmpty) {
return mirroredAccounts;
}
// Jika mirror kosong, coba ambil dari server dan mirror
try {
final serverAccounts = await serverFetchFunction();
if (serverAccounts.isNotEmpty) {
// Simpan ke mirror jika berhasil ambil dari server
await updateMirrorFromServer(serverAccounts);
return serverAccounts;
}
} catch (e) {
print('Gagal mengambil akun dari server: $e');
}
// Jika semua gagal, kembalikan empty list
return [];
}
/// Format waktu sync untuk display
static String formatSyncTime(DateTime? syncTime) {
if (syncTime == null) {
return 'Belum pernah disinkronisasi';
}
final now = DateTime.now();
final difference = now.difference(syncTime);
if (difference.inMinutes < 1) {
return 'Baru saja';
} else if (difference.inHours < 1) {
final minutes = difference.inMinutes;
return '$minutes menit yang lalu';
} else if (difference.inDays < 1) {
final hours = difference.inHours;
return '$hours jam yang lalu';
} else {
final days = difference.inDays;
return '$days hari yang lalu';
}
}
/// Sinkronisasi otomatis jika server tersedia
static Future<bool> autoSyncIfNeeded(
Future<List<FireflyAccount>> Function() serverFetchFunction,
) async {
try {
final serverAccounts = await serverFetchFunction();
if (serverAccounts.isNotEmpty) {
await updateMirrorFromServer(serverAccounts);
return true;
}
} catch (e) {
print('Auto sync gagal: $e');
return false;
}
return false;
}
}