151 lines
4.7 KiB
Dart
151 lines
4.7 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
import '../../../common/domain/metal_type.dart';
|
|
import '../../../common/storage/preferences_storage.dart';
|
|
import '../../../common/storage/storage_keys.dart';
|
|
import 'asset_models.dart';
|
|
|
|
final mockAssetRepositoryProvider = Provider<MockAssetRepository>(
|
|
(ref) => MockAssetRepository(ref.watch(preferencesStorageProvider)),
|
|
);
|
|
|
|
class MockAssetRepository {
|
|
MockAssetRepository(this._preferences);
|
|
|
|
static const guestAccountScope = 'guest';
|
|
|
|
final PreferencesStorage _preferences;
|
|
Future<void> _operationTail = Future<void>.value();
|
|
|
|
static String accountScope({String? userId, String? phone}) {
|
|
final normalizedUserId = userId?.trim() ?? '';
|
|
if (normalizedUserId.isNotEmpty) return 'id:$normalizedUserId';
|
|
final normalizedPhone = phone?.trim() ?? '';
|
|
if (normalizedPhone.isNotEmpty) return 'phone:$normalizedPhone';
|
|
return guestAccountScope;
|
|
}
|
|
|
|
static String holdingsStorageKey(String accountScope) =>
|
|
'$storageJinzhiHoldings:${Uri.encodeComponent(accountScope)}';
|
|
|
|
static String deletedStorageKey(String accountScope) =>
|
|
'$storageJinzhiHoldingsDeleted:${Uri.encodeComponent(accountScope)}';
|
|
|
|
List<GoldAssetHolding> loadHoldings(String accountScope) {
|
|
if (_preferences.getBool(deletedStorageKey(accountScope))) return [];
|
|
final encoded = _preferences.getString(holdingsStorageKey(accountScope));
|
|
if (encoded == null || encoded.isEmpty) return _seedHoldings();
|
|
try {
|
|
final decoded = jsonDecode(encoded);
|
|
if (decoded is! List) return _seedHoldings();
|
|
return [
|
|
for (final item in decoded)
|
|
GoldAssetHolding.fromJson(Map<String, Object?>.from(item as Map)),
|
|
];
|
|
} catch (_) {
|
|
return _seedHoldings();
|
|
}
|
|
}
|
|
|
|
Future<void> saveHoldings(
|
|
String accountScope,
|
|
List<GoldAssetHolding> holdings,
|
|
) async {
|
|
final encoded = jsonEncode([
|
|
for (final holding in holdings) holding.toJson(),
|
|
]);
|
|
await _serialize(() async {
|
|
await _preferences.setString(holdingsStorageKey(accountScope), encoded);
|
|
await _preferences.remove(deletedStorageKey(accountScope));
|
|
});
|
|
}
|
|
|
|
Future<void> deleteAccountHoldings(String accountScope) async {
|
|
await _serialize(() async {
|
|
final scopes = {accountScope, guestAccountScope};
|
|
await Future.wait([
|
|
for (final scope in scopes) ...[
|
|
_preferences.remove(holdingsStorageKey(scope)),
|
|
_preferences.setBool(deletedStorageKey(scope), true),
|
|
],
|
|
// Remove the pre-account-scoping key left by earlier builds.
|
|
_preferences.remove(storageJinzhiHoldings),
|
|
]);
|
|
});
|
|
}
|
|
|
|
Future<T> _serialize<T>(Future<T> Function() operation) {
|
|
final result = _operationTail.then((_) => operation());
|
|
_operationTail = result.then<void>(
|
|
(_) {},
|
|
onError: (Object _, StackTrace _) {},
|
|
);
|
|
return result;
|
|
}
|
|
|
|
List<GoldAssetHolding> _seedHoldings() {
|
|
final now = DateTime(2026, 6, 18, 16, 11);
|
|
return [
|
|
GoldAssetHolding(
|
|
id: 'holding_gold_bar_001',
|
|
name: '投资金条',
|
|
metal: MetalType.gold,
|
|
category: AssetCategory.bar,
|
|
purity: 0.9999,
|
|
purityLabel: '足金9999',
|
|
weightGram: 50,
|
|
costAmount: 43200,
|
|
purchaseDate: DateTime(2025, 10, 12),
|
|
channel: '银行',
|
|
createdAt: now.subtract(const Duration(days: 249)),
|
|
updatedAt: now,
|
|
),
|
|
GoldAssetHolding(
|
|
id: 'holding_gold_ring_001',
|
|
name: '素圈戒指',
|
|
metal: MetalType.gold,
|
|
category: AssetCategory.ring,
|
|
purity: 0.999,
|
|
purityLabel: '足金999',
|
|
weightGram: 8.6,
|
|
costAmount: 7820,
|
|
purchaseDate: DateTime(2024, 12, 4),
|
|
channel: '金店',
|
|
createdAt: now.subtract(const Duration(days: 196)),
|
|
updatedAt: now,
|
|
),
|
|
GoldAssetHolding(
|
|
id: 'holding_platinum_001',
|
|
name: 'PT950 项链',
|
|
metal: MetalType.platinum,
|
|
category: AssetCategory.platinumPiece,
|
|
purity: 0.95,
|
|
purityLabel: 'PT950',
|
|
weightGram: 12.3,
|
|
costAmount: 5200,
|
|
purchaseDate: DateTime(2023, 8, 21),
|
|
channel: '金店',
|
|
createdAt: now.subtract(const Duration(days: 667)),
|
|
updatedAt: now,
|
|
),
|
|
GoldAssetHolding(
|
|
id: 'holding_silver_001',
|
|
name: '银手镯',
|
|
metal: MetalType.silver,
|
|
category: AssetCategory.bracelet,
|
|
purity: 0.999,
|
|
purityLabel: '999银',
|
|
weightGram: 31.8,
|
|
costAmount: 980,
|
|
purchaseDate: DateTime(2024, 4, 7),
|
|
channel: '金店',
|
|
note: '材料价值偏低',
|
|
createdAt: now.subtract(const Duration(days: 802)),
|
|
updatedAt: now,
|
|
),
|
|
];
|
|
}
|
|
}
|