[mrg] upstream

This commit is contained in:
Leonardo Pistone
2014-03-07 13:44:26 +01:00
24 changed files with 716 additions and 76 deletions

View File

@@ -25,7 +25,7 @@ Advanced reconciliation method for the module account_easy_reconcile
Reconcile rules with transaction_ref
""",
'version': '1.0',
'version': '1.0.1',
'author': 'Camptocamp',
'category': 'Finance',
'website': 'http://www.camptocamp.com',

View File

@@ -30,7 +30,7 @@ class AccountMoveLine(Model):
'transaction_ref': fields.char('Transaction Ref.', size=128),
}
class AccountBankSatement(Model):
class AccountBankStatement(Model):
"""
Inherit account.bank.statement class in order to set transaction_ref info on account.move.line
"""
@@ -43,7 +43,7 @@ class AccountBankSatement(Model):
if context is None:
context = {}
res = super(AccountBankSatement, self)._prepare_move_line_vals(
res = super(AccountBankStatement, self)._prepare_move_line_vals(
cr, uid, st_line, move_id, debit, credit,
currency_id=currency_id,
amount_currency=amount_currency,

View File

@@ -20,7 +20,7 @@
#
{'name': "Bank statement completion from bank account number",
'version': '1.0',
'version': '1.0.1',
'author': 'ACSONE SA/NV',
'maintainer': 'ACSONE SA/NV',
'category': 'Finance',
@@ -29,21 +29,20 @@
'account_statement_base_completion',
],
'description': """
Add a completion method based on the partner bank account number provided by the bank/office.
Add a completion method based on the partner bank account number
provided by the bank/office.
Completion will look in the partner with that bank account number to match the partner,
then it will fill in the bank statement line with it to ease the reconciliation.
Completion will look in the partner with that bank account number
to match the partner, then it will fill in the bank statement line
with it to ease the reconciliation.
""",
'website': 'http://www.acsone.eu',
'init_xml': [],
'update_xml': [
'data': [
"data.xml",
],
'demo_xml': [],
'test': [],
'demo': [],
'installable': True,
'images': [],
'auto_install': True,
'auto_install': False,
'license': 'AGPL-3',
}

View File

@@ -3,7 +3,7 @@
<data noupdate="1">
<record id="bank_statement_completion_rule_10" model="account.statement.completion.rule">
<field name="name">Match from bank account number (Nomal or IBAN))</field>
<field name="name">Match from bank account number (Normal or IBAN))</field>
<field name="sequence">10</field>
<field name="function_to_call">get_from_bank_account</field>
</record>

View File

@@ -19,5 +19,5 @@
#
##############################################################################
import statement
import partner
from . import partner
from . import statement

View File

@@ -20,7 +20,7 @@
##############################################################################
{'name': "Bank statement base completion",
'version': '1.0',
'version': '1.0.1',
'author': 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Finance',

View File

@@ -319,9 +319,12 @@ class AccountStatementCompletionRule(orm.Model):
if not context['partner_memoizer']:
return res
st_obj = self.pool.get('account.bank.statement.line')
sql = "SELECT id FROM res_partner WHERE name ~* %s and id in %s"
pattern = ".*%s.*" % re.escape(st_line['name'])
cr.execute(sql, (pattern, context['partner_memoizer']))
# regexp_replace(name,'([^a-zA-Z0-9 -])', '\\\1', 'g'), 'i') escape the column name to avoid false positive. (ex 'jho..doe' -> 'joh\.\.doe'
sql = """SELECT id FROM (
SELECT id, regexp_matches(%s, regexp_replace(name,'([^[:alpha:]0-9 -])', %s, 'g'), 'i') AS name_match FROM res_partner
WHERE id IN %s) AS res_patner_matcher
WHERE name_match IS NOT NULL"""
cr.execute(sql, (st_line['name'], r"\\\1", context['partner_memoizer']))
result = cr.fetchall()
if not result:
return res
@@ -332,7 +335,7 @@ class AccountStatementCompletionRule(orm.Model):
res['partner_id'] = result[0][0]
st_vals = st_obj.get_values_for_line(cr,
uid,
profile_id=st_line['porfile_id'],
profile_id=st_line['profile_id'],
master_account_id=st_line['master_account_id'],
partner_id=res['partner_id'],
line_type=False,
@@ -469,7 +472,7 @@ class AccountStatementLine(orm.Model):
sql_err.pgerror)
class AccountBankSatement(orm.Model):
class AccountBankStatement(orm.Model):
"""
We add a basic button and stuff to support the auto-completion
of the bank statement once line have been imported or manually fullfill.

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Laurent Mignon
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# 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 . import test_base_completion
checks = [
test_base_completion
]

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
#
#
# Authors: Laurent Mignon
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# All Rights Reserved
#
# 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 openerp.tests import common
import time
from collections import namedtuple
name_completion_case = namedtuple("name_completion_case", ["partner_name", "line_label", "should_match"])
NAMES_COMPLETION_CASES = [
name_completion_case("Acsone", "Line for Acsone SA", True),
name_completion_case("Acsone", "Line for Acsone", True),
name_completion_case("Acsone", "Acsone for line", True),
name_completion_case("acsone", "Acsone for line", True),
name_completion_case("Acsone SA", "Line for Acsone SA test", True),
name_completion_case("Ac..ne", "Acsone for line", False),
name_completion_case("é@|r{}", "Acsone é@|r{} for line", True),
name_completion_case("Acsone", "A..one for line", False),
name_completion_case("A.one SA", "A.one SA for line", True),
name_completion_case("Acsone SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", False),
name_completion_case("Acsone ([^a-zA-Z0-9 -]) SA", "Line for Acsone ([^a-zA-Z0-9 -]) SA test", True),
]
class base_completion(common.TransactionCase):
def setUp(self):
super(base_completion, self).setUp()
self.company_a = self.browse_ref('base.main_company')
self.profile_obj = self.registry("account.statement.profile")
self.partner_obj = self.registry("res.partner")
self.account_bank_statement_obj = self.registry("account.bank.statement")
self.account_bank_statement_line_obj = self.registry("account.bank.statement.line")
self.journal_id = self.ref("account.bank_journal")
self.partner_id = self.ref('base.main_partner')
self.account_id = self.ref("account.a_recv")
self.partner_id = self.ref("base.res_partner_12")
def test_name_completion(self):
"""Test complete partner_id from statement line label
Test the automatic completion of the partner_id based if the name of the partner appears in
the statement line label
"""
self.completion_rule_id = self.ref('account_statement_base_completion.bank_statement_completion_rule_3')
# Create the profile
self.profile_id = self.profile_obj.create(self.cr, self.uid, {
"name": "TEST",
"commission_account_id": self.account_id,
"journal_id": self.journal_id,
"rule_ids": [(6, 0, [self.completion_rule_id])]})
# Create a bank statement
self.statement_id = self.account_bank_statement_obj.create(self.cr, self.uid, {
"balance_end_real": 0.0,
"balance_start": 0.0,
"date": time.strftime('%Y-%m-%d'),
"journal_id": self.journal_id,
"profile_id": self.profile_id
})
for case in NAMES_COMPLETION_CASES:
self.partner_obj.write(self.cr, self.uid, self.partner_id, {'name': case.partner_name})
statement_line_id = self.account_bank_statement_line_obj.create(self.cr, self.uid, {
'amount': 1000.0,
'name': case.line_label,
'ref': 'My ref',
'statement_id': self.statement_id,
})
statement_line = self.account_bank_statement_line_obj.browse(self.cr, self.uid, statement_line_id)
self.assertFalse(statement_line.partner_id, "Partner_id must be blank before completion")
statement_obj = self.account_bank_statement_obj.browse(self.cr, self.uid, self.statement_id)
statement_obj.button_auto_completion()
statement_line = self.account_bank_statement_line_obj.browse(self.cr, self.uid, statement_line_id)
if case.should_match:
self.assertEquals(self.partner_id, statement_line.partner_id['id'],
"Missing expected partner id after completion (partner_name: %s, line_name: %s)" % (case.partner_name, case.line_label))
else:
self.assertNotEquals(self.partner_id, statement_line.partner_id['id'],
"Partner id should be empty after completion(partner_name: %s, line_name: %s)" % (case.partner_name, case.line_label))

View File

@@ -20,7 +20,7 @@
##############################################################################
{'name': "Bank statement base import",
'version': '1.0',
'version': '1.1.0',
'author': 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Finance',

View File

@@ -35,24 +35,24 @@ def float_or_zero(val):
class FileParser(BankStatementImportParser):
"""
Generic abstract class for defining parser for .csv or .xls file format.
Generic abstract class for defining parser for .csv, .xls or .xlsx file format.
"""
def __init__(self, parse_name, ftype='csv', extra_fields=None, header=None, **kwargs):
"""
:param char: parse_name: The name of the parser
:param char: ftype: extension of the file (could be csv or xls)
:param char: ftype: extension of the file (could be csv, xls or xlsx)
:param dict: extra_fields: extra fields to add to the conversion dict. In the format
{fieldname: fieldtype}
:param list: header : specify header fields if the csv file has no header
"""
super(FileParser, self).__init__(parse_name, **kwargs)
if ftype in ('csv', 'xls'):
self.ftype = ftype
if ftype in ('csv', 'xls' ,'xlsx'):
self.ftype = ftype[0:3]
else:
raise except_osv(_('User Error'),
_('Invalid file type %s. Please use csv or xls') % ftype)
_('Invalid file type %s. Please use csv, xls or xlsx') % ftype)
self.conversion_dict = {
'ref': unicode,
'label': unicode,
@@ -81,7 +81,7 @@ class FileParser(BankStatementImportParser):
def _parse(self, *args, **kwargs):
"""
Launch the parsing through .csv or .xls depending on the
Launch the parsing through .csv, .xls or .xlsx depending on the
given ftype
"""
@@ -128,7 +128,7 @@ class FileParser(BankStatementImportParser):
def _parse_xls(self):
"""
:return: dict of dict from xls file (line/rows)
:return: dict of dict from xls/xlsx file (line/rows)
"""
wb_file = tempfile.NamedTemporaryFile()
wb_file.write(self.filebuffer)
@@ -180,7 +180,7 @@ class FileParser(BankStatementImportParser):
def _from_xls(self, result_set, conversion_rules):
"""
Handle the converstion from the dict and handle date format from
an .xls file.
an .csv, .xls or .xlsx file.
"""
for line in result_set:
for rule in conversion_rules:

View File

@@ -20,12 +20,13 @@
##############################################################################
import base64
import csv
from datetime import datetime
def UnicodeDictReader(utf8_data, **kwargs):
sniffer = csv.Sniffer()
pos = utf8_data.tell()
sample_data = utf8_data.read(1024)
sample_data = utf8_data.read(2048)
utf8_data.seek(pos)
dialect = sniffer.sniff(sample_data, delimiters=',;\t')
csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs)
@@ -121,10 +122,10 @@ class BankStatementImportParser(object):
:return: dict of vals that represent additional infos for the statement
"""
return {
'name': self.statement_name,
'name': self.statement_name or '/',
'balance_start': self.balance_start,
'balance_end_real': self.balance_end,
'date': self.statement_date
'date': self.statement_date or datetime.now()
}
def get_st_line_vals(self, line, *args, **kwargs):

View File

@@ -26,17 +26,19 @@ import datetime
from openerp.osv.orm import Model
from openerp.osv import fields, osv
from parser import new_bank_statement_parser
from openerp.tools.config import config
class AccountStatementProfil(Model):
_inherit = "account.statement.profile"
def get_import_type_selection(self, cr, uid, context=None):
"""
Has to be inherited to add parser
"""
"""This is the method to be inherited for adding the parser"""
return [('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')]
def _get_import_type_selection(self, cr, uid, context=None):
return self.get_import_type_selection(cr, uid, context=context)
_columns = {
'launch_import_completion': fields.boolean(
"Launch completion after import",
@@ -46,14 +48,17 @@ class AccountStatementProfil(Model):
# we remove deprecated as it floods logs in standard/warning level sob...
'rec_log': fields.text('log', readonly=True), # Deprecated
'import_type': fields.selection(
get_import_type_selection,
_get_import_type_selection,
'Type of import',
required=True,
help="Choose here the method by which you want to import bank"
"statement for this profile."),
}
_defaults = {
'import_type': 'generic_csvxls_so'
}
def _write_extra_statement_lines(
self, cr, uid, parser, result_row_list, profile, statement_id, context):
"""Insert extra lines after the main statement lines.
@@ -85,7 +90,11 @@ class AccountStatementProfil(Model):
context=context)
return True
def prepare_statetement_lines_vals(
#Deprecated remove on V8
def prepare_statetement_lines_vals(self, *args, **kwargs):
return self.prepare_statement_lines_vals(*args, **kwargs)
def prepare_statement_lines_vals(
self, cr, uid, parser_vals, account_payable, account_receivable,
statement_id, context):
"""
@@ -183,7 +192,7 @@ class AccountStatementProfil(Model):
statement_store = []
for line in result_row_list:
parser_vals = parser.get_st_line_vals(line)
values = self.prepare_statetement_lines_vals(
values = self.prepare_statement_lines_vals(
cr, uid, parser_vals, account_payable, account_receivable, statement_id,
context)
statement_store.append(values)
@@ -218,10 +227,14 @@ class AccountStatementProfil(Model):
context)
except Exception:
statement_obj.unlink(cr, uid, [statement_id], context=context)
error_type, error_value, trbk = sys.exc_info()
st = "Error: %s\nDescription: %s\nTraceback:" % (error_type.__name__, error_value)
st += ''.join(traceback.format_tb(trbk, 30))
#TODO we should catch correctly the exception with a python
#Exception and only re-catch some special exception.
#For now we avoid re-catching error in debug mode
if config['debug_mode']:
raise
raise osv.except_osv(_("Statement import error"),
_("The statement cannot be created: %s") % st)
return statement_id

View File

@@ -20,7 +20,7 @@
##############################################################################
{'name': "Bank statement extension and profiles",
'version': '1.3.0',
'version': '1.3.3',
'author': 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Finance',

View File

@@ -31,9 +31,10 @@ def fixed_write(self, cr, uid, ids, vals, context=None):
I will do it when I have time."""
res = super(stat_mod.account_bank_statement, self).write(cr, uid, ids,
vals, context=context)
cr.execute("UPDATE account_bank_statement_line"
" SET sequence = account_bank_statement_line.id + 1"
" where statement_id in %s", (tuple(ids),))
if ids: # will be false for an new empty bank statement
cr.execute("UPDATE account_bank_statement_line"
" SET sequence = account_bank_statement_line.id + 1"
" where statement_id in %s", (tuple(ids),))
return res
stat_mod.account_bank_statement.write = fixed_write
@@ -118,7 +119,7 @@ class AccountStatementProfile(Model):
class AccountBankSatement(Model):
class AccountBankStatement(Model):
"""
We improve the bank statement class mostly for :
- Removing the period and compute it from the date of each line.
@@ -207,7 +208,8 @@ class AccountBankSatement(Model):
profile_obj = self.pool.get('account.statement.profile')
profile = profile_obj.browse(cr, uid, vals['profile_id'], context=context)
vals['journal_id'] = profile.journal_id.id
return super(AccountBankSatement, self).create(cr, uid, vals, context=context)
return super(AccountBankStatement, self
).create(cr, uid, vals, context=context)
def _get_period(self, cr, uid, date, context=None):
"""Return matching period for a date."""
@@ -255,8 +257,9 @@ class AccountBankSatement(Model):
"""
if context is None:
context = {}
res = super(AccountBankSatement, self)._prepare_move(
cr, uid, st_line, st_line_number, context=context)
res = super(AccountBankStatement, self
)._prepare_move(cr, uid, st_line, st_line_number,
context=context)
ctx = context.copy()
ctx['company_id'] = st_line.company_id.id
period_id = self._get_period(cr, uid, st_line.date, context=ctx)
@@ -285,7 +288,7 @@ class AccountBankSatement(Model):
"""
if context is None:
context = {}
res = super(AccountBankSatement, self)._prepare_move_line_vals(
res = super(AccountBankStatement, self)._prepare_move_line_vals(
cr, uid, st_line, move_id, debit, credit,
currency_id=currency_id,
amount_currency=amount_currency,
@@ -309,10 +312,9 @@ class AccountBankSatement(Model):
create the move from.
:return: int/long of the res.partner to use as counterpart
"""
bank_partner_id = super(AccountBankSatement, self)._get_counter_part_partner(cr,
uid,
st_line,
context=context)
bank_partner_id = super(AccountBankStatement, self
)._get_counter_part_partner(cr, uid, st_line,
context=context)
# get the right partner according to the chosen profile
if st_line.statement_id.profile_id.force_partner_on_bank:
bank_partner_id = st_line.statement_id.profile_id.partner_id.id
@@ -542,8 +544,9 @@ class AccountBankSatement(Model):
"""
st = self.browse(cr, uid, st_id, context=context)
if st.balance_check:
return super(AccountBankSatement, self).balance_check(
cr, uid, st_id, journal_type, context=context)
return super(AccountBankStatement, self
).balance_check(cr, uid, st_id, journal_type,
context=context)
else:
return True
@@ -563,7 +566,7 @@ class AccountBankSatement(Model):
'balance_check': import_config.balance_check}}
class AccountBankSatementLine(Model):
class AccountBankStatementLine(Model):
"""
Override to compute the period from the date of the line, add a method to retrieve
the values for a line from the profile. Override the on_change method to take care of
@@ -658,6 +661,11 @@ class AccountBankSatementLine(Model):
# This can be quite a performance killer as we read ir.properity fields
if partner_id:
part = obj_partner.browse(cr, uid, partner_id, context=context)
part = part.commercial_partner_id
# When the method is called from bank statement completion,
# ensure that the line's partner is a commercial
# (accounting) entity
res['partner_id'] = part.id
pay_account = part.property_account_payable.id
receiv_account = part.property_account_receivable.id
# If no value, look on the default company property
@@ -693,11 +701,9 @@ class AccountBankSatementLine(Model):
Keep the same features as in standard and call super. If an account is returned,
call the method to compute line values.
"""
res = super(AccountBankSatementLine, self).onchange_type(cr, uid,
line_id,
partner_id,
line_type,
context=context)
res = super(AccountBankStatementLine, self
).onchange_type(cr, uid, line_id, partner_id,
line_type, context=context)
if 'account_id' in res['value']:
result = self.get_values_for_line(cr, uid,
profile_id=profile_id,

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexandre Fayolle
# Copyright 2013 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 . import point_of_sale

View File

@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Nicolas Bessi, Joel Grand-Guillaume
# Copyright 2011-2013 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 extension and profiles for Point of Sale",
'version': '1.0.0',
'author': 'Camptocamp',
'maintainer': 'Camptocamp',
'category': 'Point Of Sale',
'complexity': 'normal',
'depends': ['point_of_sale',
'account_statement_ext',
],
'description': """
Update the point of sale code to work with improved bank statements.
""",
'website': 'http://www.camptocamp.com',
'data': [],
'demo': [],
'test': [],
'installable': True,
'images': [],
'auto_install': True,
'license': 'AGPL-3',
'active': False,
}

View File

@@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexandre Fayolle
# Copyright 2013 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 openerp.addons.point_of_sale.point_of_sale import pos_session as std_pos_session
from openerp.osv import orm, osv
from openerp.tools.translate import _
if not hasattr(std_pos_session, '_prepare_bank_statement'):
# monkey patch to fix lp:1245375
#
# We replace pos_session.create with the implementation in
# mp_create below which is essentially the same, only with a call
# to self._prepare_bank_statement.
#
# The default implementation has been extracted in
# mp_prepare_bank_statement below, and can be overridden in models
# which _inherit pos.session
#
# This change has been proposed for merging to fix lp:125375
def mp_prepare_bank_statement(self, cr, uid, pos_config, journal, context=None):
bank_values = {
'journal_id' : journal.id,
'user_id' : uid,
'company_id' : pos_config.shop_id.company_id.id
}
return bank_values
def mp_create(self, cr, uid, values, context=None):
context = context or {}
config_id = values.get('config_id', False) or context.get('default_config_id', False)
if not config_id:
raise osv.except_osv( _('Error!'),
_("You should assign a Point of Sale to your session."))
# journal_id is not required on the pos_config because it does not
# exists at the installation. If nothing is configured at the
# installation we do the minimal configuration. Impossible to do in
# the .xml files as the CoA is not yet installed.
jobj = self.pool.get('pos.config')
pos_config = jobj.browse(cr, uid, config_id, context=context)
context.update({'company_id': pos_config.shop_id.company_id.id})
if not pos_config.journal_id:
jid = jobj.default_get(cr, uid, ['journal_id'], context=context)['journal_id']
if jid:
jobj.write(cr, uid, [pos_config.id], {'journal_id': jid}, context=context)
else:
raise osv.except_osv( _('error!'),
_("Unable to open the session. You have to assign a sale journal to your point of sale."))
# define some cash journal if no payment method exists
if not pos_config.journal_ids:
journal_proxy = self.pool.get('account.journal')
cashids = journal_proxy.search(cr, uid, [('journal_user', '=', True), ('type','=','cash')], context=context)
if not cashids:
cashids = journal_proxy.search(cr, uid, [('type', '=', 'cash')], context=context)
if not cashids:
cashids = journal_proxy.search(cr, uid, [('journal_user','=',True)], context=context)
jobj.write(cr, uid, [pos_config.id], {'journal_ids': [(6,0, cashids)]})
pos_config = jobj.browse(cr, uid, config_id, context=context)
bank_statement_ids = []
for journal in pos_config.journal_ids:
bank_values = self._prepare_bank_statement(cr, uid, pos_config, journal, context)
statement_id = self.pool.get('account.bank.statement').create(cr, uid, bank_values, context=context)
bank_statement_ids.append(statement_id)
values.update({
'name' : pos_config.sequence_id._next(),
'statement_ids' : [(6, 0, bank_statement_ids)],
'config_id': config_id
})
return super(std_pos_session, self).create(cr, uid, values, context=context)
std_pos_session._prepare_bank_statement = mp_prepare_bank_statement
std_pos_session.create = mp_create
class pos_session(orm.Model):
_inherit = 'pos.session'
def _prepare_bank_statement(self, cr, uid, pos_config, journal, context=None):
""" Override the function _mp_create. To add the bank profile to the statement
Function That was previously added to pos.session model using monkey patching
"""
bank_values = super(pos_session, self)._prepare_bank_statement(cr, uid,
pos_config,
journal, context)
user_obj = self.pool.get('res.users')
profile_obj = self.pool.get('account.statement.profile')
user = user_obj.browse(cr, uid, uid, context=context)
defaults = self.pool['account.bank.statement'].default_get(cr, uid,
['profile_id', 'period_id'],
context=context)
profile_ids = profile_obj.search(cr, uid,
[('company_id', '=', user.company_id.id),
('journal_id', '=', bank_values['journal_id'])],
context=context)
if profile_ids:
defaults['profile_id'] = profile_ids[0]
bank_values.update(defaults)
return bank_values

View File

@@ -33,14 +33,3 @@ class AccountStatementProfil(orm.Model):
context=context)
selection.append(('ofx_so', _('OFX - Open Financial Exchange')))
return selection
_columns = {
'import_type': fields.selection(
get_import_type_selection,
'Type of import',
required=True,
help="Choose here the method by which you want to import bank"
"statement for this profile."),
}

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# account_statement_one_move for OpenERP
# Copyright (C) 2013-TODAY Akretion <http://www.akretion.com>.
# @author Sébastien BEAU <sebastien.beau@akretion.com>
#
# 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 . import statement

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# account_statement_one_move for OpenERP
# Copyright (C) 2013-TODAY Akretion <http://www.akretion.com>.
# @author Sébastien BEAU <sebastien.beau@akretion.com>
#
# 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 one move',
'version': '0.1',
'category': 'Generic Modules/Others',
'license': 'AGPL-3',
'description': """
This module allows to group all lines of a bank statement in only one move.
This feature is optional and can be activated with a checkbox in the bank
statement's profile. This is very useful for credit card deposit for
example, you won't have a move for each line.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com/',
'depends': ['account_statement_ext'],
'data': [
'statement_view.xml'
],
'demo': [],
'installable': True,
'auto_install': False,
'active': False,
}

View File

@@ -0,0 +1,225 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# account_statement_one_move for OpenERP
# Copyright (C) 2013-TODAY Akretion <http://www.akretion.com>.
# @author Sébastien BEAU <sebastien.beau@akretion.com>
#
# 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 openerp.osv import fields, orm, osv
class AccountStatementProfile(orm.Model):
_inherit = "account.statement.profile"
_columns = {
'one_move': fields.boolean(
'Group Journal Items',
help="Only one Journal Entry will be generated on the "
"validation of the bank statement."),
'split_transfer_line': fields.boolean(
'Split Transfer Line',
help="Two transfer lines will be automatically generated : one "
"for the refunds and one for the payments.")
}
class account_bank_statement(orm.Model):
_inherit = "account.bank.statement"
def _prepare_move_line_vals(self, cr, uid, st_line, *args, **kwargs):
res = super(account_bank_statement, self)._prepare_move_line_vals(cr, uid, st_line,
*args, **kwargs)
period_id = self._get_period(cr, uid, st_line.statement_id.date,
context=kwargs.get('context'))
if st_line.statement_id.profile_id.one_move:
res.update({
'period_id': period_id,
'date': st_line.statement_id.date,
'name': st_line.ref,
})
return res
return res
def _prepare_move(self, cr, uid, st_line, st_line_number, context=None):
res = super(account_bank_statement, self).\
_prepare_move(cr, uid, st_line, st_line_number, context=context)
res.update({
'ref': st_line.statement_id.name,
'name': st_line.statement_id.name,
'date': st_line.statement_id.date,
})
return res
def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id,
st_line_number, context=None):
if context is None:
context = {}
context['from_parent_object'] = True #For compability with module account_constraints
account_move_obj = self.pool.get('account.move')
account_bank_statement_line_obj = self.pool.get('account.bank.statement.line')
st_line = account_bank_statement_line_obj.browse(cr, uid, st_line_id,
context=context)
st = st_line.statement_id
if st.profile_id.one_move:
if not context.get('move_id'):
move_vals = self._prepare_move(cr, uid, st_line, st_line_number, context=context)
context['move_id'] = account_move_obj.create(cr, uid, move_vals, context=context)
self.create_move_line_from_st_line(cr, uid, context['move_id'],
st_line_id, company_currency_id,
context=context)
return context['move_id']
else:
return super(account_bank_statement, self).create_move_from_st_line(cr, uid, st_line_id,
company_currency_id,
st_line_number,
context=context)
def create_move_line_from_st_line(self, cr, uid, move_id, st_line_id,
company_currency_id, context=None):
"""Create the account move line from the statement line.
:param int/long move_id: ID of the account.move
:param int/long st_line_id: ID of the account.bank.statement.line to create the move line from.
:param int/long company_currency_id: ID of the res.currency of the company
:return: ID of the account.move created
"""
if context is None:
context = {}
res_currency_obj = self.pool.get('res.currency')
account_move_line_obj = self.pool.get('account.move.line')
account_bank_statement_line_obj = self.pool.get('account.bank.statement.line')
st_line = account_bank_statement_line_obj.browse(cr, uid, st_line_id, context=context)
st = st_line.statement_id
context.update({'date': st_line.date})
acc_cur = ((st_line.amount<=0) and st.journal_id.default_debit_account_id) or st_line.account_id
context.update({
'res.currency.compute.account': acc_cur,
})
amount = res_currency_obj.compute(cr, uid, st.currency.id,
company_currency_id,
st_line.amount,
context=context)
bank_move_vals = self._prepare_bank_move_line(cr, uid, st_line, move_id, amount,
company_currency_id, context=context)
return account_move_line_obj.create(cr, uid, bank_move_vals, context=context)
def _valid_move(self, cr, uid, move_id, context=None):
move_obj = self.pool.get('account.move')
move = move_obj.browse(cr, uid, move_id, context=context)
move_obj.post(cr, uid, [move_id], context=context)
return True
def _prepare_transfer_move_line_vals(self, cr, uid, st, name, amount, move_id, context=None):
"""
Prepare the dict of values to create the transfer move lines.
"""
account_id = st.profile_id.journal_id.default_debit_account_id.id
partner_id = st.profile_id.partner_id and profile.partner_id.id or False
if amount < 0.0:
debit = 0.0
credit = -amount
else:
debit = amount
credit = 0.0
vals = {
'name': name,
'date': st.date,
'partner_id': partner_id,
'statement_id': st.id,
'account_id': account_id,
'ref': name,
'move_id': move_id,
'credit': credit,
'debit': debit,
'journal_id': st.journal_id.id,
'period_id': st.period_id.id,
}
return vals
def create_move_transfer_lines(self, cr, uid, move, st, context=None):
move_line_obj = self.pool.get('account.move.line')
move_id = move.id
refund = 0.0
payment = 0.0
transfer_lines = []
transfer_line_ids = []
#Calculate the part of the refund amount and the payment amount
for move_line in move.line_id:
refund -= move_line.debit
payment += move_line.credit
#Create 2 Transfer lines or One global tranfer line
if st.profile_id.split_transfer_line:
if refund:
transfer_lines.append(['Refund Transfer', refund])
if payment:
transfer_lines.append(['Payment Transfer', payment])
else:
amount = payment + refund
if amount:
transfer_lines.append(['Transfer', amount])
for transfer_line in transfer_lines:
vals = self._prepare_transfer_move_line_vals(cr, uid, st,
transfer_line[0],
transfer_line[1],
move_id,
context=context)
transfer_line_ids.append(move_line_obj.create(cr, uid, vals, context=context))
return transfer_line_ids
def button_confirm_bank(self, cr, uid, ids, context=None):
st_line_obj = self.pool.get('account.bank.statement.line')
move_obj = self.pool.get('account.move')
if context is None:
context = {}
for st in self.browse(cr, uid, ids, context=context):
super(account_bank_statement, self).button_confirm_bank(cr, uid, ids,
context=context)
if st.profile_id.one_move and context.get('move_id', False):
move_id = context['move_id']
move = move_obj.browse(cr, uid, move_id, context=context)
transfe_line_ids = self.create_move_transfer_lines(cr, uid, move, st, context=context)
self._valid_move(cr, uid, move_id, context=context)
lines_ids = [x.id for x in st.line_ids]
st_line_obj.write(cr, uid, lines_ids,
{'move_ids': [(4, move_id, False)]},
context=context)
return True
def button_cancel(self, cr, uid, ids, context=None):
done = []
for st in self.browse(cr, uid, ids, context=context):
if st.profile_id.one_move and st.line_ids:
for move in st.line_ids[0].move_ids:
if move.state != 'draft':
move.button_cancel(context=context)
move.unlink(context=context)
st.write({'state':'draft'}, context=context)
else:
super(account_bank_statement, self).button_cancel(cr, uid, ids,
context=context)
return True

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
account_statement_one_move for OpenERP
Copyright (C) 2013-TODAY Akretion <http://www.akretion.com>.
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<!-- INHERITED VIEW FOR THE OBJECT : account_statement -->
<record id="account_statement_view_form" model="ir.ui.view">
<field name="name">account_statement_one_move.account_statement.view_form</field>
<field name="model">account.statement.profile</field>
<field name="inherit_id" ref="account_statement_ext.statement_importer_view_form" />
<field name="arch" type="xml">
<field name="balance_check" position="after">
<field name="one_move"/>
<field name="split_transfer_line" attrs="{'invisible': [('one_move', '=', False)]}"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-10 05:56+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-03-01 05:55+0000\n"
"X-Generator: Launchpad (build 16948)\n"
#. module: account_statement_regex_account_completion
#: field:account.statement.completion.rule,regex:0