Browse Source

[IMP] account_bank_statement_import_paypal: better wizard

12.0
Alexey Pelykh 4 years ago
parent
commit
5703ac3ef7
  1. 2
      account_bank_statement_import_paypal/__manifest__.py
  2. 47
      account_bank_statement_import_paypal/data/maps.xml
  3. 10
      account_bank_statement_import_paypal/tests/fixtures/statement_en.csv
  4. 5
      account_bank_statement_import_paypal/tests/fixtures/statement_es.csv
  5. 77
      account_bank_statement_import_paypal/tests/test_account_bank_statement_import_paypal.py
  6. 180
      account_bank_statement_import_paypal/wizards/account_bank_statement_import_paypal_mapping_wizard.py
  7. 149
      account_bank_statement_import_paypal/wizards/account_bank_statement_import_paypal_mapping_wizard.xml
  8. 1
      oca_dependencies.txt

2
account_bank_statement_import_paypal/__manifest__.py

@ -17,6 +17,8 @@
'installable': True,
'depends': [
'account_bank_statement_import',
'multi_step_wizard',
'web_widget_dropdown_dynamic',
],
'external_dependencies': {
'python': [

47
account_bank_statement_import_paypal/data/maps.xml

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Tecnativa - Vicent Cubells
Copyright 2019 Brainbean Apps (https://brainbeanapps.com)
Copyright 2019-2020 Brainbean Apps (https://brainbeanapps.com)
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<odoo noupdate="1">
@ -51,4 +51,49 @@
<field name="note_column">Note</field>
</record>
<record id="paypal_statement_map_es" model="account.bank.statement.import.paypal.mapping">
<field name="name">PayPal Statement (ES)</field>
<field name="float_thousands_sep">dot</field>
<field name="float_decimal_sep">comma</field>
<field name="date_format">%d/%m/%Y</field>
<field name="time_format">%H:%M:%S</field>
<field name="date_column">Fecha</field>
<field name="time_column">Hora</field>
<field name="tz_column">Zona horaria</field>
<field name="name_column">Nombre</field>
<field name="currency_column">Divisa</field>
<field name="gross_column">Bruto</field>
<field name="fee_column">Comisión</field>
<field name="balance_column">Saldo</field>
<field name="transaction_id_column">Id. de transacción</field>
<field name="description_column">Descripción</field>
<field name="from_email_address_column">Correo electrónico del remitente</field>
<field name="invoice_id_column">Id. de factura</field>
<field name="bank_name_column">Nombre del banco</field>
<field name="bank_account_column">Cuenta bancaria</field>
</record>
<record id="paypal_activity_map_es" model="account.bank.statement.import.paypal.mapping">
<field name="name">PayPal Activity (ES)</field>
<field name="float_thousands_sep">dot</field>
<field name="float_decimal_sep">comma</field>
<field name="date_format">%d/%m/%Y</field>
<field name="time_format">%H:%M:%S</field>
<field name="date_column">Fecha</field>
<field name="time_column">Hora</field>
<field name="tz_column">Zona horaria</field>
<field name="name_column">Nombre</field>
<field name="currency_column">Divisa</field>
<field name="gross_column">Bruto</field>
<field name="fee_column">Tarifa</field>
<field name="balance_column">Saldo</field>
<field name="transaction_id_column">Id. de transacción</field>
<field name="type_column">Tipo</field>
<field name="from_email_address_column">Correo electrónico del remitente</field>
<field name="to_email_address_column">Correo electrónico del destinatario</field>
<field name="invoice_id_column">Número de factura</field>
<field name="subject_column">Asunto</field>
<field name="note_column">Nota</field>
</record>
</odoo>

10
account_bank_statement_import_paypal/tests/fixtures/statement_en.csv

@ -9,12 +9,12 @@
"9/27/2018","21:33:27","America/Los_Angeles","General Currency Conversion","EUR","9,648.13","0.00","9,648.13","0.75","TID8","","","","","0.00","0.00","","TID7"
"9/4/2018","20:44:10","America/Los_Angeles","Express Checkout Payment","USD","1,309.80","-48.76","1,261.04","1,261.93","TID9","paypal@partner1.com","Partner 1","","","0.00","0.00","361",""
"9/4/2018","21:15:11","America/Los_Angeles","General Currency Conversion","USD","-1,261.00","0.00","-1,261.00","0.93","TID10","","","","","0.00","0.00","","TID1"
"9/10/2018","17:48:19","America/Los_Angeles","Express Checkout Payment","USD","3,840.60","-142.40","3,698.20","3,699.13","TID11","paypa@partner2.com","Partner 2","","","0.00","0.00","362",""
"9/10/2018","17:48:19","America/Los_Angeles","Express Checkout Payment","USD","3,840.60","-142.40","3,698.20","3,699.13","TID11","paypal@partner2.com","Partner 2","","","0.00","0.00","362",""
"9/11/2018","00:01:50","America/Los_Angeles","General Currency Conversion","USD","-3,699.00","0.00","-3,699.00","0.13","TID12","","","","","0.00","0.00","","TID3"
"9/24/2018","16:41:01","America/Los_Angeles","Express Checkout Payment","USD","4,447.40","-164.85","4,282.55","4,282.68","TID13","paypa@partner2.com","Partner 2","","","0.00","0.00","363",""
"9/24/2018","16:41:01","America/Los_Angeles","Express Checkout Payment","USD","4,447.40","-164.85","4,282.55","4,282.68","TID13","paypal@partner2.com","Partner 2","","","0.00","0.00","363",""
"9/25/2018","04:22:39","America/Los_Angeles","General Currency Conversion","USD","-4,282.00","0.00","-4,282.00","0.68","TID14","","","","","0.00","0.00","","TID5"
"9/27/2018","18:15:34","America/Los_Angeles","Express Checkout Payment","USD","5,600.00","-207.50","5,392.50","5,393.18","TID15","paypa@partner3.com","Partner 3","","","0.00","0.00","366",""
"9/27/2018","18:16:12","CET","Express Checkout Payment","USD","920.70","-34.37","886.33","6,279.51","TID16","paypa@partner3.com","Partner 3","","","0.00","0.00","367",""
"9/27/2018","18:17:59","America/Los_Angeles","Express Checkout Payment","USD","5,600.00","-207.50","5,392.50","11,672.01","TID17","paypa@partner3.com","Partner 3","","","0.00","0.00","371",""
"9/27/2018","18:15:34","America/Los_Angeles","Express Checkout Payment","USD","5,600.00","-207.50","5,392.50","5,393.18","TID15","paypal@partner3.com","Partner 3","","","0.00","0.00","366",""
"9/27/2018","18:16:12","CET","Express Checkout Payment","USD","920.70","-34.37","886.33","6,279.51","TID16","paypal@partner3.com","Partner 3","","","0.00","0.00","367",""
"9/27/2018","18:17:59","America/Los_Angeles","Express Checkout Payment","USD","5,600.00","-207.50","5,392.50","11,672.01","TID17","paypal@partner3.com","Partner 3","","","0.00","0.00","371",""
"9/27/2018","21:33:27","America/Los_Angeles","General Currency Conversion","USD","-11,672.00","0.00","-11,672.00","0.01","TID18","","","","","0.00","0.00","","TID7"
"9/30/2018","21:22:33","America/Los_Angeles","Express Checkout Payment","USD","292.30","-11.12","281.18","281.19","TID19","paypal@partner1.com","Partner 1","","","0.00","0.00","380",""

5
account_bank_statement_import_paypal/tests/fixtures/statement_es.csv

@ -0,0 +1,5 @@
"Fecha","Hora","Zona horaria","Descripción","Divisa","Bruto","Comisión","Neto","Saldo","Id. de transacción","Correo electrónico del remitente","Nombre","Nombre del banco","Cuenta bancaria","Importe de envío y manipulación","Impuesto de ventas","Id. de factura","Id. de referencia de trans.",,,,,,
"2/1/2020","11:05:56","Europe/Berlin","Pago estándar","EUR","49,37","-1,78","47,59","4.626,81","TID1","paypal@partner1.com","Partner 1","","","0,00","0,00","",""
"2/1/2020","13:06:07","Europe/Berlin","Pago estándar","EUR","28,82","-1,19","27,63","4.654,44","TID2","paypal@partner2.com","Partner 2","","","0,00","0,00","",""
"2/1/2020","19:20:05","Europe/Berlin","Pago estándar","EUR","35,78","-1,39","34,39","4.688,83","TID3","paypal@partner3.com","Partner 3","","","0,00","0,00","",""
"3/1/2020","09:44:24","Europe/Berlin","Pago estándar","EUR","22,47","-1,00","21,47","4.710,30","TID4","paypal@partner4.com","Partner 4","","","0,00","0,00","",""

77
account_bank_statement_import_paypal/tests/test_account_bank_statement_import_paypal.py

@ -20,6 +20,9 @@ class TestAccountBankStatementImportPayPal(common.TransactionCase):
self.paypal_statement_map_en = self.env.ref(
'account_bank_statement_import_paypal.paypal_statement_map_en'
)
self.paypal_statement_map_es = self.env.ref(
'account_bank_statement_import_paypal.paypal_statement_map_es'
)
self.paypal_activity_map_en = self.env.ref(
'account_bank_statement_import_paypal.paypal_activity_map_en'
)
@ -63,6 +66,30 @@ class TestAccountBankStatementImportPayPal(common.TransactionCase):
self.assertEqual(len(statement), 1)
self.assertEqual(len(statement.line_ids), 18)
def test_import_statement_es(self):
journal = self.AccountJournal.create({
'name': 'PayPal',
'type': 'bank',
'code': 'PP',
'currency_id': self.currency_eur.id,
})
wizard = self.AccountBankStatementImport.with_context({
'journal_id': journal.id,
}).create({
'filename': 'fixtures/statement_es.csv',
'data_file': self._data_file('fixtures/statement_es.csv'),
'paypal_mapping_id': self.paypal_statement_map_es.id,
})
wizard.with_context({
'journal_id': journal.id,
'account_bank_statement_import_paypal_test': True,
}).import_file()
statement = self.AccountBankStatement.search([
('journal_id', '=', journal.id),
])
self.assertEqual(len(statement), 1)
self.assertEqual(len(statement.line_ids), 8)
def test_import_activity_en(self):
journal = self.AccountJournal.create({
'name': 'PayPal',
@ -112,21 +139,39 @@ class TestAccountBankStatementImportPayPal(common.TransactionCase):
self.assertEqual(len(statement), 0)
def test_import_activity_mapping_en(self):
wizard = self.AccountBankStatementImportPayPalMappingWizard.create({
'filename': 'fixtures/activity_en.csv',
'data_file': self._data_file('fixtures/activity_en.csv'),
})
mapping = self.AccountBankStatementImportPayPalMapping.browse(
wizard.import_mapping()['res_id']
)
self.assertTrue(mapping)
with common.Form(
self.AccountBankStatementImportPayPalMappingWizard) as form:
form.filename = 'fixtures/activity_en.csv'
form.data_file = self._data_file(
'fixtures/activity_en.csv'
)
self.assertEqual(
len(
self.AccountBankStatementImportPayPalMappingWizard
.with_context(
header=form.header,
).statement_columns()
),
22
)
wizard = form.save()
wizard.import_mapping()
def test_import_statement_mapping_en(self):
wizard = self.AccountBankStatementImportPayPalMappingWizard.create({
'filename': 'fixtures/statement_en.csv',
'data_file': self._data_file('fixtures/statement_en.csv'),
})
mapping = self.AccountBankStatementImportPayPalMapping.browse(
wizard.import_mapping()['res_id']
)
self.assertTrue(mapping)
with common.Form(
self.AccountBankStatementImportPayPalMappingWizard) as form:
form.filename = 'fixtures/statement_en.csv'
form.data_file = self._data_file(
'fixtures/statement_en.csv'
)
self.assertEqual(
len(
self.AccountBankStatementImportPayPalMappingWizard
.with_context(
header=form.header,
).statement_columns()
),
18
)
wizard = form.save()
wizard.import_mapping()

180
account_bank_statement_import_paypal/wizards/account_bank_statement_import_paypal_mapping_wizard.py

@ -1,78 +1,162 @@
# Copyright 2019 Tecnativa - Vicent Cubells
# Copyright 2019 Brainbean Apps (https://brainbeanapps.com)
# Copyright 2019-2020 Brainbean Apps (https://brainbeanapps.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from base64 import b64decode
import json
from os import path
class AccountBankStatementImportPayPalMappingWizard(models.TransientModel):
_name = 'account.bank.statement.import.paypal.mapping.wizard'
_description = 'Account Bank Statement Import PayPal Mapping Wizard'
_inherit = ['multi.step.wizard.mixin']
data_file = fields.Binary(
string='Bank Statement File',
string='PayPal Report File',
required=True,
)
filename = fields.Char()
header = fields.Char()
date_column = fields.Char(
string='"Date" column',
)
time_column = fields.Char(
string='"Time" column',
)
tz_column = fields.Char(
string='"Timezone" column',
)
name_column = fields.Char(
string='"Name" column',
)
currency_column = fields.Char(
string='"Currency" column',
)
gross_column = fields.Char(
string='"Gross" column',
)
fee_column = fields.Char(
string='"Fee" column',
)
balance_column = fields.Char(
string='"Balance" column',
)
transaction_id_column = fields.Char(
string='"Transaction ID" column',
)
description_column = fields.Char(
string='"Description" column',
)
type_column = fields.Char(
string='"Type" column',
)
from_email_address_column = fields.Char(
string='"From Email Address" column',
)
to_email_address_column = fields.Char(
string='"To Email Address" column',
)
invoice_id_column = fields.Char(
string='"Invoice ID" column',
)
subject_column = fields.Char(
string='"Subject" column',
)
note_column = fields.Char(
string='"Note" column',
)
bank_name_column = fields.Char(
string='"Bank Name" column',
)
bank_account_column = fields.Char(
string='"Bank Account" column',
)
@api.onchange('data_file')
def _onchange_data_file(self):
Parser = self.env['account.bank.statement.import.paypal.parser']
if not self.data_file:
return
header = Parser.parse_header(b64decode(self.data_file))
header = [column for column in header if column]
self.header = json.dumps(header)
if len(header) == 22:
self.date_column = header[0]
self.time_column = header[1]
self.tz_column = header[2]
self.name_column = header[3]
self.currency_column = header[6]
self.gross_column = header[7]
self.fee_column = header[8]
self.balance_column = header[18]
self.transaction_id_column = header[12]
self.type_column = header[4]
self.from_email_address_column = header[10]
self.to_email_address_column = header[11]
self.invoice_id_column = header[16]
self.subject_column = header[20]
self.note_column = header[21]
elif len(header) == 18:
self.date_column = header[0]
self.time_column = header[1]
self.tz_column = header[2]
self.name_column = header[11]
self.currency_column = header[4]
self.gross_column = header[5]
self.fee_column = header[6]
self.balance_column = header[8]
self.transaction_id_column = header[9]
self.description_column = header[3]
self.from_email_address_column = header[10]
self.invoice_id_column = header[16]
self.bank_name_column = header[12]
self.bank_account_column = header[13]
@api.model
def statement_columns(self):
header = self.env.context.get('header')
if not header:
return []
return [(x, x) for x in json.loads(header)]
@api.multi
def import_mapping(self):
def _get_mapping_values(self):
"""Hook for extension"""
self.ensure_one()
mapping_values = {
return {
'name': _('Mapping from %s') % path.basename(self.filename),
'float_thousands_sep': 'comma',
'float_decimal_sep': 'dot',
'date_format': '%d/%m/%Y',
'time_format': '%H:%M:%S',
'date_column': self.date_column,
'time_column': self.time_column,
'tz_column': self.tz_column,
'name_column': self.name_column,
'currency_column': self.currency_column,
'gross_column': self.gross_column,
'fee_column': self.fee_column,
'balance_column': self.balance_column,
'transaction_id_column': self.transaction_id_column,
'description_column': self.description_column,
'type_column': self.type_column,
'from_email_address_column': self.from_email_address_column,
'to_email_address_column': self.to_email_address_column,
'invoice_id_column': self.invoice_id_column,
'subject_column': self.subject_column,
'note_column': self.note_column,
'bank_name_column': self.bank_name_column,
'bank_account_column': self.bank_account_column,
}
header = self.env['account.bank.statement.import.paypal.parser'] \
.parse_header(b64decode(self.data_file))
if len(header) == 22:
mapping_values.update({
'date_column': header[0],
'time_column': header[1],
'tz_column': header[2],
'name_column': header[3],
'currency_column': header[6],
'gross_column': header[7],
'fee_column': header[8],
'balance_column': header[18],
'transaction_id_column': header[12],
'type_column': header[4],
'from_email_address_column': header[10],
'to_email_address_column': header[11],
'invoice_id_column': header[16],
'subject_column': header[20],
'note_column': header[21],
})
elif len(header) == 18:
mapping_values.update({
'date_column': header[0],
'time_column': header[1],
'tz_column': header[2],
'name_column': header[11],
'currency_column': header[4],
'gross_column': header[5],
'fee_column': header[6],
'balance_column': header[8],
'transaction_id_column': header[9],
'description_column': header[3],
'from_email_address_column': header[10],
'invoice_id_column': header[16],
'bank_name_column': header[12],
'bank_account_column': header[13],
})
else:
raise UserError(_(
'File structure does not look like a PayPal report, please '
'check the file or create the mapping manually.'
))
@api.multi
def import_mapping(self):
self.ensure_one()
mapping = self.env['account.bank.statement.import.paypal.mapping']\
.create(mapping_values)
.create(self._get_mapping_values())
return {
'type': 'ir.actions.act_window',
'name': _('Imported Mapping'),

149
account_bank_statement_import_paypal/wizards/account_bank_statement_import_paypal_mapping_wizard.xml

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Tecnativa - Vicent Cubells
Copyright 2019 Brainbean Apps (https://brainbeanapps.com)
Copyright 2019-2020 Brainbean Apps (https://brainbeanapps.com)
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<odoo>
@ -9,16 +9,147 @@
<record id="account_bank_statement_import_paypal_mapping_wizard_form" model="ir.ui.view">
<field name="name">account.bank.statement.import.paypal.mapping.wizard.form</field>
<field name="model">account.bank.statement.import.paypal.mapping.wizard</field>
<field name="mode">primary</field>
<field name="inherit_id" ref="multi_step_wizard.multi_step_wizard_form"/>
<field name="arch" type="xml">
<form>
<xpath expr="//footer" position="before">
<h2>Select a PayPal report file to import mapping.</h2>
<field name="data_file" filename="filename" placeholder="Choose a file to import..."/>
<field name="filename" invisible="1"/>
<footer>
<button name="import_mapping" string="Import" type="object" class="btn-primary" />
<button string="Cancel" class="btn-default" special="cancel"/>
</footer>
</form>
<group name="start" attrs="{'invisible': [('state', '!=', 'start')]}">
<group colspan="2">
<field name="data_file" filename="filename" placeholder="Choose a file to import..."/>
<field name="filename" invisible="1"/>
</group>
</group>
<group name="final" attrs="{'invisible': [('state', '!=', 'final')]}">
<group colspan="2">
<field name="header" invisible="1"/>
<field
name="date_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="time_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="tz_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="name_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="currency_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="gross_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="fee_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="balance_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="transaction_id_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
attrs="{'required': [('state', '=', 'final')]}"
/>
<field
name="description_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="type_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="from_email_address_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="to_email_address_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="invoice_id_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="subject_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="note_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="bank_name_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
<field
name="bank_account_column"
widget="dynamic_dropdown"
values="statement_columns"
context="{'header': header}"
/>
</group>
</group>
</xpath>
<xpath expr="//div[@name='final_buttons']/button" position="attributes">
<attribute name="class">btn-default</attribute>
<attribute name="string">Cancel</attribute>
</xpath>
<xpath expr="//div[@name='final_buttons']/button" position="before">
<button name="import_mapping" string="Import" type="object" class="btn-primary" />
</xpath>
</field>
</record>

1
oca_dependencies.txt

@ -1 +1,2 @@
web
server-ux
Loading…
Cancel
Save