diff --git a/account_statement_ext/__init__.py b/account_statement_ext/__init__.py
new file mode 100644
index 00000000..a8ce7c24
--- /dev/null
+++ b/account_statement_ext/__init__.py
@@ -0,0 +1,22 @@
+# -*- 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 .
+#
+##############################################################################
+
+import statement
diff --git a/account_statement_ext/__openerp__.py b/account_statement_ext/__openerp__.py
new file mode 100644
index 00000000..7056f184
--- /dev/null
+++ b/account_statement_ext/__openerp__.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Joel Grand-Guillaume
+# Copyright 2011-2012 Camptocamp SA
+# Thanks to EduSense BV () for some part and idea
+# taken from the account_banking module
+#
+# 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 .
+#
+##############################################################################
+
+{'name': "Account Bank Statement without Period",
+ 'version': '1.0',
+ 'author': 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'Finance',
+ 'complexity': 'normal', #easy, normal, expert
+ 'depends': ['account'],
+ 'description': """
+ Remove the period on the bank statement, and compute it for each line based on their date instead.
+ If errors occurs, it will summarize them all in one popup instead of blocking all the process at every error.
+ """,
+ 'website': 'http://www.camptocamp.com',
+ 'init_xml': [],
+ 'update_xml': [
+ 'statement_view.xml',
+ ],
+ 'demo_xml': [],
+ 'test': [],
+ 'installable': True,
+ 'images': [],
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'active': False,
+}
diff --git a/account_statement_ext/statement.py b/account_statement_ext/statement.py
new file mode 100644
index 00000000..98e60936
--- /dev/null
+++ b/account_statement_ext/statement.py
@@ -0,0 +1,276 @@
+# -*- 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 .
+#
+##############################################################################
+
+from osv import fields, osv
+from tools.translate import _
+from account_statement_import.file_parser.parser import FileParser
+import datetime
+import netsvc
+logger = netsvc.Logger()
+
+
+class AccountSatement(osv.osv):
+ """Override account bank statement to remove the period on it
+ and compute it for each line."""
+
+ _inherit = "account.bank.statement"
+
+ _columns = {
+ 'period_id': fields.many2one('account.period', 'Period', required=False, readonly=True),
+ }
+
+ _defaults = {
+ 'period_id': lambda *a: False,
+ }
+
+ def _get_period(self, cursor, uid, date, context=None):
+ '''
+ Find matching period for date, used in thestatement line creation.
+ '''
+ period_obj = self.pool.get('account.period')
+ periods = period_obj.find(cursor, uid, dt=date, context=context)
+ return periods and periods[0] or False
+
+ def _check_company_id(self, cr, uid, ids, context=None):
+ """
+ Adapt this constraint method from the account module to reflect the
+ move of period_id to the statement line
+ """
+ for statement in self.browse(cr, uid, ids, context=context):
+ if (statement.period_id and
+ statement.company_id.id != statement.period_id.company_id.id):
+ return False
+ for line in statement.line_ids:
+ if (line.period_id and
+ statement.company_id.id != line.period_id.company_id.id):
+ return False
+ return True
+
+ # Redefine the constraint, or it still refer to the original method
+ _constraints = [
+ (_check_company_id, 'The journal and period chosen have to belong to the same company.', ['journal_id','period_id']),
+ ]
+
+ def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, st_line_number, context=None):
+ """Override a large portion of the code to compute the periode for each line instead of
+ taking the period of the whole statement.
+ Remove the entry posting on generated account moves."""
+ if context is None:
+ context = {}
+ res_currency_obj = self.pool.get('res.currency')
+ account_move_obj = self.pool.get('account.move')
+ 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})
+ ctx = context.copy() # Chg
+ ctx['company_id'] = st_line.company_id.id # Chg
+ period_id = self._get_period( # Chg
+ cr, uid, st_line.date, context=ctx)
+
+ move_id = account_move_obj.create(cr, uid, {
+ 'journal_id': st.journal_id.id,
+ 'period_id': period_id, # Chg
+ 'date': st_line.date,
+ 'name': st_line_number,
+ 'ref': st_line.ref,
+ }, context=context)
+ account_bank_statement_line_obj.write(cr, uid, [st_line.id], {
+ 'move_ids': [(4, move_id, False)]
+ })
+
+ torec = []
+ if st_line.amount >= 0:
+ account_id = st.journal_id.default_credit_account_id.id
+ else:
+ account_id = st.journal_id.default_debit_account_id.id
+
+ 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)
+
+ val = {
+ 'name': st_line.name,
+ 'date': st_line.date,
+ 'ref': st_line.ref,
+ 'move_id': move_id,
+ 'partner_id': ((st_line.partner_id) and st_line.partner_id.id) or False,
+ 'account_id': (st_line.account_id) and st_line.account_id.id,
+ 'credit': ((amount>0) and amount) or 0.0,
+ 'debit': ((amount<0) and -amount) or 0.0,
+ 'statement_id': st.id,
+ 'journal_id': st.journal_id.id,
+ 'period_id': period_id, #Chg
+ 'currency_id': st.currency.id,
+ 'analytic_account_id': st_line.analytic_account_id and st_line.analytic_account_id.id or False
+ }
+
+ if st.currency.id <> company_currency_id:
+ amount_cur = res_currency_obj.compute(cr, uid, company_currency_id,
+ st.currency.id, amount, context=context)
+ val['amount_currency'] = -amount_cur
+
+ if st_line.account_id and st_line.account_id.currency_id and st_line.account_id.currency_id.id <> company_currency_id:
+ val['currency_id'] = st_line.account_id.currency_id.id
+ amount_cur = res_currency_obj.compute(cr, uid, company_currency_id,
+ st_line.account_id.currency_id.id, amount, context=context)
+ val['amount_currency'] = -amount_cur
+
+ move_line_id = account_move_line_obj.create(cr, uid, val, context=context)
+ torec.append(move_line_id)
+
+ # Fill the secondary amount/currency
+ # if currency is not the same than the company
+ amount_currency = False
+ currency_id = False
+ if st.currency.id <> company_currency_id:
+ amount_currency = st_line.amount
+ currency_id = st.currency.id
+ account_move_line_obj.create(cr, uid, {
+ 'name': st_line.name,
+ 'date': st_line.date,
+ 'ref': st_line.ref,
+ 'move_id': move_id,
+ 'partner_id': ((st_line.partner_id) and st_line.partner_id.id) or False,
+ 'account_id': account_id,
+ 'credit': ((amount < 0) and -amount) or 0.0,
+ 'debit': ((amount > 0) and amount) or 0.0,
+ 'statement_id': st.id,
+ 'journal_id': st.journal_id.id,
+ 'period_id': period_id, #Chg
+ 'amount_currency': amount_currency,
+ 'currency_id': currency_id,
+ }, context=context)
+
+ for line in account_move_line_obj.browse(cr, uid, [x.id for x in
+ account_move_obj.browse(cr, uid, move_id,
+ context=context).line_id],
+ context=context):
+ if line.state <> 'valid':
+ raise osv.except_osv(_('Error !'),
+ _('Journal item "%s" is not valid.') % line.name)
+
+ # Bank statements will not consider boolean on journal entry_posted
+ account_move_obj.post(cr, uid, [move_id], context=context)
+ return move_id
+
+ def _get_st_number_period(self, cr, uid, date, journal_sequence_id):
+ """Retrieve the name of bank statement from sequence, according to the period
+ corresponding to the date passed in args"""
+ year = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, date)).fiscalyear_id.id
+ c = {'fiscalyear_id': year}
+ obj_seq = self.pool.get('ir.sequence')
+ if journal_sequence_id:
+ st_number = obj_seq.next_by_id(cr, uid, journal_sequence_id, context=c)
+ else:
+ st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=c)
+ return st_number
+
+ def button_confirm_bank(self, cr, uid, ids, context=None):
+ """Completely override the method in order to have
+ an error message which displays all the messages
+ instead of having them pop one by one.
+ We have to copy paste a big block of code, changing the error
+ stack + managing period from date."""
+ # obj_seq = self.pool.get('irerrors_stack.sequence')
+ if context is None:
+ context = {}
+ for st in self.browse(cr, uid, ids, context=context):
+
+ j_type = st.journal_id.type
+ company_currency_id = st.journal_id.company_id.currency_id.id
+ if not self.check_status_condition(cr, uid, st.state, journal_type=j_type):
+ continue
+
+ self.balance_check(cr, uid, st.id, journal_type=j_type, context=context)
+ if (not st.journal_id.default_credit_account_id) \
+ or (not st.journal_id.default_debit_account_id):
+ raise osv.except_osv(_('Configuration Error !'),
+ _('Please verify that an account is defined in the journal.'))
+
+ if not st.name == '/':
+ st_number = st.name
+ else:
+# Begin Changes
+ seq_id = st.journal_id.sequence_id and st.journal_id.sequence_id.id or False
+ st_number = self._get_st_number_period(cr, uid, st.date, seq_id)
+ # c = {'fiscalyear_id': st.period_id.fiscalyear_id.id}
+ # if st.journal_id.sequence_id:
+ # st_number = obj_seq.next_by_id(cr, uid, st.journal_id.sequence_id.id, context=c)
+ # else:
+ # st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement', context=c)
+# End Changes
+ for line in st.move_line_ids:
+ if line.state <> 'valid':
+ raise osv.except_osv(_('Error !'),
+ _('The account entries lines are not in valid state.'))
+# begin changes
+ errors_stack = []
+ for st_line in st.line_ids:
+ try:
+ if st_line.analytic_account_id:
+ if not st.journal_id.analytic_journal_id:
+ raise osv.except_osv(_('No Analytic Journal !'),
+ _("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
+ if not st_line.amount:
+ continue
+ st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context)
+ self.create_move_from_st_line(cr, uid, st_line.id, company_currency_id, st_line_number, context)
+ except osv.except_osv, exc:
+ msg = "Line ID %s with ref %s had following error: %s" % (st_line.id, st_line.ref, exc.value)
+ errors_stack.append(msg)
+ except Exception, exc:
+ msg = "Line ID %s with ref %s had following error: %s" % (st_line.id, st_line.ref, str(exc))
+ errors_stack.append(msg)
+ if errors_stack:
+ msg = u"\n".join(errors_stack)
+ raise osv.except_osv(_('Error'), msg)
+#end changes
+ self.write(cr, uid, [st.id], {
+ 'name': st_number,
+ 'balance_end_real': st.balance_end
+ }, context=context)
+ self.log(cr, uid, st.id, _('Statement %s is confirmed, journal items are created.') % (st_number,))
+ return self.write(cr, uid, ids, {'state':'confirm'}, context=context)
+
+class AccountSatementLine(osv.osv):
+ '''
+ Adds the period on line, matched on the date.
+ '''
+ _inherit = 'account.bank.statement.line'
+
+ def _get_period(self, cursor, user, context=None):
+ date = context.get('date', None)
+ periods = self.pool.get('account.period').find(cursor, user, dt=date)
+ return periods and periods[0] or False
+
+ _columns = {
+ 'period_id': fields.many2one('account.period', 'Period', required=True),
+ }
+
+ _defaults = {
+ 'period_id': _get_period,
+ }
diff --git a/account_statement_ext/statement_view.xml b/account_statement_ext/statement_view.xml
new file mode 100644
index 00000000..a66915c2
--- /dev/null
+++ b/account_statement_ext/statement_view.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+ account.bank.statement.form
+ account.bank.statement
+
+ form
+
+
+
+
+
+ account.bank.statement.tree.banking
+
+ account.bank.statement
+ tree
+
+
+
+
+
+
+ account.bank.statement.form.add_period
+
+ account.bank.statement
+ form
+
+
+
+
+
+
+
+ account.bank.statement.form.add_period2
+
+ account.bank.statement
+ form
+
+
+
+
+
+
+
+
+
+
+ account.bank.statement.line.inherit
+ account.bank.statement
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/base_transaction_id/__openerp__.py b/base_transaction_id/__openerp__.py
index bd32d912..abf49131 100644
--- a/base_transaction_id/__openerp__.py
+++ b/base_transaction_id/__openerp__.py
@@ -26,7 +26,9 @@
'category': 'Hidden/Dependency',
'complexity': 'easy', #easy, normal, expert
'depends': ['account', 'sale','stock'],
- 'description': """Adds transaction id to invoice and sale models and views""",
+ 'description': """Adds transaction id to invoice and sale models and views. This is mostely used for E-commerce handling. You
+ can then add a mapping on that SO field to save the E-Commerce financial Transaction ID into the OpenERP SO field. The main
+ purpose is to ease the reconciliation process.""",
'website': 'http://www.openerp.com',
'init_xml': [],
'update_xml': ['invoice_view.xml', 'sale_view.xml'],