feat: backend MVP (auth/rbac, catalog, orders, fulfillment, invoices) + specs + scaffolds
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
use rust_decimal::prelude::*;
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
use crate::error::ApiError;
|
||||
use crate::models::Currency;
|
||||
|
||||
/// Convert integer minor units between currencies via base rates.
|
||||
/// rate_to_base = units of currency per 1 unit of base. Rounds half-up
|
||||
/// to whole minor units of the target currency.
|
||||
pub fn convert_minor(amount_minor: i64, from: &Currency, to: &Currency) -> Result<i64, ApiError> {
|
||||
if amount_minor < 0 {
|
||||
return Err(ApiError::BadRequest("amount_minor must be >= 0".into()));
|
||||
}
|
||||
let amount = Decimal::from(amount_minor);
|
||||
let from_scale = Decimal::from(10i64.pow(from.exponent as u32));
|
||||
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);
|
||||
target
|
||||
.to_i64()
|
||||
.ok_or_else(|| ApiError::BadRequest("amount out of range".into()))
|
||||
}
|
||||
Reference in New Issue
Block a user