Browse Source
Merge pull request #161 from Tecnativa/11.0-mig_account_bank_statement_import_paypal
Merge pull request #161 from Tecnativa/11.0-mig_account_bank_statement_import_paypal
[MIG]account_bank_statement_import_paypal: Migration to 11.0pull/182/merge
Pedro M. Baeza
6 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 432 additions and 0 deletions
-
105account_bank_statement_import_paypal/README.rst
-
1account_bank_statement_import_paypal/__init__.py
-
18account_bank_statement_import_paypal/__manifest__.py
-
1account_bank_statement_import_paypal/models/__init__.py
-
281account_bank_statement_import_paypal/models/account_bank_statement_import_paypal.py
-
12account_bank_statement_import_paypal/readme/CONFIGURE.rst
-
5account_bank_statement_import_paypal/readme/CONTRIBUTORS.rst
-
1account_bank_statement_import_paypal/readme/DESCRIPTION.rst
-
8account_bank_statement_import_paypal/readme/USAGE.rst
-
BINaccount_bank_statement_import_paypal/static/description/icon.png
-
BINaccount_bank_statement_import_paypal/static/description/paypal_backoffice.png
@ -0,0 +1,105 @@ |
|||||
|
============================= |
||||
|
Import Paypal Bank Statements |
||||
|
============================= |
||||
|
|
||||
|
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
!! This file is generated by oca-gen-addon-readme !! |
||||
|
!! changes will be overwritten. !! |
||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
|
||||
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png |
||||
|
:target: https://odoo-community.org/page/development-status |
||||
|
:alt: Beta |
||||
|
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fbank--statement--import-lightgray.png?logo=github |
||||
|
:target: https://github.com/OCA/bank-statement-import/tree/11.0/account_bank_statement_import_paypal |
||||
|
:alt: OCA/bank-statement-import |
||||
|
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png |
||||
|
:target: https://translation.odoo-community.org/projects/bank-statement-import-11-0/bank-statement-import-11-0-account_bank_statement_import_paypal |
||||
|
:alt: Translate me on Weblate |
||||
|
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png |
||||
|
:target: https://runbot.odoo-community.org/runbot/174/11.0 |
||||
|
:alt: Try me on Runbot |
||||
|
|
||||
|
|badge1| |badge2| |badge3| |badge4| |badge5| |
||||
|
|
||||
|
This module allows you to import the Paypal CSV files in Odoo as bank statements. |
||||
|
|
||||
|
**Table of contents** |
||||
|
|
||||
|
.. contents:: |
||||
|
:local: |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
|
||||
|
In the menu Accounting > Configuration > Accounting > Bank Accounts, |
||||
|
make sure that you have your Paypal bank account with the following parameters: |
||||
|
* Bank Account Type: Normal Bank Account |
||||
|
* Account Number: the email address associated with your Paypal account |
||||
|
* Account Journal: the journal associated to your Paypal account |
||||
|
|
||||
|
TIPS |
||||
|
---- |
||||
|
For now only French and English report are supported. |
||||
|
For adding new support you just need to add your header in |
||||
|
model/account_bank_statement_import_paypal.py in the variables HEADERS. |
||||
|
Please help us and do a PR for adding new header ! Thanks |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
To use this module, you need to: |
||||
|
|
||||
|
#. Go to Paypal and download your Bank Statement |
||||
|
|
||||
|
.. image:: account_bank_statement_import_paypal/static/description/paypal_backoffice.png |
||||
|
:alt: . |
||||
|
.. image:: static/description/paypal_backoffice.png |
||||
|
:alt: . |
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/bank-statement-import/issues>`_. |
||||
|
In case of trouble, please check there if your issue has already been reported. |
||||
|
If you spotted it first, help us smashing it by providing a detailed and welcomed |
||||
|
`feedback <https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import_paypal%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
||||
|
|
||||
|
Do not contact contributors directly about support or help with technical issues. |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Authors |
||||
|
------- |
||||
|
|
||||
|
* Akretion |
||||
|
|
||||
|
Contributors |
||||
|
~~~~~~~~~~~~ |
||||
|
|
||||
|
* Alexis de Lattre <alexis.delattre@akretion.com> |
||||
|
* Sebastien BEAU <sebastien.beau@akretion.com> |
||||
|
* Tecnativa (https://www.tecnativa.com) |
||||
|
|
||||
|
* Vicent Cubells <vicent.cubells@tecnativa.com> |
||||
|
|
||||
|
Maintainers |
||||
|
~~~~~~~~~~~ |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use. |
||||
|
|
||||
|
This module is part of the `OCA/bank-statement-import <https://github.com/OCA/bank-statement-import/tree/11.0/account_bank_statement_import_paypal>`_ project on GitHub. |
||||
|
|
||||
|
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
@ -0,0 +1 @@ |
|||||
|
from . import models |
@ -0,0 +1,18 @@ |
|||||
|
# Copyright 2014-2017 Akretion (http://www.akretion.com). |
||||
|
# @author Alexis de Lattre <alexis.delattre@akretion.com> |
||||
|
# @author Sébastien BEAU <sebastien.beau@akretion.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
{ |
||||
|
"name": "Import Paypal Bank Statements", |
||||
|
'summary': 'Import Paypal CSV files as Bank Statements in Odoo', |
||||
|
"version": "11.0.1.0.0", |
||||
|
"category": "Accounting", |
||||
|
"website": "https://github.com/OCA/bank-statement-import", |
||||
|
"author": " Akretion, Odoo Community Association (OCA)", |
||||
|
"license": "AGPL-3", |
||||
|
"application": False, |
||||
|
"installable": True, |
||||
|
"depends": [ |
||||
|
"account_bank_statement_import", |
||||
|
], |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
from . import account_bank_statement_import_paypal |
@ -0,0 +1,281 @@ |
|||||
|
# Copyright 2014-2017 Akretion (http://www.akretion.com). |
||||
|
# @author Alexis de Lattre <alexis.delattre@akretion.com> |
||||
|
# @author Sébastien BEAU <sebastien.beau@akretion.com> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
import logging |
||||
|
from datetime import datetime |
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import UserError |
||||
|
import re |
||||
|
from io import StringIO |
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
try: |
||||
|
import csv |
||||
|
except (ImportError, IOError) as err: |
||||
|
_logger.debug(err) |
||||
|
|
||||
|
# Paypal header depend of the country the order are the same but the |
||||
|
# value are translated. You can add you header here |
||||
|
|
||||
|
HEADERS = [ |
||||
|
# French |
||||
|
'"Date","Heure","Fuseau horaire","Description","Devise","Avant commission"' |
||||
|
',"Commission","Net","Solde","Numéro de transaction","Adresse email de ' |
||||
|
'l\'expéditeur","Nom","Nom de la banque","Compte bancaire","Montant des ' |
||||
|
'frais de livraison et de traitement","TVA","Identifiant de facture",' |
||||
|
'"Numéro de la transaction de référence"', |
||||
|
# English |
||||
|
'"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"', |
||||
|
] |
||||
|
|
||||
|
|
||||
|
class AccountBankStatementImport(models.TransientModel): |
||||
|
_inherit = 'account.bank.statement.import' |
||||
|
|
||||
|
@api.model |
||||
|
def _get_paypal_encoding(self): |
||||
|
return 'utf-8-sig' |
||||
|
|
||||
|
@api.model |
||||
|
def _get_paypal_str_data(self, data_file): |
||||
|
if not isinstance(data_file, str): |
||||
|
data_file = data_file.decode(self._get_paypal_encoding()) |
||||
|
return data_file.strip() |
||||
|
|
||||
|
@api.model |
||||
|
def _get_paypal_date_format(self): |
||||
|
""" This method is designed to be inherited """ |
||||
|
return '%d/%m/%Y' |
||||
|
|
||||
|
@api.model |
||||
|
def _paypal_convert_amount(self, amount_str): |
||||
|
""" This method is designed to be inherited """ |
||||
|
valstr = re.sub(r'[^\d,.-]', '', amount_str) |
||||
|
valstrdot = valstr.replace('.', '') |
||||
|
valstrdot = valstrdot.replace(',', '.') |
||||
|
return float(valstrdot) |
||||
|
|
||||
|
@api.model |
||||
|
def _check_paypal(self, data_file): |
||||
|
data_file = self._get_paypal_str_data(data_file) |
||||
|
for header in HEADERS: |
||||
|
if data_file.strip().startswith(header): |
||||
|
return True |
||||
|
return False |
||||
|
|
||||
|
def _convert_paypal_line_to_dict(self, idx, line): |
||||
|
date_dt = datetime.strptime(line[0], self._get_paypal_date_format()) |
||||
|
rline = { |
||||
|
'date': fields.Date.to_string(date_dt), |
||||
|
'time': line[1], |
||||
|
'description': line[3], |
||||
|
'currency': line[4], |
||||
|
'amount': line[5], |
||||
|
'commission': line[6], |
||||
|
'balance': line[8], |
||||
|
'transaction_id': line[9], |
||||
|
'email': line[10], |
||||
|
'partner_name': line[11], |
||||
|
# This two field are useful for bank transfer |
||||
|
'bank_name': line[12], |
||||
|
'bank_account': line[13], |
||||
|
'invoice_number': line[16], |
||||
|
'origin_transaction_id': line[17], |
||||
|
'idx': idx, |
||||
|
} |
||||
|
for field in ['commission', 'amount', 'balance']: |
||||
|
_logger.debug('Trying to convert %s to float' % rline[field]) |
||||
|
try: |
||||
|
rline[field] = self._paypal_convert_amount(rline[field]) |
||||
|
except Exception: |
||||
|
raise UserError( |
||||
|
_("Value '%s' for the field '%s' on line %d, " |
||||
|
"cannot be converted to float") |
||||
|
% (rline[field], field, idx)) |
||||
|
return rline |
||||
|
|
||||
|
def _parse_paypal_file(self, data_file): |
||||
|
data_file = self._get_paypal_str_data(data_file) |
||||
|
f = StringIO(data_file) |
||||
|
f.seek(0) |
||||
|
raw_lines = [] |
||||
|
reader = csv.reader(f) |
||||
|
next(reader) # Drop header |
||||
|
for idx, line in enumerate(reader): |
||||
|
_logger.debug("Line %d: %s" % (idx, line)) |
||||
|
raw_lines.append(self._convert_paypal_line_to_dict(idx, line)) |
||||
|
return raw_lines |
||||
|
|
||||
|
def _prepare_paypal_currency_vals(self, cline): |
||||
|
currencies = self.env['res.currency'].search( |
||||
|
[('name', '=', cline['currency'])]) |
||||
|
if not currencies: |
||||
|
raise UserError( |
||||
|
_('currency %s on line %d cannot be found in odoo') |
||||
|
% (cline['currency'], cline['idx'])) |
||||
|
return { |
||||
|
'amount_currency': cline['amount'], |
||||
|
'currency_id': currencies.id, |
||||
|
'currency': cline['currency'], |
||||
|
'partner_name': cline['partner_name'], |
||||
|
'description': cline['description'], |
||||
|
'email': cline['email'], |
||||
|
'transaction_id': cline['transaction_id'], |
||||
|
} |
||||
|
|
||||
|
def _post_process_statement_line(self, raw_lines): |
||||
|
journal_id = self.env.context.get('journal_id') |
||||
|
if not journal_id: |
||||
|
raise UserError(_('You must run this wizard from the journal')) |
||||
|
journal = self.env['account.journal'].browse(journal_id) |
||||
|
currency = journal.currency_id or journal.company_id.currency_id |
||||
|
currency_change_lines = {} |
||||
|
real_transactions = [] |
||||
|
for line in raw_lines: |
||||
|
if line['currency'] != currency.name: |
||||
|
currency_change_lines[line['transaction_id']] = line |
||||
|
else: |
||||
|
real_transactions.append(line) |
||||
|
|
||||
|
for line in real_transactions: |
||||
|
# Check if the current transaction is linked with a |
||||
|
# transaction of currency change if yes merge the transaction |
||||
|
# as for odoo it's only one line |
||||
|
cline = currency_change_lines.get(line['origin_transaction_id']) |
||||
|
if cline: |
||||
|
# we update the current line with currency information |
||||
|
vals = self._prepare_paypal_currency_vals(cline) |
||||
|
line.update(vals) |
||||
|
return real_transactions |
||||
|
|
||||
|
def _prepare_paypal_statement_line(self, fline): |
||||
|
if fline['bank_name']: |
||||
|
name = '|'.join([ |
||||
|
fline['description'], |
||||
|
fline['bank_name'], |
||||
|
fline['bank_account'] |
||||
|
]) |
||||
|
else: |
||||
|
name = '|'.join([ |
||||
|
fline['description'], |
||||
|
fline['partner_name'], |
||||
|
fline['email'], |
||||
|
fline['invoice_number'], |
||||
|
]) |
||||
|
return { |
||||
|
'date': fline['date'], |
||||
|
'name': name, |
||||
|
'ref': fline['transaction_id'], |
||||
|
'unique_import_id': |
||||
|
fline['transaction_id'] + fline['date'] + fline['time'], |
||||
|
'amount': fline['amount'], |
||||
|
'bank_account_id': False, |
||||
|
'currency_id': fline.get('currency_id'), |
||||
|
'amount_currency': fline.get('amount_currency'), |
||||
|
} |
||||
|
|
||||
|
def _prepare_paypal_statement(self, lines): |
||||
|
return { |
||||
|
'name': |
||||
|
_('PayPal Import %s > %s') |
||||
|
% (lines[0]['date'], lines[-1]['date']), |
||||
|
'date': lines[-1]['date'], |
||||
|
'balance_start': |
||||
|
lines[0]['balance'] - |
||||
|
lines[0]['amount'] - |
||||
|
lines[0]['commission'], |
||||
|
'balance_end_real': lines[-1]['balance'], |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def _parse_file(self, data_file): |
||||
|
""" Import a file in Paypal CSV format """ |
||||
|
paypal = self._check_paypal(data_file) |
||||
|
if not paypal: |
||||
|
return super(AccountBankStatementImport, self)._parse_file( |
||||
|
data_file) |
||||
|
|
||||
|
raw_lines = self._parse_paypal_file(data_file) |
||||
|
final_lines = self._post_process_statement_line(raw_lines) |
||||
|
|
||||
|
vals_bank_statement = self._prepare_paypal_statement(final_lines) |
||||
|
|
||||
|
transactions = [] |
||||
|
commission_total = 0 |
||||
|
for fline in final_lines: |
||||
|
commission_total += fline['commission'] |
||||
|
vals_line = self._prepare_paypal_statement_line(fline) |
||||
|
_logger.debug("vals_line = %s" % vals_line) |
||||
|
transactions.append(vals_line) |
||||
|
|
||||
|
if commission_total: |
||||
|
commission_line = { |
||||
|
'date': vals_bank_statement['date'], |
||||
|
'name': _('Paypal commissions'), |
||||
|
'ref': _('PAYPAL-COSTS'), |
||||
|
'amount': commission_total, |
||||
|
'unique_import_id': False, |
||||
|
} |
||||
|
transactions.append(commission_line) |
||||
|
|
||||
|
vals_bank_statement['transactions'] = transactions |
||||
|
return None, None, [vals_bank_statement] |
||||
|
|
||||
|
@api.model |
||||
|
def _get_paypal_partner(self, description, partner_name, |
||||
|
partner_email, invoice_number): |
||||
|
if invoice_number: |
||||
|
# In most case e-commerce case invoice_number |
||||
|
# will contain the sale order number |
||||
|
sale = self.env['sale.order'].search([ |
||||
|
('name', '=', invoice_number)]) |
||||
|
if sale and len(sale) == 1: |
||||
|
return sale.partner_id.commercial_partner_id |
||||
|
|
||||
|
invoice = self.env['account.invoice'].search([ |
||||
|
('number', '=', invoice_number)]) |
||||
|
if invoice and len(invoice) == 1: |
||||
|
return invoice.partner_id.commercial_partner_id |
||||
|
|
||||
|
if partner_email: |
||||
|
partner = self.env['res.partner'].search([ |
||||
|
('email', '=', partner_email), |
||||
|
('parent_id', '=', False)]) |
||||
|
if partner and len(partner) == 1: |
||||
|
return partner.commercial_partner_id |
||||
|
|
||||
|
if partner_name: |
||||
|
partner = self.env['res.partner'].search([ |
||||
|
('name', '=ilike', partner_name)]) |
||||
|
if partner and len(partner) == 1: |
||||
|
return partner.commercial_partner_id |
||||
|
return None |
||||
|
|
||||
|
@api.model |
||||
|
def _complete_paypal_statement_line(self, line): |
||||
|
_logger.debug('Process line %s', line['name']) |
||||
|
info = line['name'].split('|') |
||||
|
if len(info) == 4: |
||||
|
partner = self._get_paypal_partner(*info) |
||||
|
if partner: |
||||
|
return { |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': partner.property_account_receivable.id, |
||||
|
} |
||||
|
return None |
||||
|
|
||||
|
@api.model |
||||
|
def _complete_statement(self, stmts_vals, journal_id, account_number): |
||||
|
""" Match the partner from paypal information """ |
||||
|
stmts_vals = super(AccountBankStatementImport, self).\ |
||||
|
_complete_statement(stmts_vals, journal_id, account_number) |
||||
|
for line in stmts_vals['transactions']: |
||||
|
vals = self._complete_paypal_statement_line(line) |
||||
|
if vals: |
||||
|
line.update(vals) |
||||
|
return stmts_vals |
@ -0,0 +1,12 @@ |
|||||
|
In the menu Accounting > Configuration > Accounting > Bank Accounts, |
||||
|
make sure that you have your Paypal bank account with the following parameters: |
||||
|
* Bank Account Type: Normal Bank Account |
||||
|
* Account Number: the email address associated with your Paypal account |
||||
|
* Account Journal: the journal associated to your Paypal account |
||||
|
|
||||
|
TIPS |
||||
|
---- |
||||
|
For now only French and English report are supported. |
||||
|
For adding new support you just need to add your header in |
||||
|
model/account_bank_statement_import_paypal.py in the variables HEADERS. |
||||
|
Please help us and do a PR for adding new header ! Thanks |
@ -0,0 +1,5 @@ |
|||||
|
* Alexis de Lattre <alexis.delattre@akretion.com> |
||||
|
* Sebastien BEAU <sebastien.beau@akretion.com> |
||||
|
* Tecnativa (https://www.tecnativa.com) |
||||
|
|
||||
|
* Vicent Cubells <vicent.cubells@tecnativa.com> |
@ -0,0 +1 @@ |
|||||
|
This module allows you to import the Paypal CSV files in Odoo as bank statements. |
@ -0,0 +1,8 @@ |
|||||
|
To use this module, you need to: |
||||
|
|
||||
|
#. Go to Paypal and download your Bank Statement |
||||
|
|
||||
|
.. image:: account_bank_statement_import_paypal/static/description/paypal_backoffice.png |
||||
|
:alt: . |
||||
|
.. image:: static/description/paypal_backoffice.png |
||||
|
:alt: . |
After Width: 180 | Height: 180 | Size: 6.3 KiB |
After Width: 1194 | Height: 932 | Size: 95 KiB |
Write
Preview
Loading…
Cancel
Save
Reference in new issue