diff --git a/integration-tests/multiple_commodity_balance/main.zhang b/integration-tests/multiple_commodity_balance/main.zhang new file mode 100644 index 00000000..f3c026d0 --- /dev/null +++ b/integration-tests/multiple_commodity_balance/main.zhang @@ -0,0 +1,18 @@ +option "operating_currency" "CNY" + +1970-01-01 commodity USD + +2022-08-27 open Assets:AppStore:US USD,CNY +2022-08-27 open Liabilities:CreditCard USD,CNY +2022-08-27 open Equity:Opening-Balances USD,CNY + +2024-04-07 * "" "初始AppStore账户" + Equity:Opening-Balances -82.03 CNY + Assets:AppStore:US 11.33 USD @@ 82.03 CNY + +2024-04-08 * "" "充值AppleStore" + Liabilities:CreditCard -72.51 CNY + Assets:AppStore:US 10.00 USD @@ 72.51 CNY + + +2024-04-22 balance Assets:AppStore:US 21.33 USD \ No newline at end of file diff --git a/integration-tests/multiple_commodity_balance/validations.json b/integration-tests/multiple_commodity_balance/validations.json new file mode 100644 index 00000000..0e589801 --- /dev/null +++ b/integration-tests/multiple_commodity_balance/validations.json @@ -0,0 +1,35 @@ +[ + { + "uri": "/api/store", + "validations": [ + [ + "$.data.errors.length()", + 0 + ], + [ + "$.data.commodity_lots.['Assets:AppStore:US'].[0].amount", + "21.33" + ], + [ + "$.data.commodity_lots.['Assets:AppStore:US'].[0].commodity", + "USD" + ], + [ + "$.data.commodity_lots.['Equity:Opening-Balances'].[0].amount", + "-82.03" + ], + [ + "$.data.commodity_lots.['Equity:Opening-Balances'].[0].commodity", + "CNY" + ], + [ + "$.data.commodity_lots.['Liabilities:CreditCard'].[0].amount", + "-72.51" + ], + [ + "$.data.commodity_lots.['Liabilities:CreditCard'].[0].commodity", + "CNY" + ] + ] + } +] \ No newline at end of file diff --git a/zhang-ast/src/amount.rs b/zhang-ast/src/amount.rs index 90e497f2..fc34ed5d 100644 --- a/zhang-ast/src/amount.rs +++ b/zhang-ast/src/amount.rs @@ -19,6 +19,10 @@ impl CalculatedAmount { detail, } } + pub fn persist_commodity(mut self, commodity: &str) -> Self { + self.detail.entry(commodity.to_owned()).or_default(); + self + } } #[derive(Eq, PartialEq, Debug, Clone, Serialize, Deserialize)] diff --git a/zhang-core/src/process/transaction.rs b/zhang-core/src/process/transaction.rs index c3cd64eb..009c131c 100644 --- a/zhang-core/src/process/transaction.rs +++ b/zhang-core/src/process/transaction.rs @@ -70,9 +70,11 @@ impl DirectiveProcess for Transaction { trace!("new balance checker starting with {}", &balance_checker); for (posting_idx, txn_posting) in self.txn_postings().into_iter().enumerate() { - let inferred_amount = txn_posting - .infer_trade_amount() - .map_err(|kind| ZhangError::ProcessError { span: span.clone(), kind })?; + let inferred_amount = txn_posting.units().unwrap_or( + txn_posting + .infer_trade_amount() + .map_err(|kind| ZhangError::ProcessError { span: span.clone(), kind })?, + ); let option = operations.account_target_day_balance( txn_posting.posting.account.name(), @@ -85,7 +87,6 @@ impl DirectiveProcess for Transaction { commodity: inferred_amount.currency.clone(), }); let after_number = (&previous.number).add(&inferred_amount.number); - operations.insert_transaction_posting( &id, posting_idx, diff --git a/zhang-server/src/routes/account.rs b/zhang-server/src/routes/account.rs index 41189be6..d7f585b2 100644 --- a/zhang-server/src/routes/account.rs +++ b/zhang-server/src/routes/account.rs @@ -32,7 +32,9 @@ pub async fn get_account_list(ledger: State>>) -> ApiResult>>, path: Path<(St .into_iter() .map(|balance| Amount::new(balance.balance_number, balance.balance_commodity)) .collect_vec(); - let amount = vec.calculate(Utc::now().with_timezone(timezone), &mut operations)?; + let amount = vec + .calculate(Utc::now().with_timezone(timezone), &mut operations)? + .persist_commodity(&ledger.options.operating_currency); ResponseWrapper::json(AccountInfoResponse { date: account_info.date,