Closed salsotto closed 9 years ago
Basta você passar um decimal diretamente ou uma string contendo o ponto.
Por exemplo:
Decimal(19,90) == Decimal(19.90) False
Se você passa com a vírgula, dá erro:
item1 = PagSeguroItem(id='0001', description='Meu item 0001', amount='100,00', quantity=1) Traceback (most recent call last): File "
", line 1, in File "/Users/allisson/Projects/django-pagseguro2/pagseguro/api.py", line 45, in init raise Exception(form.errors.items()) Exception: [('amount', [u'Enter a number.'])]
Passando com o ponto tudo ocorre normalmente:
item1 = PagSeguroItem(id='0001', description='Meu item 0001', amount='100.00', quantity=1)
Você também pode criar um decimal diretamente e passar no amount:
amount = Decimal('19.90') item1 = PagSeguroItem(id='0001', description='Meu item 0001', amount=amount, quantity=1)
Em resumo, como essa validação é feita com decimal, é só passar '19.90' no lugar de '19,90' :)
Fiz esse pedido aqui usando o sandbox:
django-pagseguro2)allisson@Allissons-MacBook-Pro:~/Projects/django-pagseguro2> testapp/manage.py shell Python 2.7.8 (default, Oct 19 2014, 16:02:00) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole)
from pagseguro.api import PagSeguroItem, PagSeguroApi item1 = PagSeguroItem(id='0001', description='Meu item 0001', amount='100.90', quantity=1) item2 = PagSeguroItem(id='0002', description='Meu item 0002', amount='150.90', quantity=1, shipping_cost='25.00', weight=500) pagseguro_api = PagSeguroApi(reference='id-unico-de-referencia-do-seu-sistema') pagseguro_api.add_item(item1) pagseguro_api.add_item(item2) data = pagseguro_api.checkout()
Indo para o redirect_url os valores estão ok, mesmo usando 100.90 e 150.90.
No meu caso, o valor é salvo no banco de dados como 19.9 e não salva o zero. Esse é o problema. O que eu passo para o objeto de fato é 19.9 (DecimalField) e não 19,90.
Estava assim: item = PagSeguroItem(id=plano.id, description=plano.nome_pagseguro, amount=plano.value, quantity=1)
e modifiquei assim: item = PagSeguroItem(id=plano.id, description=plano.nome_pagseguro, amount=format(plano.value, '.2f'), quantity=1)
Você tá salvando um valor no banco com apenas uma casa decimal?
Como tá esse seu field no model?
O campo está configurado da seguinte maneira:
value = models.DecimalField(verbose_name=(u"Valor"), max_digits=10, decimal_places=2)
No entanto, se eu salvo qualquer valor que não termine com zero ele salva normalmente com as duas casas decimais, exemplo: 19,99 é salvo como 19.99.
Nesse caso é um bug no django ehheeheheh.
Você está usando sqlite como banco? Em caso positivo isso é um bug mesmo porque o sqlite não tem campo decimal: http://stackoverflow.com/questions/5418788/different-behavior-for-django-decimalfield-on-sqlite-vs-mysql/5419834#5419834
Então é isso ai mesmo... estou usando o sqlite no desenvolvimento.
Mas de todo modo, você não acha que seria interessante assegurar que o parâmetro passado seja um valor decimal dentro do padrão do Pagseguro? Digo isso porque o erro que de fato me retornou no Django foi que o dicionário não possuia a chave 'redirect_url'.
Descobri o erro 11029 debugando. Talvez uma exceção direcionando o erro do Pagseguro?
E o que acha de tratar também esse caso do sqlite no objeto, pois não impactará de forma negativa para outras bases e garantirá o uso da app sem necessidades de ajustes da parte de quem usufrui.
Por favor, não entenda mal minhas sugestões, penso apenas maneiras de ajudar! ;)
Valeu pela atenção!
Eu estou usando o django forms para validar os dados, o problema que eu vi aqui é que o decimal_places=2 no form não garante que ele vai ter duas casas, garante que ele vai ter no máximo duas casas.
Eu pensei que ele seguia a mesma regra do decimalfield no model, de qualquer forma, eu vou fazer uma verificação manual pra garantir que o item não seja criado com menos de duas casas decimais.
:)
Seria legal garantir também que o valor passado seja um decimal.
O django forms já faz essa conversão caso o valor passado seja uma string, então nesse caso não precisa.
Acredito que validando o número mínimo de casas decimais resolve todos os problemas :)
Allison,
Enfrentei alguns problemas ao passar valores decimais com "zero" no final no PagSeguroItem. Exemplo: 19,90 era passado como 19.9.
Sugiro tratar isso diretamente na criação do objeto, uma vez que necessariamente esse parâmetro deve seguir o padão especificado do item 11029 (Item amount invalid pattern: {0}. Must fit the patern: \d+.\d{2}) na tabela de códigos de erro da API.
Sugestões: 1) Cast do parâmetro para Float 2) Formatação de duas casas decimais: format(value, '.2f')
Obs.: equivale para o shippingCost que segue o mesmo padrão.
Talvez você possa achar uma forma mais elegante, mas por hora são essas minhas sugestões.
Abraços!