Add transfer tracking and secure admin access
This commit is contained in:
@@ -194,6 +194,13 @@ class RecognitionImportService {
|
||||
sourceText: candidate.sourceText,
|
||||
occurredAt: ShanghaiTime.toCivil(occurredUtc),
|
||||
clientRequestId: candidate.clientRequestId,
|
||||
transferDirection: candidate.transferDirection,
|
||||
counterparty: candidate.counterparty,
|
||||
provider: candidate.provider,
|
||||
providerTransactionId: candidate.providerTransactionId,
|
||||
recognitionOccurrenceId: candidate.recognitionOccurrenceId,
|
||||
evidenceFingerprint: candidate.evidenceFingerprint,
|
||||
recognitionConfidence: candidate.identityConfidence,
|
||||
);
|
||||
await ScreenshotChannel.acknowledgeRecognitionCandidate(
|
||||
candidate.id,
|
||||
@@ -227,6 +234,13 @@ class RecognitionImportService {
|
||||
source: candidate.source,
|
||||
sourceText: candidate.sourceText,
|
||||
occurredAt: ShanghaiTime.toCivil(occurredUtc),
|
||||
transferDirection: candidate.transferDirection,
|
||||
counterparty: candidate.counterparty,
|
||||
provider: candidate.provider,
|
||||
providerTransactionId: candidate.providerTransactionId,
|
||||
recognitionOccurrenceId: candidate.recognitionOccurrenceId,
|
||||
evidenceFingerprint: candidate.evidenceFingerprint,
|
||||
recognitionConfidence: candidate.identityConfidence,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -254,11 +268,23 @@ class RecognitionImportService {
|
||||
RecognitionCandidate candidate,
|
||||
Map<String, List<CategoryItem>> cache,
|
||||
) async {
|
||||
if (candidate.type != 'income' && candidate.type != 'expense') {
|
||||
if (candidate.type != 'income' &&
|
||||
candidate.type != 'expense' &&
|
||||
candidate.type != 'transfer') {
|
||||
throw StateError('识别结果缺少明确的收支类型');
|
||||
}
|
||||
final categories = cache[candidate.type] ??= await TxApi.categories(
|
||||
candidate.type,
|
||||
if (candidate.type == 'transfer' &&
|
||||
candidate.transferDirection != 'in' &&
|
||||
candidate.transferDirection != 'out') {
|
||||
throw StateError('转账识别结果缺少方向');
|
||||
}
|
||||
final categoryType = candidate.type == 'transfer'
|
||||
? candidate.transferDirection == 'in'
|
||||
? 'income'
|
||||
: 'expense'
|
||||
: candidate.type;
|
||||
final categories = cache[categoryType] ??= await TxApi.categories(
|
||||
categoryType,
|
||||
);
|
||||
if (categories.isEmpty) throw StateError('当前账本没有可用分类');
|
||||
return categories
|
||||
@@ -315,16 +341,16 @@ class RecognitionImportService {
|
||||
width: 42,
|
||||
height: 42,
|
||||
decoration: BoxDecoration(
|
||||
color: candidate.type == 'income'
|
||||
color: candidate.isIncome
|
||||
? palette.primaryBackground
|
||||
: palette.expenseBackground,
|
||||
borderRadius: BorderRadius.circular(13),
|
||||
),
|
||||
child: Icon(
|
||||
candidate.type == 'income'
|
||||
candidate.isIncome
|
||||
? Icons.south_west_rounded
|
||||
: Icons.north_east_rounded,
|
||||
color: candidate.type == 'income'
|
||||
color: candidate.isIncome
|
||||
? AppTheme.primary
|
||||
: AppTheme.red,
|
||||
),
|
||||
@@ -343,7 +369,7 @@ class RecognitionImportService {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${candidate.appName} · ${candidate.type == 'income' ? '收入' : '支出'}',
|
||||
'${candidate.appName} · ${candidate.typeLabel}',
|
||||
style: TextStyle(
|
||||
color: palette.text2,
|
||||
fontSize: 12,
|
||||
@@ -353,9 +379,9 @@ class RecognitionImportService {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${candidate.type == 'income' ? '+' : '-'}¥${candidate.amount.toStringAsFixed(2)}',
|
||||
'${candidate.isIncome ? '+' : '-'}¥${candidate.amount.toStringAsFixed(2)}',
|
||||
style: TextStyle(
|
||||
color: candidate.type == 'income'
|
||||
color: candidate.isIncome
|
||||
? AppTheme.primary
|
||||
: AppTheme.red,
|
||||
fontSize: 18,
|
||||
|
||||
Reference in New Issue
Block a user