64 lines
1.9 KiB
Dart
64 lines
1.9 KiB
Dart
import 'json_util.dart';
|
||
|
||
/// 账户信息(对应后端 AccountResponse)
|
||
///
|
||
/// 语义说明(重要):
|
||
/// - [balance] 是后端计算出来的:`initialBalance + totalIncome - totalExpense`
|
||
/// - [initialBalance] 才是可写入数据库的字段(后端 PUT /accounts/balance 改的是它)
|
||
/// - [totalIncome] / [totalExpense] 是**全部账单**的汇总,只读
|
||
class AccountInfo {
|
||
final int? id;
|
||
final String name;
|
||
final double initialBalance;
|
||
final double balance;
|
||
final double totalIncome;
|
||
final double totalExpense;
|
||
|
||
const AccountInfo({
|
||
this.id,
|
||
this.name = '默认账户',
|
||
required this.initialBalance,
|
||
required this.balance,
|
||
required this.totalIncome,
|
||
required this.totalExpense,
|
||
});
|
||
|
||
factory AccountInfo.fromJson(Map<String, dynamic> json) {
|
||
final initial = asDouble(json['initialBalance']);
|
||
final income = asDouble(json['totalIncome']);
|
||
final expense = asDouble(json['totalExpense']);
|
||
return AccountInfo(
|
||
id: json['id'] == null ? null : asInt(json['id']),
|
||
name: asNonEmpty(json['name'], '默认账户'),
|
||
initialBalance: initial,
|
||
// 后端没给 balance 时本地按同一公式兜底
|
||
balance: json['balance'] == null
|
||
? initial + income - expense
|
||
: asDouble(json['balance']),
|
||
totalIncome: income,
|
||
totalExpense: expense,
|
||
);
|
||
}
|
||
|
||
static const empty = AccountInfo(
|
||
initialBalance: 0,
|
||
balance: 0,
|
||
totalIncome: 0,
|
||
totalExpense: 0,
|
||
);
|
||
}
|
||
|
||
/// 把"用户想要的目标余额"反算成后端可写入的期初余额。
|
||
///
|
||
/// 因为 balance = initialBalance + totalIncome - totalExpense,
|
||
/// 所以要让余额显示为 target,期初余额必须设为:
|
||
/// `target - totalIncome + totalExpense`
|
||
double initialBalanceFor({
|
||
required double targetBalance,
|
||
required double totalIncome,
|
||
required double totalExpense,
|
||
}) {
|
||
if (!targetBalance.isFinite) return 0;
|
||
return targetBalance - totalIncome + totalExpense;
|
||
}
|