feat: three nuxt frontends, demo seed, rounding + money-exponent + rate-cast fixes, archived specs

This commit is contained in:
Chengdong Zhang
2026-09-17 13:34:38 +08:00
parent dc9fd31c5e
commit 653f13161a
85 changed files with 4327 additions and 106 deletions
+3 -2
View File
@@ -1,5 +1,5 @@
use rust_decimal::prelude::*;
use rust_decimal::Decimal;
use rust_decimal::{Decimal, RoundingStrategy};
use crate::error::ApiError;
use crate::models::Currency;
@@ -16,7 +16,8 @@ pub fn convert_minor(amount_minor: i64, from: &Currency, to: &Currency) -> Resul
let to_scale = Decimal::from(10i64.pow(to.exponent as u32));
// minor(from) -> major(from) -> major(base) -> minor(to)
let base_major = amount / from_scale / from.rate_to_base;
let target = (base_major * to.rate_to_base * to_scale).round_dp(0);
let target = (base_major * to.rate_to_base * to_scale)
.round_dp_with_strategy(0, RoundingStrategy::MidpointAwayFromZero);
target
.to_i64()
.ok_or_else(|| ApiError::BadRequest("amount out of range".into()))
+9
View File
@@ -146,6 +146,15 @@ async fn currency_conversion_math() {
assert_eq!(body["amount_minor"], 1500);
assert_eq!(body["currency"], "JPY");
// midpoint rounds half-up (away from zero), not banker's rounding:
// 1999 minor USD ($19.99) -> JPY at rate 150 => 2998.5 -> 2999
let res = client()
.get(app.url("/api/currencies/convert?amount_minor=1999&from=USD&to=JPY"))
.send()
.await
.unwrap();
assert_eq!(res.json::<serde_json::Value>().await.unwrap()["amount_minor"], 2999);
// disabled currency rejected
let admin = login_admin(&app).await;
let res = client()