[FIX] float parsing in paypal import

In English version of the files, paypal uses ',' as thousands separator and '.' as
decimal separator -> the previous code would populate the bank statement with
wrong values without complaining.

We fix this by allowing to configure the separators in the paypal map.
This commit is contained in:
Alexandre Fayolle
2019-05-13 15:17:38 +02:00
committed by Carlos Roca
parent ee5b26bf6b
commit 230bdfd7fd
6 changed files with 71 additions and 16 deletions

View File

@@ -2,7 +2,9 @@
<odoo noupdate="1"> <odoo noupdate="1">
<record id="paypal_map" model="account.bank.statement.import.paypal.map"> <record id="paypal_map" model="account.bank.statement.import.paypal.map">
<field name="name">Paypal Monthly Statement</field> <field name="name">Paypal Monthly Statement</field>
<field name="float_thousands_sep">comma</field>
<field name="float_decimal_sep">dot</field>
</record> </record>
<record id="paypal_map_line_date" model="account.bank.statement.import.paypal.map.line"> <record id="paypal_map_line_date" model="account.bank.statement.import.paypal.map.line">

View File

@@ -1,7 +1,7 @@
# Copyright 2019 Tecnativa - Vicent Cubells # Copyright 2019 Tecnativa - Vicent Cubells
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models from odoo import fields, models, api
class AccountBankStatementImportPaypalMap(models.Model): class AccountBankStatementImportPaypalMap(models.Model):
@@ -17,6 +17,50 @@ class AccountBankStatementImportPaypalMap(models.Model):
required=True, required=True,
copy=True, copy=True,
) )
float_thousands_sep = fields.Selection(
[('dot', 'dot (.)'),
('comma', 'comma (,)'),
('none', 'none'),
],
string='Thousands separator',
# forward compatibility: this was the value assumed
# before the field was added.
default='dot',
required=True
)
float_decimal_sep = fields.Selection(
[('dot', 'dot (.)'),
('comma', 'comma (,)'),
('none', 'none'),
],
string='Decimals separator',
# forward compatibility: this was the value assumed
# before the field was added.
default='comma',
required=True
)
@api.onchange('float_thousands_sep')
def onchange_thousands_separator(self):
if 'dot' == self.float_thousands_sep == self.float_decimal_sep:
self.float_decimal_sep = 'comma'
elif 'comma' == self.float_thousands_sep == self.float_decimal_sep:
self.float_decimal_sep = 'dot'
@api.onchange('float_decimal_sep')
def onchange_decimal_separator(self):
if 'dot' == self.float_thousands_sep == self.float_decimal_sep:
self.float_thousands_sep = 'comma'
elif 'comma' == self.float_thousands_sep == self.float_decimal_sep:
self.float_thousands_sep = 'dot'
def _get_separators(self):
separators = {'dot': '.',
'comma': ',',
'none': '',
}
return (separators[self.float_thousands_sep],
separators[self.float_decimal_sep])
class AccountBankStatementImportPaypalMapLIne(models.Model): class AccountBankStatementImportPaypalMapLIne(models.Model):

View File

@@ -1,3 +1,3 @@
"Date","Time","Time Zone","Description","Currency","Gross","Fee ","Net","Balance","Transaction ID","From Email Address","Name","Bank Name","Bank Account","Shipping and Handling Amount","Sales Tax","Invoice ID","Reference Txn ID" "Date","Time","Time Zone","Description","Currency","Gross","Fee ","Net","Balance","Transaction ID","From Email Address","Name","Bank Name","Bank Account","Shipping and Handling Amount","Sales Tax","Invoice ID","Reference Txn ID"
"12/15/2018","20:07:53","CET","Your best supplier","USD","-33,50","-2,3","-31,2","-31,2","53820712527632627","","John Doe","Bank of America","123456789","0","0","INV25","23" "12/15/2018","20:07:53","CET","Your best supplier","USD","-33.50","-2.3","-31.2","-31.2","53820712527632627","","John Doe","Bank of America","123456789","0","0","INV25","23"
"12/15/2018","22:07:53","CET","Your payment","USD","525","0","525","493,80","34731322767782103","","Agrolait","","","0","0","INV/2019/0003","24" "12/15/2018","22:07:53","CET","Your payment","USD","1,525.00","0","1,525.00","1,493.80","34731322767782103","","Agrolait","","","0","0","INV/2019/0003","24"
1 Date Time Time Zone Description Currency Gross Fee Net Balance Transaction ID From Email Address Name Bank Name Bank Account Shipping and Handling Amount Sales Tax Invoice ID Reference Txn ID
2 12/15/2018 20:07:53 CET Your best supplier USD -33,50 -33.50 -2,3 -2.3 -31,2 -31.2 -31,2 -31.2 53820712527632627 John Doe Bank of America 123456789 0 0 INV25 23
3 12/15/2018 22:07:53 CET Your payment USD 525 1,525.00 0 525 1,525.00 493,80 1,493.80 34731322767782103 Agrolait 0 0 INV/2019/0003 24

View File

@@ -38,8 +38,10 @@ class TestPaypalFile(common.SavepointCase):
# Current statements before to run the wizard # Current statements before to run the wizard
old_statements = self.env['account.bank.statement'].search([]) old_statements = self.env['account.bank.statement'].search([])
# This journal is for Paypal statements # This journal is for Paypal statements
map = self.env.ref('account_bank_statement_import_paypal.paypal_map') paypal_map = self.env.ref(
self.journal.paypal_map_id = map.id 'account_bank_statement_import_paypal.paypal_map'
)
self.journal.paypal_map_id = paypal_map.id
file = self._do_import('paypal_en.csv') file = self._do_import('paypal_en.csv')
file = base64.b64encode(file.encode("utf-8")) file = base64.b64encode(file.encode("utf-8"))
wizard = self.env['account.bank.statement.import'].with_context({ wizard = self.env['account.bank.statement.import'].with_context({
@@ -51,4 +53,6 @@ class TestPaypalFile(common.SavepointCase):
self.assertEqual(len(statement.line_ids), 3) self.assertEqual(len(statement.line_ids), 3)
self.assertEqual(len(statement.mapped('line_ids').filtered( self.assertEqual(len(statement.mapped('line_ids').filtered(
lambda x: x.partner_id and x.account_id)), 1) lambda x: x.partner_id and x.account_id)), 1)
self.assertAlmostEqual(sum(statement.mapped('line_ids.amount')), 489.2) self.assertAlmostEqual(
sum(statement.mapped('line_ids.amount')), 1489.2
)

View File

@@ -16,6 +16,8 @@
<form string="Paypal Map"> <form string="Paypal Map">
<group> <group>
<field name="name"/> <field name="name"/>
<field name="float_thousands_sep"/>
<field name="float_decimal_sep"/>
</group> </group>
<separator string="Mapping Lines"/> <separator string="Mapping Lines"/>
<field name="map_line_ids"/> <field name="map_line_ids"/>

View File

@@ -55,10 +55,13 @@ class AccountBankStatementImport(models.TransientModel):
@api.model @api.model
def _paypal_convert_amount(self, amount_str): def _paypal_convert_amount(self, amount_str):
""" This method is designed to be inherited """ if self.paypal_map_id:
valstr = re.sub(r'[^\d,.-]', '', amount_str) thousands, decimal = self.paypal_map_id._get_separators()
valstrdot = valstr.replace('.', '') else:
valstrdot = valstrdot.replace(',', '.') thousands, decimal = ',', '.'
valstr = re.sub(r'[^\d%s%s.-]' % (thousands, decimal), '', amount_str)
valstrdot = valstr.replace(thousands, '')
valstrdot = valstrdot.replace(decimal, '.')
return float(valstrdot) return float(valstrdot)
@api.model @api.model
@@ -77,19 +80,19 @@ class AccountBankStatementImport(models.TransientModel):
def _convert_paypal_line_to_dict(self, idx, line): def _convert_paypal_line_to_dict(self, idx, line):
rline = dict() rline = dict()
for item in range(len(line)): for item in range(len(line)):
map = self.mapped('paypal_map_id.map_line_ids')[item] paypal_map = self.mapped('paypal_map_id.map_line_ids')[item]
value = line[item] value = line[item]
if not map.field_to_assign: if not paypal_map.field_to_assign:
continue continue
if map.date_format: if paypal_map.date_format:
try: try:
value = fields.Date.to_string( value = fields.Date.to_string(
datetime.strptime(value, map.date_format)) datetime.strptime(value, paypal_map.date_format))
except Exception: except Exception:
raise UserError( raise UserError(
_("Date format of map file and Paypal date does " _("Date format of map file and Paypal date does "
"not match.")) "not match."))
rline[map.field_to_assign] = value rline[paypal_map.field_to_assign] = value
for field in ['commission', 'amount', 'balance']: for field in ['commission', 'amount', 'balance']:
_logger.debug('Trying to convert %s to float' % rline[field]) _logger.debug('Trying to convert %s to float' % rline[field])