Skip to content

Commit

Permalink
Special way to add decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
lorinkoz committed Jun 27, 2024
1 parent ae7e545 commit d952a23
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 18 deletions.
33 changes: 33 additions & 0 deletions pytests/test_money.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,45 @@ def test_minus_zero(decimal):
Money("-0"),
-Money("0"),
-1 * Money("0"),
Money("0") * -1,
],
)
def test_advanced_negation(decimal):
assert str(Money(decimal).amount) == "-0"


@pytest.mark.parametrize("left", ["0", "-0"])
@pytest.mark.parametrize("right", ["0", "-0"])
def test_add_with_negative_zeros(left, right):
expected = Decimal(left) + Decimal(right)

money_left = Money(left)
money_right = Money(right)

assert str(money_left.amount) == str(left)
assert str(money_right.amount) == str(right)

assert str((money_left + Decimal(right)).amount) == str(expected)
assert str((Decimal(left) + money_right).amount) == str(expected)
assert str((money_left + money_right).amount) == str(expected)


@pytest.mark.parametrize("left", ["0", "-0"])
@pytest.mark.parametrize("right", ["0", "-0"])
def test_sub_with_negative_zeros(left, right):
expected = Decimal(left) - Decimal(right)

money_left = Money(left)
money_right = Money(right)

assert str(money_left.amount) == str(left)
assert str(money_right.amount) == str(right)

assert str((money_left - Decimal(right)).amount) == str(expected)
assert str((Decimal(left) - money_right).amount) == str(expected)
assert str((money_left - money_right).amount) == str(expected)


def test_equality_to_other_types():
x = Money(0)
assert x != None # noqa: E711
Expand Down
24 changes: 20 additions & 4 deletions src/money.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ impl Money {
fn __add__(&self, other: Bound<PyAny>) -> PyResult<Self> {
if let Ok(other_money) = other.extract::<Self>() {
Ok(Self {
amount: self.amount + other_money.amount,
amount: decimal_add(self.amount, other_money.amount),
})
} else if let Ok(other_decimal) = get_decimal(other) {
Ok(Self {
amount: self.amount + other_decimal,
amount: decimal_add(self.amount, other_decimal),
})
} else {
Err(pyo3::exceptions::PyTypeError::new_err(
Expand All @@ -113,11 +113,11 @@ impl Money {
fn __sub__(&self, other: Bound<PyAny>) -> PyResult<Self> {
if let Ok(other_money) = other.extract::<Self>() {
Ok(Self {
amount: self.amount - other_money.amount,
amount: decimal_add(self.amount, -other_money.amount),
})
} else if let Ok(other_decimal) = get_decimal(other) {
Ok(Self {
amount: self.amount - other_decimal,
amount: decimal_add(self.amount, -other_decimal),
})
} else {
Err(pyo3::exceptions::PyTypeError::new_err(
Expand Down Expand Up @@ -320,6 +320,22 @@ pub fn sum_(elems: Bound<PyAny>) -> PyResult<Money> {
Ok(Money { amount })
}

// Adds decimals the way of Python
pub fn decimal_add(left: Decimal, right: Decimal) -> Decimal {
let zero = Decimal::new(0, 0);

if left.abs() == zero && right.abs() == zero {
if left.is_sign_negative() && right.is_sign_negative() {
-zero
} else {
zero
}
} else {
left + right
}
}

// Rounds decimals the way of Python
fn round_with_negative_scale(value: Decimal, scale: i32, round_up: bool) -> Decimal {
let strategy = if round_up {
RoundingStrategy::MidpointAwayFromZero
Expand Down
14 changes: 7 additions & 7 deletions src/money_vat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::str::FromStr;

use crate::money::get_decimal;
use crate::money::Money;
use crate::money::MONEY_PRECISION;
use crate::money::{decimal_add, get_decimal};
use crate::money_vat_ratio::MoneyWithVATRatio;

const GERMAN_VAT_RATES: [i16; 5] = [0, 5, 7, 16, 19];
Expand Down Expand Up @@ -169,16 +169,16 @@ impl MoneyWithVAT {
if let Ok(other_money_with_vat) = other.extract::<Self>() {
Ok(Self {
net: Money {
amount: self.net.amount + other_money_with_vat.net.amount,
amount: decimal_add(self.net.amount, other_money_with_vat.net.amount),
},
tax: Money {
amount: self.tax.amount + other_money_with_vat.tax.amount,
amount: decimal_add(self.tax.amount, other_money_with_vat.tax.amount),
},
})
} else if let Ok(other_decimal) = get_decimal(other) {
Ok(Self {
net: Money {
amount: self.net.amount + other_decimal,
amount: decimal_add(self.net.amount, other_decimal),
},
tax: self.tax.clone(),
})
Expand All @@ -197,16 +197,16 @@ impl MoneyWithVAT {
if let Ok(other_money_with_vat) = other.extract::<Self>() {
Ok(Self {
net: Money {
amount: self.net.amount - other_money_with_vat.net.amount,
amount: decimal_add(self.net.amount, -other_money_with_vat.net.amount),
},
tax: Money {
amount: self.tax.amount - other_money_with_vat.tax.amount,
amount: decimal_add(self.tax.amount, -other_money_with_vat.tax.amount),
},
})
} else if let Ok(other_decimal) = get_decimal(other) {
Ok(Self {
net: Money {
amount: self.net.amount - other_decimal,
amount: decimal_add(self.net.amount, -other_decimal),
},
tax: self.tax.clone(),
})
Expand Down
14 changes: 7 additions & 7 deletions src/money_vat_ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use pyo3::types::{PyCFunction, PyDict, PyTuple};
use rust_decimal::prelude::FromPrimitive;
use rust_decimal::Decimal;

use crate::money::get_decimal;
use crate::money::{decimal_add, get_decimal};

#[pyclass]
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -58,22 +58,22 @@ impl MoneyWithVATRatio {

fn __neg__(&self) -> Self {
Self {
net_ratio: Decimal::new(0, 0) - self.net_ratio,
gross_ratio: Decimal::new(0, 0) - self.gross_ratio,
net_ratio: -self.net_ratio,
gross_ratio: -self.gross_ratio,
}
}

fn __add__(&self, other: Self) -> Self {
Self {
net_ratio: self.net_ratio + other.net_ratio,
gross_ratio: self.gross_ratio + other.gross_ratio,
net_ratio: decimal_add(self.net_ratio, other.net_ratio),
gross_ratio: decimal_add(self.gross_ratio, other.gross_ratio),
}
}

fn __sub__(&self, other: Self) -> Self {
Self {
net_ratio: self.net_ratio - other.net_ratio,
gross_ratio: self.gross_ratio - other.gross_ratio,
net_ratio: decimal_add(self.net_ratio, -other.net_ratio),
gross_ratio: decimal_add(self.gross_ratio, -other.gross_ratio),
}
}

Expand Down

0 comments on commit d952a23

Please sign in to comment.