fix: disable set decimal scale

This commit is contained in:
appflowy 2022-06-02 21:57:12 +08:00
parent 8b40244c73
commit 72e26ab229
2 changed files with 92 additions and 97 deletions

View File

@ -150,8 +150,7 @@ impl CellDataOperation<String> for DateTypeOption {
(true, Some(time)) => {
let time = Some(time.trim().to_uppercase());
let utc = self.utc_date_time_from_timestamp(date_timestamp);
let timestamp = self.timestamp_from_utc_with_time(&utc, &time)?;
timestamp
self.timestamp_from_utc_with_time(&utc, &time)?
}
_ => date_timestamp,
},
@ -548,7 +547,7 @@ mod tests {
assert_changeset_result(
&type_option,
DateCellContentChangeset {
date: Some(date_timestamp.clone()),
date: Some(date_timestamp),
time: Some("1:00".to_owned()),
},
&type_option.field_type(),
@ -568,7 +567,7 @@ mod tests {
assert_changeset_result(
&type_option,
DateCellContentChangeset {
date: Some(date_timestamp.clone()),
date: Some(date_timestamp),
time: Some("1:00 am".to_owned()),
},
&type_option.field_type(),
@ -622,7 +621,7 @@ mod tests {
if type_option.include_time {
format!("{}{}", decoded_data.date, decoded_data.time)
} else {
format!("{}", decoded_data.date)
decoded_data.date
}
}
}

View File

@ -71,6 +71,76 @@ pub struct NumberTypeOption {
}
impl_type_option!(NumberTypeOption, FieldType::Number);
impl NumberTypeOption {
pub fn new() -> Self {
Self::default()
}
fn cell_content_from_number_str(&self, s: &str) -> FlowyResult<String> {
return match self.format {
NumberFormat::Number => {
if let Ok(v) = s.parse::<f64>() {
return Ok(v.to_string());
}
if let Ok(v) = s.parse::<i64>() {
return Ok(v.to_string());
}
Ok("".to_string())
}
NumberFormat::Percent => {
let content = s.parse::<f64>().map_or(String::new(), |v| v.to_string());
Ok(content)
}
_ => self.money_from_number_str(s),
};
}
pub fn set_format(&mut self, format: NumberFormat) {
self.format = format;
self.symbol = format.symbol();
}
fn money_from_number_str(&self, s: &str) -> FlowyResult<String> {
let mut number = self.strip_currency_symbol(s);
if s.is_empty() {
return Ok("".to_string());
}
match Decimal::from_str(&number) {
Ok(mut decimal) => {
decimal.set_sign_positive(self.sign_positive);
let money = rusty_money::Money::from_decimal(decimal, self.format.currency()).to_string();
Ok(money)
}
Err(_) => match rusty_money::Money::from_str(&number, self.format.currency()) {
Ok(money) => Ok(money.to_string()),
Err(_) => {
number.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
if number.chars().all(char::is_numeric) {
self.money_from_number_str(&number)
} else {
Err(FlowyError::invalid_data().context("Should only contain numbers"))
}
}
},
}
}
fn strip_currency_symbol<T: ToString>(&self, s: T) -> String {
let mut s = s.to_string();
for symbol in CURRENCY_SYMBOL.iter() {
if s.starts_with(symbol) {
s = s.strip_prefix(symbol).unwrap_or("").to_string();
break;
}
}
s
}
}
impl CellDataOperation<String> for NumberTypeOption {
fn decode_cell_data<T>(
&self,
@ -103,7 +173,7 @@ impl CellDataOperation<String> for NumberTypeOption {
Ok(DecodedCellData::new(content))
}
_ => {
let content = self.number_from_str(&cell_data);
let content = self.money_from_number_str(&cell_data).unwrap_or("".to_string());
Ok(DecodedCellData::new(content))
}
}
@ -114,15 +184,8 @@ impl CellDataOperation<String> for NumberTypeOption {
C: Into<CellContentChangeset>,
{
let changeset = changeset.into();
let mut data = changeset.trim().to_string();
if self.format != NumberFormat::Number {
data = self.strip_symbol(data);
if !data.chars().all(char::is_numeric) {
return Err(FlowyError::invalid_data().context("Should only contain numbers"));
}
}
let data = changeset.trim().to_string();
let _ = self.cell_content_from_number_str(&data)?;
Ok(data)
}
}
@ -141,54 +204,6 @@ impl std::default::Default for NumberTypeOption {
}
}
impl NumberTypeOption {
pub fn set_format(&mut self, format: NumberFormat) {
self.format = format;
self.symbol = format.symbol();
}
fn number_from_str(&self, s: &str) -> String {
match Decimal::from_str(s) {
Ok(mut decimal) => {
match decimal.set_scale(self.scale) {
Ok(_) => {}
Err(e) => {
tracing::error!("Set decimal scale failed: {:?}", e);
}
}
decimal.set_sign_positive(self.sign_positive);
let money = rusty_money::Money::from_decimal(decimal, self.format.currency());
money.to_string()
}
Err(_) => {
let s = self.strip_symbol(s);
if !s.is_empty() && s.chars().all(char::is_numeric) {
self.number_from_str(&s)
} else {
"".to_owned()
}
}
}
}
fn strip_symbol<T: ToString>(&self, s: T) -> String {
let mut s = s.to_string();
for symbol in CURRENCY_SYMBOL.iter() {
if s.starts_with(symbol) {
s = s.strip_prefix(symbol).unwrap_or("").to_string();
break;
}
}
if !s.chars().all(char::is_numeric) {
s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
}
s
}
}
#[cfg(test)]
mod tests {
use crate::services::field::FieldBuilder;
@ -206,14 +221,21 @@ mod tests {
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
#[test]
fn number_type_option_strip_symbol_test() {
let mut type_option = NumberTypeOption::new();
type_option.format = NumberFormat::USD;
assert_eq!(type_option.strip_currency_symbol("$18,443"), "18,443".to_owned());
type_option.format = NumberFormat::Yuan;
assert_eq!(type_option.strip_currency_symbol("$0.2"), "0.2".to_owned());
}
#[test]
fn number_type_option_format_number_test() {
let mut type_option = NumberTypeOption::default();
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
for format in NumberFormat::iter() {
type_option.format = format;
@ -248,10 +270,12 @@ mod tests {
type_option.format = format;
match format {
NumberFormat::Number => {
// assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
assert_equal(&type_option, "0.2", "0.2", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "$18,44", "$1,844", &field_type, &field_meta);
assert_equal(&type_option, "$0.2", "$0.2", &field_type, &field_meta);
assert_equal(&type_option, "", "", &field_type, &field_meta);
assert_equal(&type_option, "abc", "", &field_type, &field_meta);
}
@ -264,7 +288,8 @@ mod tests {
assert_equal(&type_option, "CN¥1844", "CN¥1,844", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "€18.44", "€1.844", &field_type, &field_meta);
assert_equal(&type_option, "€18.44", "€18,44", &field_type, &field_meta);
assert_equal(&type_option, "€0.5", "€0,5", &field_type, &field_meta);
assert_equal(&type_option, "€1844", "€1.844", &field_type, &field_meta);
}
_ => {}
@ -272,35 +297,6 @@ mod tests {
}
}
#[test]
fn number_type_option_scale_test() {
let mut type_option = NumberTypeOption {
scale: 1,
..Default::default()
};
let field_type = FieldType::Number;
let field_meta = FieldBuilder::from_field_type(&field_type).build();
for format in NumberFormat::iter() {
type_option.format = format;
match format {
NumberFormat::Number => {
assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
}
NumberFormat::USD => {
assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
}
NumberFormat::Yen => {
assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
}
NumberFormat::EUR => {
assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
}
_ => {}
}
}
}
#[test]
fn number_description_sign_test() {
let mut type_option = NumberTypeOption {