number_description.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. use crate::impl_from_and_to_type_option;
  2. use crate::services::row::StringifyCellData;
  3. use crate::services::util::*;
  4. use chrono::format::strftime::StrftimeItems;
  5. use chrono::NaiveDateTime;
  6. use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
  7. use flowy_error::FlowyError;
  8. use flowy_grid_data_model::entities::{Field, FieldType};
  9. use rust_decimal::Decimal;
  10. use rusty_money::{
  11. iso::{Currency, CNY, EUR, USD},
  12. Money,
  13. };
  14. use serde::{Deserialize, Serialize};
  15. use std::str::FromStr;
  16. use strum_macros::EnumIter;
  17. // Number
  18. #[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
  19. pub struct NumberDescription {
  20. #[pb(index = 1)]
  21. pub money: MoneySymbol,
  22. #[pb(index = 2)]
  23. pub scale: u32,
  24. #[pb(index = 3)]
  25. pub symbol: String,
  26. #[pb(index = 4)]
  27. pub sign_positive: bool,
  28. #[pb(index = 5)]
  29. pub name: String,
  30. }
  31. impl_from_and_to_type_option!(NumberDescription, FieldType::Number);
  32. impl std::default::Default for NumberDescription {
  33. fn default() -> Self {
  34. let money = MoneySymbol::default();
  35. let symbol = money.symbol_str();
  36. NumberDescription {
  37. money,
  38. scale: 0,
  39. symbol,
  40. sign_positive: true,
  41. name: "Number".to_string(),
  42. }
  43. }
  44. }
  45. impl NumberDescription {
  46. pub fn set_money_symbol(&mut self, money_symbol: MoneySymbol) {
  47. self.money = money_symbol;
  48. self.symbol = money_symbol.symbol_str();
  49. }
  50. fn money_from_str(&self, s: &str) -> Option<String> {
  51. match Decimal::from_str(s) {
  52. Ok(mut decimal) => {
  53. match decimal.set_scale(self.scale) {
  54. Ok(_) => {}
  55. Err(e) => {
  56. tracing::error!("Set decimal scale failed: {:?}", e);
  57. }
  58. }
  59. decimal.set_sign_positive(self.sign_positive);
  60. Some(self.money.with_decimal(decimal).to_string())
  61. }
  62. Err(e) => {
  63. tracing::error!("Parser money from {} failed: {:?}", s, e);
  64. None
  65. }
  66. }
  67. }
  68. }
  69. impl StringifyCellData for NumberDescription {
  70. fn str_from_cell_data(&self, data: String) -> String {
  71. match self.money_from_str(&data) {
  72. Some(money_str) => money_str,
  73. None => String::default(),
  74. }
  75. }
  76. fn str_to_cell_data(&self, s: &str) -> Result<String, FlowyError> {
  77. let strip_symbol_money = strip_money_symbol(s);
  78. let decimal = Decimal::from_str(&strip_symbol_money).map_err(|err| FlowyError::internal().context(err))?;
  79. Ok(decimal.to_string())
  80. }
  81. }
  82. #[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
  83. pub enum MoneySymbol {
  84. CNY = 0,
  85. EUR = 1,
  86. USD = 2,
  87. }
  88. impl std::default::Default for MoneySymbol {
  89. fn default() -> Self {
  90. MoneySymbol::USD
  91. }
  92. }
  93. impl MoneySymbol {
  94. // Currency list https://docs.rs/rusty-money/0.4.0/rusty_money/iso/index.html
  95. pub fn from_symbol_str(s: &str) -> MoneySymbol {
  96. match s {
  97. "CNY" => MoneySymbol::CNY,
  98. "EUR" => MoneySymbol::EUR,
  99. "USD" => MoneySymbol::USD,
  100. _ => MoneySymbol::CNY,
  101. }
  102. }
  103. pub fn from_money(money: &rusty_money::Money<Currency>) -> MoneySymbol {
  104. MoneySymbol::from_symbol_str(&money.currency().symbol.to_string())
  105. }
  106. pub fn currency(&self) -> &'static Currency {
  107. match self {
  108. MoneySymbol::CNY => CNY,
  109. MoneySymbol::EUR => EUR,
  110. MoneySymbol::USD => USD,
  111. }
  112. }
  113. // string_to_money("¥18,443").unwrap();
  114. // string_to_money("$18,443").unwrap();
  115. // string_to_money("€18,443").unwrap();
  116. pub fn code(&self) -> String {
  117. self.currency().iso_alpha_code.to_string()
  118. }
  119. pub fn symbol_str(&self) -> String {
  120. self.currency().symbol.to_string()
  121. }
  122. pub fn zero(&self) -> Money<Currency> {
  123. let mut decimal = Decimal::new(0, 0);
  124. decimal.set_sign_positive(true);
  125. self.with_decimal(decimal)
  126. }
  127. pub fn with_decimal(&self, decimal: Decimal) -> Money<Currency> {
  128. let money = rusty_money::Money::from_decimal(decimal, self.currency());
  129. money
  130. }
  131. }