Skip to content
This repository has been archived by the owner on Jan 4, 2022. It is now read-only.

Commit

Permalink
#9 Inefficient implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
staticdev committed Apr 29, 2020
1 parent 3015870 commit 5d2c37b
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 43 deletions.
61 changes: 56 additions & 5 deletions src/irpf_cei/b3.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
EMOLUMENTOS = {2019: 0.00004105, 2020: 0.00003006}
LIQUIDACAO = 0.000275
import collections
import datetime
import sys
from typing import List


RatePeriod = collections.namedtuple("RatePeriod", ["start_date", "end_date", "rate"])

EMOLUMENTOS_PERIODS = [
RatePeriod(
datetime.datetime(2019, 1, 3), datetime.datetime(2019, 2, 1), 0.00004476
),
RatePeriod(
datetime.datetime(2019, 2, 4), datetime.datetime(2019, 3, 1), 0.00004032
),
RatePeriod(
datetime.datetime(2019, 3, 6), datetime.datetime(2019, 4, 1), 0.00004157
),
RatePeriod(datetime.datetime(2019, 4, 2), datetime.datetime(2019, 5, 2), 0.0000408),
RatePeriod(
datetime.datetime(2019, 5, 3), datetime.datetime(2019, 6, 3), 0.00004408
),
RatePeriod(
datetime.datetime(2019, 6, 4), datetime.datetime(2019, 7, 1), 0.00004245
),
RatePeriod(
datetime.datetime(2019, 7, 2), datetime.datetime(2019, 8, 1), 0.00004189
),
RatePeriod(
datetime.datetime(2019, 8, 2), datetime.datetime(2019, 9, 2), 0.00004115
),
RatePeriod(
datetime.datetime(2019, 9, 3), datetime.datetime(2019, 10, 1), 0.00003756
),
RatePeriod(
datetime.datetime(2019, 10, 2), datetime.datetime(2019, 11, 1), 0.00004105
),
RatePeriod(
datetime.datetime(2019, 11, 4), datetime.datetime(2019, 12, 2), 0.0000411
),
RatePeriod(
datetime.datetime(2019, 12, 3), datetime.datetime(2020, 1, 2), 0.00003802
),
]
LIQUIDACAO_RATE = 0.000275
ETFS = {
"BBSD11",
"XBOV11",
Expand Down Expand Up @@ -33,8 +76,16 @@ def get_investment_type(code: str) -> str:


def get_trading_rate() -> float:
return LIQUIDACAO
return LIQUIDACAO_RATE


def get_emoluments_rate(year: int) -> float:
return EMOLUMENTOS[year]
def get_emoluments_rates(dates: List[datetime.datetime]) -> List[float]:
rates = []
for idx, date in enumerate(dates, 1):
for period in EMOLUMENTOS_PERIODS:
if period.start_date <= date <= period.end_date:
rates.append(period.rate)
break
if len(rates) < idx:
sys.exit("No period found for date: {}".format(date))
return rates
5 changes: 2 additions & 3 deletions src/irpf_cei/cei.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ def group_trades(df: pd.DataFrame) -> pd.DataFrame:
)


# TODO reproduce rounding calculation
def calculate_taxes(df: pd.DataFrame, ref_year: int) -> pd.DataFrame:
def calculate_taxes(df: pd.DataFrame) -> pd.DataFrame:
"""Groups emolumentos and liquidação taxes based on reference year.
Args:
Expand All @@ -162,7 +161,7 @@ def calculate_taxes(df: pd.DataFrame, ref_year: int) -> pd.DataFrame:
df["Valor Total (R$)"] * irpf_cei.b3.get_trading_rate()
).apply(round_down)
df["Emolumentos (R$)"] = (
df["Valor Total (R$)"] * irpf_cei.b3.get_emoluments_rate(ref_year)
df["Valor Total (R$)"] * irpf_cei.b3.get_emoluments_rates(df["Data Negócio"])
).apply(round_down)
return df

Expand Down
2 changes: 1 addition & 1 deletion src/irpf_cei/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def main() -> None:
ref_year, institution = irpf_cei.cei.validate_header(filename)
source_df = irpf_cei.cei.read_xls(filename)
source_df = irpf_cei.cei.clean_table_cols(source_df)
tax_df = irpf_cei.cei.calculate_taxes(source_df, ref_year)
tax_df = irpf_cei.cei.calculate_taxes(source_df)
irpf_cei.cei.output_taxes(tax_df)
result_df = irpf_cei.cei.goods_and_rights(tax_df)
irpf_cei.cei.output_goods_and_rights(result_df, ref_year, institution)
25 changes: 23 additions & 2 deletions tests/test_b3.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
"""Test cases for the B3 module."""
import datetime

import pandas as pd
import pytest

from irpf_cei import b3


Expand All @@ -18,5 +23,21 @@ def test_get_trading_rate() -> None:
assert b3.get_trading_rate() == 0.000275


def test_get_emoluments_rate() -> None:
assert b3.get_emoluments_rate(2019) == 0.00004105
def test_get_emoluments_rates_sucess() -> None:
series = pd.Series(
[
datetime.datetime(2019, 2, 20),
datetime.datetime(2019, 3, 6),
datetime.datetime(2019, 5, 14),
]
)
expected = [0.00004032, 0.00004157, 0.00004408]
result = b3.get_emoluments_rates(series)
assert result == expected


def test_get_emoluments_rates_error() -> None:
"""It raises `SystemExit` when date is not found."""
series = pd.Series([datetime.datetime(1930, 2, 20)])
with pytest.raises(SystemExit):
assert b3.get_emoluments_rates(series)
67 changes: 35 additions & 32 deletions tests/test_cei.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ def mock_pandas_read_excel(mocker: MockFixture) -> Mock:
"""Fixture for mocking pandas.read_excel."""
mock = mocker.patch("pandas.read_excel")
header = pd.DataFrame(
{"Período de": ["01/01/2019 a 31/12/2019", "NAN", "NAN", "NAN", "INSTITUTION"]}
{
"Período de": [
"01/01/2019 a 31/12/2019",
np.nan,
np.nan,
np.nan,
"INSTITUTION",
]
}
)
mock.return_value = header
return mock
Expand Down Expand Up @@ -150,45 +158,40 @@ def test_group_trades() -> None:
pd.testing.assert_frame_equal(result_df, expected_df)


@pytest.fixture
def mock_group_trades(mocker: MockFixture) -> Mock:
"""Fixture for mocking cei.group_trades."""
mock = mocker.patch("irpf_cei.cei.group_trades")
df = pd.DataFrame(
@patch(
"irpf_cei.cei.group_trades",
return_value=pd.DataFrame(
{
"Valor Total (R$)": [
4618.5,
935,
# 10956
"Data Negócio": [
datetime.datetime(2019, 2, 20),
datetime.datetime(2019, 3, 6),
datetime.datetime(2019, 5, 14),
],
"Valor Total (R$)": [935, 10956, 8870],
}
)
mock.return_value = df
return mock


def test_calculate_taxes_2019(mock_group_trades) -> None:
ref_year = 2019
),
)
@patch("irpf_cei.b3.get_trading_rate", return_value=0.000275)
@patch(
"irpf_cei.b3.get_emoluments_rates",
return_value=[0.00004105, 0.00004105, 0.00004105],
)
def test_calculate_taxes_2019(
mock_get_emoluments_rates, mock_get_trading_rate, mock_group_trades
) -> None:
expected_df = pd.DataFrame(
{
"Valor Total (R$)": [
4618.5,
935,
# 10956
],
"Liquidação (R$)": [
1.27,
0.25,
# 3.01
],
"Emolumentos (R$)": [
0.18,
0.03,
# 0.45
"Data Negócio": [
datetime.datetime(2019, 2, 20),
datetime.datetime(2019, 3, 6),
datetime.datetime(2019, 5, 14),
],
"Valor Total (R$)": [935, 10956, 8870],
"Liquidação (R$)": [0.25, 3.01, 2.43],
"Emolumentos (R$)": [0.03, 0.44, 0.36],
}
)
result_df = cei.calculate_taxes(pd.DataFrame(), ref_year)
result_df = cei.calculate_taxes(pd.DataFrame())
pd.testing.assert_frame_equal(result_df, expected_df)


Expand Down

0 comments on commit 5d2c37b

Please sign in to comment.