mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[FIX] Various fixes after presentation to F.Clementi
(lp:c2c-financial-addons/6.1 rev 24.1.23)
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
1) Match from statement line label (based on partner field 'Bank Statement Label')
|
||||
2) Match from statement line label (based on partner name)
|
||||
3) Match from statement line reference (based on SO number)
|
||||
3) Match from statement line reference (based on Invoice number)
|
||||
|
||||
It add as well a label on the bank statement line (on which the pre-define rules can match) and
|
||||
a char field on the partner called 'Bank Statement Label'. Using the pre-define rules, you'll be
|
||||
|
||||
@@ -58,7 +58,6 @@ class AccountStatementProfil(Model):
|
||||
...
|
||||
}
|
||||
"""
|
||||
|
||||
if not context:
|
||||
context={}
|
||||
res = {}
|
||||
@@ -111,7 +110,7 @@ class AccountStatementCompletionRule(Model):
|
||||
If more than one partner matched, raise an error.
|
||||
Return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line.
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
@@ -122,6 +121,7 @@ class AccountStatementCompletionRule(Model):
|
||||
if st_line:
|
||||
inv_obj = self.pool.get('account.invoice')
|
||||
inv_id = inv_obj.search(cursor, uid, [('number', '=', st_line.ref)])
|
||||
if inv_id:
|
||||
if inv_id and len(inv_id) == 1:
|
||||
inv = inv_obj.browse(cursor, uid, inv_id[0])
|
||||
res['partner_id'] = inv.partner_id.id
|
||||
@@ -138,7 +138,7 @@ class AccountStatementCompletionRule(Model):
|
||||
If more than one partner matched, raise an error.
|
||||
Return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line.
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
@@ -149,6 +149,7 @@ class AccountStatementCompletionRule(Model):
|
||||
if st_line:
|
||||
so_obj = self.pool.get('sale.order')
|
||||
so_id = so_obj.search(cursor, uid, [('name', '=', st_line.ref)])
|
||||
if so_id:
|
||||
if so_id and len(so_id) == 1:
|
||||
so = so_obj.browse(cursor, uid, so_id[0])
|
||||
res['partner_id'] = so.partner_id.id
|
||||
@@ -168,7 +169,7 @@ class AccountStatementCompletionRule(Model):
|
||||
If more than one partner matched, raise an error.
|
||||
Return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line.
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
@@ -187,6 +188,7 @@ class AccountStatementCompletionRule(Model):
|
||||
res['partner_id'] = partner.id
|
||||
if compt > 1:
|
||||
raise ErrorTooManyPartner(_('Line named "%s" was matched by more than one partner.')%(st_line.name,st_line.id))
|
||||
if res:
|
||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
||||
res.update(st_vals)
|
||||
@@ -198,7 +200,7 @@ class AccountStatementCompletionRule(Model):
|
||||
Then, call the generic st_line method to complete other values.
|
||||
Return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line.
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
|
||||
@@ -215,6 +217,7 @@ class AccountStatementCompletionRule(Model):
|
||||
raise ErrorTooManyPartner(_('Line named "%s" was matched by more than one partner.')%(st_line.name,st_line.id))
|
||||
for id in result:
|
||||
res['partner_id'] = id
|
||||
if res:
|
||||
st_vals = st_obj.get_values_for_line(cursor, uid, profile_id = st_line.statement_id.profile_id.id,
|
||||
partner_id = res.get('partner_id',False), line_type = st_line.type, amount = st_line.amount, context = context)
|
||||
res.update(st_vals)
|
||||
@@ -252,13 +255,19 @@ class AccountStatementLine(Model):
|
||||
We ignore line for which already_completed is ticked!
|
||||
"""
|
||||
profile_obj = self.pool.get('account.statement.profil')
|
||||
st_obj = self.pool.get('account.bank.statement.line')
|
||||
res={}
|
||||
errors_stack = []
|
||||
for line in self.browse(cr,uid, ids, context):
|
||||
if not line.already_completed:
|
||||
try:
|
||||
# Take the default values
|
||||
res[line.id] = st_obj.get_values_for_line(cr, uid, profile_id = line.statement_id.profile_id.id,
|
||||
line_type = line.type, amount = line.amount, context = context)
|
||||
# Ask the rule
|
||||
vals = profile_obj.find_values_from_rules(cr, uid, line.statement_id.profile_id.id, line.id, context)
|
||||
res[line.id]=vals
|
||||
# Merge the result
|
||||
res[line.id].update(vals)
|
||||
except ErrorTooManyPartner, exc:
|
||||
msg = "Line ID %s had following error: %s" % (line.id, str(exc))
|
||||
errors_stack.append(msg)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/tree/field[@name='sequence']" position="before">
|
||||
<field name="already_completed" />
|
||||
</xpath>
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='ref']" position="after">
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='sequence']" position="after">
|
||||
<separator colspan="4" string="Importation related infos"/>
|
||||
<field name="label" />
|
||||
<field name="already_completed" />
|
||||
</xpath>
|
||||
@@ -23,7 +24,7 @@
|
||||
</xpath>
|
||||
|
||||
<xpath expr="/form/group/field[@name='balance_end']" position="after">
|
||||
<button name="button_auto_completion" string="Auto Completion" type="object" colspan="1"/>
|
||||
<button name="button_auto_completion" string="Auto Completion" states='draft,open' type="object" colspan="1"/>
|
||||
</xpath>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -33,7 +33,7 @@ except:
|
||||
|
||||
class FileParser(BankStatementImportParser):
|
||||
"""Abstract clall for that help to build a specific parser for all
|
||||
.csv and .xls files"""
|
||||
.csv and .xls files."""
|
||||
|
||||
def __init__(self, parse_name, keys_to_validate={}, ftype='csv', convertion_dict=None, *args, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -55,7 +55,42 @@ class GenericFileParser(FileParser):
|
||||
def parser_for(cls, parser_name):
|
||||
return parser_name == 'generic_csvxls_so'
|
||||
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
"""This method must return a dict of vals that can be passed to create
|
||||
method of statement line in order to record it. It is the responsibility
|
||||
of every parser to give this dict of vals, so each one can implement his
|
||||
own way of recording the lines.
|
||||
:param: line: a dict of vals that represent a line of result_row_list
|
||||
:return: dict of values to give to the create method of statement line,
|
||||
it MUST contain at least:
|
||||
{
|
||||
'name':value,
|
||||
'date':value,
|
||||
'amount':value,
|
||||
'ref':value,
|
||||
'label':value,
|
||||
'commission_amount':value,
|
||||
}
|
||||
In this generic parser, the commission is given for every line, so we store it
|
||||
for each one.
|
||||
"""
|
||||
return {
|
||||
'name': line.get('label', line.get('ref','/')),
|
||||
'date': line.get('date', datetime.datetime.now().date()),
|
||||
'amount': line.get('amount', 0.0),
|
||||
'ref': line.get('ref','/'),
|
||||
'label': line.get('label',''),
|
||||
'commission_amount': line.get('commission_amount', 0.0),
|
||||
}
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
"""Compute the commission from value of each line"""
|
||||
res = super(GenericFileParser, self)._post(*args, **kwargs)
|
||||
val = 0.0
|
||||
for row in self.result_row_list:
|
||||
val += row.get('commission_amount',0.0)
|
||||
self.commission_global_amount = val
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ class BankStatementImportParser(object):
|
||||
def __init__(self, parser_name, *args, **kwargs):
|
||||
# The name of the parser as it will be called
|
||||
self.parser_name = parser_name
|
||||
# The result as a list of row
|
||||
# The result as a list of row. One row per line of data in the file, but
|
||||
# not the commission one !
|
||||
self.result_row_list = None
|
||||
# The file buffer on which to work on
|
||||
self.filebuffer = None
|
||||
@@ -84,6 +85,32 @@ class BankStatementImportParser(object):
|
||||
amount in the self.commission_global_amount one."""
|
||||
return NotImplementedError
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
"""This method must return a dict of vals that can be passed to create
|
||||
method of statement line in order to record it. It is the responsibility
|
||||
of every parser to give this dict of vals, so each one can implement his
|
||||
own way of recording the lines.
|
||||
:param: line: a dict of vals that represent a line of result_row_list
|
||||
:return: dict of values to give to the create method of statement line,
|
||||
it MUST contain at least:
|
||||
{
|
||||
'name':value,
|
||||
'date':value,
|
||||
'amount':value,
|
||||
'ref':value,
|
||||
}
|
||||
"""
|
||||
return NotImplementedError
|
||||
|
||||
def get_st_line_commision(self, *args, **kwargs):
|
||||
"""This is called by the importation method to create the commission line in
|
||||
the bank statement. We will always create one line for the commission in the
|
||||
bank statement, but it could be computated from a value of each line, or given
|
||||
in a single line for the whole file.
|
||||
return: float of the whole commission
|
||||
"""
|
||||
return self.commission_global_amount
|
||||
|
||||
def parse(self, filebuffer, *args, **kwargs):
|
||||
"""This will be the method that will be called by wizard, button and so
|
||||
to parse a filebuffer by calling successively all the private method
|
||||
|
||||
@@ -67,23 +67,22 @@ class AccountStatementProfil(Model):
|
||||
"Bank Statement ID %s have been imported with %s lines "%(statement_id, num_lines))
|
||||
return True
|
||||
|
||||
def create_global_commission_line(self, cr, uid, commission_global_amount,
|
||||
def prepare_global_commission_line_vals(self, cr, uid, parser,
|
||||
result_row_list, profile, statement_id, context):
|
||||
"""Create the global commission line if there is one. The global commission is computed by
|
||||
"""Prepare the global commission line if there is one. The global commission is computed by
|
||||
summing the commission column of each row. Feel free to override the methode to compute
|
||||
your own commission line from the result_row_list.
|
||||
:params: cr: The DB Cursor
|
||||
:params: uid: int/long ID of the current user in the system
|
||||
:params: commission_global_amount: float
|
||||
:params: result_row_list: [{'key':value}]
|
||||
:params: profile: browserecord of account.statement.profile
|
||||
:params: statement_id : int/long of the current importing statement ID
|
||||
:params: context: global context
|
||||
return: an ID of the statement line that represent the global commission
|
||||
for the statement.
|
||||
:param: cr: The DB Cursor
|
||||
:param: uid: int/long ID of the current user in the system
|
||||
:param: browse_record of the current parser
|
||||
:param: result_row_list: [{'key':value}]
|
||||
:param: profile: browserecord of account.statement.profile
|
||||
:param: statement_id : int/long of the current importing statement ID
|
||||
:param: context: global context
|
||||
return: dict of vals that will be passed to create method of statement line.
|
||||
"""
|
||||
res = False
|
||||
if commission_global_amount:
|
||||
comm_values = False
|
||||
if parser.get_st_line_commision():
|
||||
partner_id = profile.partner_id and profile.partner_id.id or False
|
||||
commission_account_id = profile.commission_account_id and profile.commission_account_id.id or False
|
||||
commission_analytic_id = profile.commission_analytic_id and profile.commission_analytic_id.id or False
|
||||
@@ -91,7 +90,7 @@ class AccountStatementProfil(Model):
|
||||
comm_values = {
|
||||
'name': 'IN '+ _('Commission line'),
|
||||
'date': datetime.datetime.now().date(),
|
||||
'amount': commission_global_amount,
|
||||
'amount': parser.get_st_line_commision(),
|
||||
'partner_id': partner_id,
|
||||
'type': 'general',
|
||||
'statement_id': statement_id,
|
||||
@@ -101,30 +100,20 @@ class AccountStatementProfil(Model):
|
||||
# !! We set the already_completed so auto-completion will not update those values !
|
||||
'already_completed': True,
|
||||
}
|
||||
res = statement_line_obj.create(cr, uid,
|
||||
comm_values,
|
||||
context=context)
|
||||
return res
|
||||
return comm_values
|
||||
|
||||
def prepare_statetement_lines_vals(self, cursor, uid, parser_line,
|
||||
def prepare_statetement_lines_vals(self, cursor, uid, parser_vals,
|
||||
account_payable, account_receivable, statement_id, context):
|
||||
"""Hook to change the values of a line. Overide it to compute or change
|
||||
the account or any other values (e.g. if a line is the global commission)"""
|
||||
values = {
|
||||
'name': parser_line.get('label', parser_line.get('ref','/')),
|
||||
'date': parser_line.get('date', datetime.datetime.now().date()),
|
||||
'amount': parser_line['amount'],
|
||||
'ref': parser_line['ref'],
|
||||
'type': 'customer',
|
||||
'statement_id': statement_id,
|
||||
'label': parser_line.get('label',''),
|
||||
'commission_amount': parser_line.get('commission_amount', 0.0),
|
||||
#'account_id': journal.default_debit_account_id
|
||||
}
|
||||
"""Hook to build the values of a line from the parser returned values. At
|
||||
least it fullfill the statement_id and account_id. Overide it to add your
|
||||
own completion if needed. """
|
||||
statement_obj = self.pool.get('account.bank.statement')
|
||||
values = parser_vals
|
||||
values['statement_id']= statement_id
|
||||
values['account_id'] = statement_obj.get_account_for_counterpart(
|
||||
cursor,
|
||||
uid,
|
||||
parser_line['amount'],
|
||||
parser_vals['amount'],
|
||||
account_receivable,
|
||||
account_payable
|
||||
)
|
||||
@@ -134,6 +123,7 @@ class AccountStatementProfil(Model):
|
||||
"""Create a bank statement with the given profile and parser. It will fullfill the bank statement
|
||||
with the values of the file providen, but will not complete data (like finding the partner, or
|
||||
the right account). This will be done in a second step with the completion rules.
|
||||
It will also create the commission line if it apply.
|
||||
"""
|
||||
context = context or {}
|
||||
statement_obj = self.pool.get('account.bank.statement')
|
||||
@@ -158,20 +148,19 @@ class AccountStatementProfil(Model):
|
||||
|
||||
statement_id = statement_obj.create(cursor,uid,{'profile_id':prof.id,},context)
|
||||
account_receivable, account_payable = statement_obj.get_default_pay_receiv_accounts(cursor, uid, context)
|
||||
commission_global_amount = 0.0
|
||||
try:
|
||||
# Record every line in the bank statement and compute the global commission
|
||||
# based on the commission_amount column
|
||||
for line in result_row_list:
|
||||
commission_global_amount += line.get('commission_amount', 0.0)
|
||||
values = self.prepare_statetement_lines_vals(cursor, uid, line, account_payable,
|
||||
parser_vals = parser.get_st_line_vals(line)
|
||||
values = self.prepare_statetement_lines_vals(cursor, uid, parser_vals, account_payable,
|
||||
account_receivable, statement_id, context)
|
||||
# we finally create the line in system
|
||||
statement_line_obj.create(cursor, uid, values, context=context)
|
||||
|
||||
# we create commission line
|
||||
self.create_global_commission_line(cursor, uid, commission_global_amount,
|
||||
result_row_list, prof, statement_id, context)
|
||||
# Build and create the global commission line for the whole statement
|
||||
comm_vals = self.prepare_global_commission_line_vals(cursor, uid, parser, result_row_list, prof, statement_id, context)
|
||||
if comm_vals:
|
||||
res = statement_line_obj.create(cursor, uid, comm_vals,context=context)
|
||||
|
||||
attachment_obj.create(
|
||||
cursor,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='ref']" position="after">
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='label']" position="after">
|
||||
<field name="commission_amount" />
|
||||
</xpath>
|
||||
</data>
|
||||
|
||||
@@ -32,19 +32,19 @@ class CreditPartnerStatementImporter(osv.osv_memory):
|
||||
|
||||
_name = "credit.statement.import"
|
||||
|
||||
def _get_profile(self, cr, uid, context=None):
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None: context = {}
|
||||
res = False
|
||||
res = {}
|
||||
if (context.get('active_model', False) == 'account.statement.profil' and
|
||||
context.get('active_ids', False)):
|
||||
res = context['active_ids']
|
||||
if len(res) > 1:
|
||||
raise Exception (_('You cannot use this on more than one profile !'))
|
||||
return res[0]
|
||||
ids = context['active_ids']
|
||||
assert len(ids) == 1, 'You cannot use this on more than one profile !'
|
||||
res['profile_id'] = ids[0]
|
||||
other_vals = self.onchange_profile_id(cr, uid, [], res['profile_id'], context=context)
|
||||
res.update(other_vals.get('value',{}))
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
|
||||
'profile_id': fields.many2one('account.statement.profil',
|
||||
'Import configuration parameter',
|
||||
required=True),
|
||||
@@ -73,12 +73,14 @@ class CreditPartnerStatementImporter(osv.osv_memory):
|
||||
help="Tic that box if you want OpenERP to control the start/end balance\
|
||||
before confirming a bank statement. If don't ticked, no balance control will be done."
|
||||
),
|
||||
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'profile_id': _get_profile,
|
||||
}
|
||||
|
||||
|
||||
# _defaults = _get_default_values
|
||||
# {
|
||||
# 'profile_id': _get_profile,
|
||||
# }
|
||||
|
||||
def onchange_profile_id(self, cr, uid, ids, profile_id, context=None):
|
||||
res={}
|
||||
@@ -117,13 +119,6 @@ class CreditPartnerStatementImporter(osv.osv_memory):
|
||||
ftype.replace('.',''),
|
||||
context=context
|
||||
)
|
||||
# obj_data = self.pool.get('ir.model.data')
|
||||
# act_obj = self.pool.get('ir.actions.act_window')
|
||||
# result = obj_data.get_object_reference(cursor, uid, 'account_statement_import', 'action_treasury_statement_tree')
|
||||
#
|
||||
# id = result and result[1] or False
|
||||
# result = act_obj.read(cursor, uid, [id], context=context)[0]
|
||||
# result['domain'] = str([('id','in',[sid])])
|
||||
|
||||
# We should return here the profile for which we executed the import
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Import statement">
|
||||
<group colspan="4" >
|
||||
<field name="profile_id" />
|
||||
<field name="profile_id" on_change="onchange_profile_id(profile_id)"/>
|
||||
<field name="input_statement" filename="file_name" colspan="2"/>
|
||||
<field name="file_name" colspan="2" invisible="1"/>
|
||||
<separator string="Import Parameters Summary" colspan="4"/>
|
||||
@@ -38,7 +38,7 @@
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="statement_importer_menu" name="Import Treasury Statement" action="statement_importer_action" parent="account.menu_finance_periodical_processing"/>
|
||||
<menuitem id="statement_importer_menu" name="Import Bank Statement" action="statement_importer_action" parent="account.menu_finance_bank_and_cash"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
So this way, the reconciliation always happend on the SO name stored in ref.
|
||||
|
||||
|
||||
""",
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'init_xml': [],
|
||||
|
||||
@@ -47,7 +47,7 @@ class AccountStatementCompletionRule(Model):
|
||||
In that case, we always fullfill the reference of the line with the SO name.
|
||||
Return:
|
||||
A dict of value that can be passed directly to the write method of
|
||||
the statement line.
|
||||
the statement line or {}
|
||||
{'partner_id': value,
|
||||
'account_id' : value,
|
||||
...}
|
||||
@@ -64,6 +64,7 @@ class AccountStatementCompletionRule(Model):
|
||||
res['ref'] = so.name
|
||||
elif so_id and len(so_id) > 1:
|
||||
raise Exception(_('Line named "%s" was matched by more than one partner.')%(st_line.name,st_line.id))
|
||||
if so_id:
|
||||
st_vals = st_obj.get_values_for_line(cr, uid, profile_id = st_line.statement_id.profile_id.id,
|
||||
partner_id = res.get('partner_id',False), line_type = st_line.type, st_line.amount, context)
|
||||
res.update(st_vals)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='ref']" position="after">
|
||||
<xpath expr="/form/notebook/page/field[@name='line_ids']/form/field[@name='label']" position="after">
|
||||
<field name="transaction_id" />
|
||||
</xpath>
|
||||
</data>
|
||||
|
||||
21
account_statement_transactionid_import/__init__.py
Normal file
21
account_statement_transactionid_import/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
import parser
|
||||
60
account_statement_transactionid_import/__openerp__.py
Normal file
60
account_statement_transactionid_import/__openerp__.py
Normal file
@@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Joel Grand-Guillaume
|
||||
# Copyright 2011-2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{'name': "Bank statement transactionID import",
|
||||
'version': '1.0',
|
||||
'author': 'Camptocamp',
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
'complexity': 'normal', #easy, normal, expert
|
||||
'depends': ['account_statement_base_import','account_statement_transactionid_completion'],
|
||||
'description': """
|
||||
This module brings generic methods and fields on bank statement to deal with
|
||||
the importation of different bank and offices that uses transactionID.
|
||||
|
||||
This module allow you to import your bank transactions with a standard .csv or .xls file
|
||||
(you'll find it in the 'datas' folder). It'll respect the profil
|
||||
you'll choose (providen by the accouhnt_statement_ext module) to generate the entries.
|
||||
|
||||
This module can handle a commission taken by the payment office and has the following format:
|
||||
|
||||
* transactionID : the transaction ID given by the bank/office. It'll be used as reference
|
||||
in the generated entries and will be useful for reconciliation process
|
||||
* date : date of the payment
|
||||
* amount : amount paid in the currency of the journal used in the importation profil
|
||||
* commission_amount : amount of the comission for each line
|
||||
* label : the comunication given by the payment office, used as communication in the
|
||||
generated entries.
|
||||
|
||||
|
||||
""",
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'init_xml': [],
|
||||
'update_xml': [
|
||||
],
|
||||
'demo_xml': [],
|
||||
'test': [],
|
||||
'installable': True,
|
||||
'images': [],
|
||||
'auto_install': False,
|
||||
'license': 'AGPL-3',
|
||||
'active': False,
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
"transaction_id";"date";"amount";"commission_amount";"label"
|
||||
50969286;2011-03-07 13:45:14;118.4;-11.84;"label a"
|
||||
51065326;2011-03-05 13:45:14;189;-15.12;"label b"
|
||||
51179306;2011-03-02 17:45:14;189;-15.12;"label c"
|
||||
|
BIN
account_statement_transactionid_import/datas/statement.xls
Normal file
BIN
account_statement_transactionid_import/datas/statement.xls
Normal file
Binary file not shown.
24
account_statement_transactionid_import/parser/__init__.py
Normal file
24
account_statement_transactionid_import/parser/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2011-2012 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# from parser import new_bank_statement_parser
|
||||
# from parser import BankStatementImportParser
|
||||
import transactionid_file_parser
|
||||
@@ -0,0 +1,97 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright Camptocamp SA
|
||||
# Author Joel Grand-Guillaume
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
import base64
|
||||
import csv
|
||||
import tempfile
|
||||
import datetime
|
||||
from account_statement_base_import.parser.file_parser import FileParser
|
||||
|
||||
try:
|
||||
import xlrd
|
||||
except:
|
||||
raise Exception(_('Please install python lib xlrd'))
|
||||
|
||||
class TransactionIDFileParser(FileParser):
|
||||
"""TransactionID parser that use a define format in csv or xls to import
|
||||
bank statement."""
|
||||
|
||||
|
||||
|
||||
def __init__(self, parse_name, ftype='csv'):
|
||||
convertion_dict = {
|
||||
'transaction_id': unicode,
|
||||
'label': unicode,
|
||||
'date': datetime.datetime,
|
||||
'amount': float,
|
||||
'commission_amount': float
|
||||
}
|
||||
# Order of cols does not matter but first row of the file has to be header
|
||||
keys_to_validate = ['transaction_id', 'label', 'date', 'amount', 'commission_amount']
|
||||
|
||||
|
||||
super(TransactionIDFileParser,self).__init__(parse_name, keys_to_validate=keys_to_validate, ftype=ftype, convertion_dict=convertion_dict)
|
||||
|
||||
@classmethod
|
||||
def parser_for(cls, parser_name):
|
||||
return parser_name == 'generic_csvxls_transaction'
|
||||
|
||||
def get_st_line_vals(self, line, *args, **kwargs):
|
||||
"""This method must return a dict of vals that can be passed to create
|
||||
method of statement line in order to record it. It is the responsibility
|
||||
of every parser to give this dict of vals, so each one can implement his
|
||||
own way of recording the lines.
|
||||
:param: line: a dict of vals that represent a line of result_row_list
|
||||
:return: dict of values to give to the create method of statement line,
|
||||
it MUST contain at least:
|
||||
{
|
||||
'name':value,
|
||||
'date':value,
|
||||
'amount':value,
|
||||
'ref':value,
|
||||
'label':value,
|
||||
'commission_amount':value,
|
||||
}
|
||||
In this generic parser, the commission is given for every line, so we store it
|
||||
for each one.
|
||||
"""
|
||||
return {
|
||||
'name': line.get('label', line.get('ref','/')),
|
||||
'date': line.get('date', datetime.datetime.now().date()),
|
||||
'amount': line.get('amount', 0.0),
|
||||
'ref': line.get('transaction_id','/'),
|
||||
'label': line.get('label',''),
|
||||
'transaction_id': line.get('transaction_id','/'),
|
||||
'commission_amount': line.get('commission_amount', 0.0),
|
||||
}
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
"""Compute the commission from value of each line"""
|
||||
res = super(GenericFileParser, self)._post(*args, **kwargs)
|
||||
val = 0.0
|
||||
for row in self.result_row_list:
|
||||
val += row.get('commission_amount',0.0)
|
||||
self.commission_global_amount = val
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user