Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adiciona utilitário de formatação monetária #434

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Utilitário `convert_code_to_uf` [#397](https://github.com/brazilian-utils/brutils-python/pull/410)
- Utilitário `convert_date_to_text`[#394](https://github.com/brazilian-utils/brutils-python/pull/415)
- Utilitário `get_municipality_by_code` [412](https://github.com/brazilian-utils/brutils-python/pull/412)

- Utilitário `get_code_by_municipality_name` [#399](https://github.com/brazilian-utils/brutils-python/issues/399)
- Utilitário `get_code_by_municipality_name` [#399](https://github.com/brazilian-utils/brutils-python/issues/399)
- Utilitário `format_currency` [#426](https://github.com/brazilian-utils/brutils-python/issues/426)

## [2.2.0] - 2024-09-12

Expand Down
39 changes: 34 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,20 @@ False
- [remove\_symbols\_pis](#remove_symbols_pis)
- [generate\_pis](#generate_pis)
- [Processo Jurídico](#processo-jurídico)
- [is\_valid\_legal\_process](#is_valid_legal_process)
- [is\_valid\_legal\_process](#is_valid_legal_process)
- [format\_legal\_process](#format_legal_process)
- [remove\_symbols\_legal\_process](#remove_symbols_legal_process)
- [generate\_legal\_process](#generate_legal_process)
- [Título Eleitoral](#titulo-eleitoral)
- [is_valid_voter_id](#is_valid_voter_id)
- [format_voter_id](#format_voter_id)
- [generate_voter_id](#generate_voter_id)
- [Titulo Eleitoral](#titulo-eleitoral)
- [is\_valid\_voter\_id](#is_valid_voter_id)
- [format\_voter\_id](#format_voter_id)
- [generate\_voter\_id](#generate_voter_id)
- [IBGE](#ibge)
- [get_code_by_municipality_name](#get_code_by_municipality_name)
- [convert_code_to_uf](#convert_code_to_uf)
- [get\_municipality\_by\_code](#get_municipality_by_code)
- [Monetário](#monetário)
- [format\_currency](#format_currency)

## CPF

Expand Down Expand Up @@ -1190,6 +1192,33 @@ None
>>> get_code_by_municipality_name("Municipio Inexistente", "RS")
None
```

## Monetário

### format_currency

Formata um número seguindo o padrão monetário brasileiro. O número será formatado
adicionando o símbolo R$ como prefixo, vírgula como separador decimal, e ponto como
agrupador de milhar.

Argumentos:
* float ou Decimal: Um número com ou sem casas decimais.

Retorna:
* str ou None: O número formatado seguindo o padrão brasileiro.

Exemplo:

```python
>>> from brutils.currency import format_currency
>>> format_currency(1259.03)
'R$ 1.259,03'
>>> format_currency(0)
'R$ 0,00'
>>> format_currency("not a number")
None
```

# Novos Utilitários e Reportar Bugs

Caso queira sugerir novas funcionalidades ou reportar bugs, basta criar
Expand Down
28 changes: 28 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ False
- [convert_code_to_uf](#convert_code_to_uf)
- [get\_municipality\_by\_code](#get_municipality_by_code)
- [get_code_by_municipality_name](#get_code_by_municipality_name)
- [Monetary](#monetary)
- [format_currency](#format_currency)

## CPF

Expand Down Expand Up @@ -1195,6 +1197,32 @@ None
None
```

## Monetary

### format_currency

Formats a number following the Brazilian monetary standard. The number will be
formatted by adding the R$ symbol as a prefix, a comma as a decimal separator, and a
period as a thousands grouper.

Args:
* float or Decimal: A number with or without decimal places.

Returns:
* str or None: The number formatted following the Brazilian standard.

Example:

```python
>>> from brutils.currency import format_currency
>>> format_currency(1259.03)
'R$ 1.259,03'
>>> format_currency(0)
'R$ 0,00'
>>> format_currency("not a number")
None
```

# Feature Request and Bug Report

If you want to suggest new features or report bugs, simply create
Expand Down
125 changes: 35 additions & 90 deletions brutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,24 @@
get_address_from_cep,
get_cep_information_from_address,
)
from brutils.cep import (
generate as generate_cep,
)
from brutils.cep import (
is_valid as is_valid_cep,
)
from brutils.cep import (
remove_symbols as remove_symbols_cep,
)
from brutils.cep import generate as generate_cep
from brutils.cep import is_valid as is_valid_cep
from brutils.cep import remove_symbols as remove_symbols_cep

# CNPJ Imports
from brutils.cnpj import (
format_cnpj,
)
from brutils.cnpj import (
generate as generate_cnpj,
)
from brutils.cnpj import (
is_valid as is_valid_cnpj,
)
from brutils.cnpj import (
remove_symbols as remove_symbols_cnpj,
)
from brutils.cnpj import format_cnpj
from brutils.cnpj import generate as generate_cnpj
from brutils.cnpj import is_valid as is_valid_cnpj
from brutils.cnpj import remove_symbols as remove_symbols_cnpj

# CPF Imports
from brutils.cpf import (
format_cpf,
)
from brutils.cpf import (
generate as generate_cpf,
)
from brutils.cpf import (
is_valid as is_valid_cpf,
)
from brutils.cpf import (
remove_symbols as remove_symbols_cpf,
)
from brutils.cpf import format_cpf
from brutils.cpf import generate as generate_cpf
from brutils.cpf import is_valid as is_valid_cpf
from brutils.cpf import remove_symbols as remove_symbols_cpf

# Currency
from brutils.currency import format_currency

# Date imports
from brutils.date import convert_date_to_text
Expand All @@ -53,81 +34,43 @@
get_code_by_municipality_name,
get_municipality_by_code,
)
from brutils.ibge.uf import (
convert_code_to_uf,
)
from brutils.ibge.uf import convert_code_to_uf

# Legal Process Imports
from brutils.legal_process import (
format_legal_process,
)
from brutils.legal_process import (
generate as generate_legal_process,
)
from brutils.legal_process import (
is_valid as is_valid_legal_process,
)
from brutils.legal_process import (
remove_symbols as remove_symbols_legal_process,
)
from brutils.legal_process import format_legal_process
from brutils.legal_process import generate as generate_legal_process
from brutils.legal_process import is_valid as is_valid_legal_process
from brutils.legal_process import remove_symbols as remove_symbols_legal_process

# License Plate Imports
from brutils.license_plate import (
convert_to_mercosul as convert_license_plate_to_mercosul,
)
from brutils.license_plate import (
format_license_plate,
)
from brutils.license_plate import (
generate as generate_license_plate,
)
from brutils.license_plate import (
get_format as get_format_license_plate,
)
from brutils.license_plate import (
is_valid as is_valid_license_plate,
)
from brutils.license_plate import (
remove_symbols as remove_symbols_license_plate,
)
from brutils.license_plate import format_license_plate
from brutils.license_plate import generate as generate_license_plate
from brutils.license_plate import get_format as get_format_license_plate
from brutils.license_plate import is_valid as is_valid_license_plate
from brutils.license_plate import remove_symbols as remove_symbols_license_plate

# Phone Imports
from brutils.phone import (
format_phone,
remove_international_dialing_code,
remove_symbols_phone,
)
from brutils.phone import (
generate as generate_phone,
)
from brutils.phone import (
is_valid as is_valid_phone,
)
from brutils.phone import generate as generate_phone
from brutils.phone import is_valid as is_valid_phone

# PIS Imports
from brutils.pis import (
format_pis,
)
from brutils.pis import (
generate as generate_pis,
)
from brutils.pis import (
is_valid as is_valid_pis,
)
from brutils.pis import (
remove_symbols as remove_symbols_pis,
)
from brutils.pis import format_pis
from brutils.pis import generate as generate_pis
from brutils.pis import is_valid as is_valid_pis
from brutils.pis import remove_symbols as remove_symbols_pis

# Voter ID Imports
from brutils.voter_id import (
format_voter_id,
)
from brutils.voter_id import (
generate as generate_voter_id,
)
from brutils.voter_id import (
is_valid as is_valid_voter_id,
)
from brutils.voter_id import format_voter_id
from brutils.voter_id import generate as generate_voter_id
from brutils.voter_id import is_valid as is_valid_voter_id

# Defining __all__ to expose the public methods
__all__ = [
Expand Down Expand Up @@ -183,4 +126,6 @@
"convert_code_to_uf",
"get_municipality_by_code",
"get_code_by_municipality_name",
# Currency
"format_currency",
]
40 changes: 40 additions & 0 deletions brutils/currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from decimal import Decimal, InvalidOperation


def format_currency(value): # type: (float) -> str | None
"""
Formats a given float as Brazilian currency (R$).

This function takes a float value and returns a formatted string representing
the value as Brazilian currency, using the correct thousand and decimal separators.

Args:
value (float or Decimal): The numeric value to be formatted.

Returns:
str or None: A string formatted as Brazilian currency, or None if the input is invalid.

Example:
>>> format_currency(1234.56)
"R$ 1.234,56"
>>> format_currency(0)
"R$ 0,00"
>>> format_currency(-9876.54)
"R$ -9.876,54"
>>> format_currency(None)
None
>>> format_currency("not a number")
None
"""

try:
decimal_value = Decimal(value)
formatted_value = (
f"R$ {decimal_value:,.2f}".replace(",", "_")
.replace(".", ",")
.replace("_", ".")
)

return formatted_value
except InvalidOperation:
return None
27 changes: 27 additions & 0 deletions tests/test_currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from decimal import Decimal
from unittest import TestCase

from brutils.currency import format_currency


class TestFormatCurrency(TestCase):
def test_when_value_is_a_decimal_value(self):
assert format_currency(Decimal("123236.70")) == "R$ 123.236,70"

def test_when_value_is_a_float_value(self):
assert format_currency(123236.70) == "R$ 123.236,70"

def test_when_value_is_negative(self):
assert format_currency(-123236.70) == "R$ -123.236,70"

def test_when_value_is_zero(self):
print(format_currency(0))
assert format_currency(0) == "R$ 0,00"

def test_value_decimal_replace_rounding(self):
assert format_currency(-123236.7676) == "R$ -123.236,77"

def test_when_value_is_not_a_valid_currency(self):
assert format_currency("not a number") is None
assert format_currency("09809,87") is None
assert format_currency("897L") is None
Loading