brazilian-utils / brutils-python

Biblioteca de utilitários projetada para validar, gerar e manipular dados de acordo com as particularidades do Brasil 🇧🇷
https://pypi.python.org/pypi/brutils
MIT License
248 stars 59 forks source link

Conversão de Moeda Real para Texto #387

Open camilamaia opened 1 month ago

camilamaia commented 1 month ago

Aqui está a versão atualizada da issue:


Seu pedido de recurso está relacionado a um problema? Por favor, descreva.

Dado um número que representa um valor monetário em Reais, quero obter uma String correspondente a esse valor convertido em texto por extenso, seguindo as regras gramaticais e monetárias do Brasil.

Por exemplo, converter 1523.45 para "Mil quinhentos e vinte e três reais e quarenta e cinco centavos".

Descreva a solução que você gostaria

Descreva alternativas que você considerou

  1. Seguir até o passo 8 do guia de contribuição

  2. Como parte do passo 8, criar o arquivo: brutils-python/brutils/currency.py.

    def convert_real_to_text(amount): # type: (decimal) -> str | None
        """
        Converts a given monetary value in Brazilian Reais to its textual representation.
    
        This function takes a decimal number representing a monetary value in Reais 
        and converts it to a string with the amount written out in Brazilian Portuguese. It 
        handles both the integer part (Reais) and the fractional part (centavos), respecting 
        the correct grammar for singular and plural cases, as well as special cases like zero 
        and negative values.
    
        Args:
            amount (decimal): The monetary value to be converted into text. 
                - The integer part represents Reais.
                - The decimal part represents centavos.
                - 2 decimal places
    
        Returns:
            str: A string with the monetary value written out in Brazilian Portuguese.
                - Returns "Zero reais" for a value of 0.00.
                - Returns None if the amount is invalid.
                - Handles negative values, adding "Menos" at the beginning of the string.
    
        Example:
            >>> convert_real_to_text(1523.45)
            "Mil quinhentos e vinte e três reais e quarenta e cinco centavos"
            >>> convert_real_to_text(1.00)
            "Um real"
            >>> convert_real_to_text(0.50)
            "Cinquenta centavos"
            >>> convert_real_to_text(0.00)
            "Zero reais"
            >>> convert_real_to_text(-50.25)
            "Menos cinquenta reais e vinte e cinco centavos"
        """    
        # implementar a lógica da função aqui

    Importar a nova função no arquivo brutils-python/brutils/__init__.py

    # Currency Imports    
    from brutils.currency import (
        convert_real_to_text,
    )

    E adicionar o nome da nova função na lista __all__ do mesmo arquivo brutils-python/brutils/__init__.py:

    __all__ = [
        ...
        # Currency
        convert_real_to_text
    ]
  3. Como parte do passo 9, criar o arquivo de teste: brutils-python/tests/test_currency.py

    from unittest import TestCase
    from brutils.currency import convert_real_to_text
    
    class TestCurrency(TestCase):
        def test_convert_real_to_text(self):
            self.assertEqual(convert_real_to_text(0.00), "Zero reais")
            self.assertEqual(convert_real_to_text(0.01), "Um centavo")
            self.assertEqual(convert_real_to_text(0.50), "Cinquenta centavos")
            self.assertEqual(convert_real_to_text(1.00), "Um real")
            self.assertEqual(convert_real_to_text(-50.25), "Menos cinquenta reais e vinte e cinco centavos")
            self.assertEqual(convert_real_to_text(1523.45), "Mil quinhentos e vinte e três reais e quarenta e cinco centavos")
            self.assertEqual(convert_real_to_text(1000000.00), "Um milhão de reais")
            self.assertEqual(convert_real_to_text(2000000.00), "Dois milhões de reais")
            self.assertEqual(convert_real_to_text(1000000000.00), "Um bilhão de reais")
            self.assertEqual(convert_real_to_text(2000000000.00), "Dois bilhões de reais")
            self.assertEqual(convert_real_to_text(1000000000000.00), "Um trilhão de reais")
            self.assertEqual(convert_real_to_text(2000000000000.00), "Dois trilhões de reais")
            self.assertEqual(convert_real_to_text(1000000.45), "Um milhão de reais e quarenta e cinco centavos")
            self.assertEqual(convert_real_to_text(2000000000.99), "Dois bilhões de reais e noventa e nove centavos")
            self.assertEqual(convert_real_to_text(1234567890.50), "Um bilhão duzentos e trinta e quatro milhões quinhentos e sessenta e sete mil oitocentos e noventa reais e cinquenta centavos")
    
            # Valores próximos a zero
            self.assertEqual(convert_real_to_text(0.001), "Zero reais")
            self.assertEqual(convert_real_to_text(0.009), "Zero reais")
    
            # Valores negativos em milhões
            self.assertEqual(convert_real_to_text(-1000000.00), "Menos um milhão de reais")
            self.assertEqual(convert_real_to_text(-2000000.50), "Menos dois milhões de reais e cinquenta centavos")
    
            # Valores grandes com centavos
            self.assertEqual(convert_real_to_text(1000000000.01), "Um bilhão de reais e um centavo")
            self.assertEqual(convert_real_to_text(1000000000.99), "Um bilhão de reais e noventa e nove centavos")
    
            # Teste de edge cases para retorno de None
            self.assertIsNone(convert_real_to_text("invalid_value"))  # Valor não numérico
            self.assertIsNone(convert_real_to_text(None))  # None como argumento
            self.assertIsNone(convert_real_to_text(-9999999999999.99))  # Valor fora do alcance esperado (abaixo de -1 trilhão)
            self.assertIsNone(convert_real_to_text(9999999999999.99))  # Valor fora do alcance esperado (acima de 1 trilhão)
            self.assertIsNone(convert_real_to_text(float('inf')))  # Infinito
            self.assertIsNone(convert_real_to_text(float('nan')))  # Not a number (NaN)
    
            # implementar mais casos de teste aqui se necessário
  4. Seguir os passos seguintes do guia de contribuição

Contexto adicional

amberploencio commented 1 month ago

Bora!

camilamaia commented 1 month ago

@amberploencio te dei o assign! O bora tem que ter o !no final 😅

JoaquimCassano commented 1 month ago

@amberploencio Eu tinha feito uma implementação simples, convertendo um código que fazia isso do stackoverflow de PHP pra python, se quiser fazer em cima: https://github.com/JoaquimCassano/brutils-python/tree/main/brutils