diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 86166ec0125..c538614fd0f 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -63,6 +63,8 @@ for a particular financial year and for preparation of vouchers there is a modul 'wizard/account_use_model_view.xml', 'account_installer.xml', 'wizard/account_period_close_view.xml', + 'wizard/account_reconcile_view.xml', + 'wizard/account_unreconcile_view.xml', 'account_view.xml', 'account_report.xml', 'account_financial_report_data.xml', @@ -85,14 +87,12 @@ for a particular financial year and for preparation of vouchers there is a modul 'wizard/account_journal_select_view.xml', 'wizard/account_change_currency_view.xml', 'wizard/account_validate_move_view.xml', - 'wizard/account_unreconcile_view.xml', 'wizard/account_report_general_ledger_view.xml', 'wizard/account_invoice_state_view.xml', 'wizard/account_report_partner_balance_view.xml', 'wizard/account_report_account_balance_view.xml', 'wizard/account_report_aged_partner_balance_view.xml', 'wizard/account_report_partner_ledger_view.xml', - 'wizard/account_reconcile_view.xml', 'wizard/account_reconcile_partner_process_view.xml', 'wizard/account_automatic_reconcile_view.xml', 'wizard/account_financial_report_view.xml', @@ -126,6 +126,14 @@ for a particular financial year and for preparation of vouchers there is a modul 'res_config_view.xml', 'account_pre_install.yml' ], + 'js': [ + 'static/src/js/account_move_reconciliation.js', + ], + 'qweb' : [ + "static/src/xml/account_move_reconciliation.xml", + ], + 'css':['static/src/css/account_move_reconciliation.css' + ], 'demo': [ 'demo/account_demo.xml', 'project/project_demo.xml', @@ -151,6 +159,5 @@ for a particular financial year and for preparation of vouchers there is a modul ], 'installable': True, 'auto_install': False, - 'certificate': '0080331923549', } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account.py b/addons/account/account.py index d145f0308b0..c2e6f3d1221 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -601,7 +601,7 @@ class account_account(osv.osv): if not default: default = {} default = default.copy() - default['code'] = (account['code'] or '') + '(copy)' + default.update(code=_("%s (copy)") % (account['code'] or '')) if not local: done_list = [] if account.id in done_list: @@ -782,9 +782,10 @@ class account_journal(osv.osv): if not default: default = {} default = default.copy() - default['code'] = (journal['code'] or '') + '(copy)' - default['name'] = (journal['name'] or '') + '(copy)' - default['sequence_id'] = False + default.update( + code=_("%s (copy)") % (journal['code'] or ''), + name=_("%s (copy)") % (journal['name'] or ''), + sequence_id=False) return super(account_journal, self).copy(cr, uid, id, default, context=context) def write(self, cr, uid, ids, vals, context=None): diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 2dc7f96768f..9889eadf387 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -447,11 +447,13 @@ class account_bank_statement(osv.osv): return self.write(cr, uid, done, {'state':'draft'}, context=context) def _compute_balance_end_real(self, cr, uid, journal_id, context=None): - cr.execute('SELECT balance_end_real \ - FROM account_bank_statement \ - WHERE journal_id = %s AND NOT state = %s \ - ORDER BY date DESC,id DESC LIMIT 1', (journal_id, 'draft')) - res = cr.fetchone() + res = False + if journal_id: + cr.execute('SELECT balance_end_real \ + FROM account_bank_statement \ + WHERE journal_id = %s AND NOT state = %s \ + ORDER BY date DESC,id DESC LIMIT 1', (journal_id, 'draft')) + res = cr.fetchone() return res and res[0] or 0.0 def onchange_journal_id(self, cr, uid, statement_id, journal_id, context=None): diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 69b1bef08e6..5ddbbee74f2 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -485,7 +485,7 @@ class account_move_line(osv.osv): 'debit': fields.float('Debit', digits_compute=dp.get_precision('Account')), 'credit': fields.float('Credit', digits_compute=dp.get_precision('Account')), 'account_id': fields.many2one('account.account', 'Account', required=True, ondelete="cascade", domain=[('type','<>','view'), ('type', '<>', 'closed')], select=2), - 'move_id': fields.many2one('account.move', 'Move', ondelete="cascade", help="The move of this entry line.", select=2, required=True), + 'move_id': fields.many2one('account.move', 'Journal Entry', ondelete="cascade", help="The move of this entry line.", select=2, required=True), 'narration': fields.related('move_id','narration', type='text', relation='account.move', string='Internal Note'), 'ref': fields.related('move_id', 'ref', string='Reference', type='char', size=64, store=True), 'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1), @@ -708,7 +708,9 @@ class account_move_line(osv.osv): context = {} if context and context.get('next_partner_only', False): if not context.get('partner_id', False): - partner = self.get_next_partner_only(cr, uid, offset, context) + partner = self.list_partners_to_reconcile(cr, uid, context=context) + if partner: + partner = partner[0] else: partner = context.get('partner_id', False) if not partner: @@ -716,26 +718,26 @@ class account_move_line(osv.osv): args.append(('partner_id', '=', partner[0])) return super(account_move_line, self).search(cr, uid, args, offset, limit, order, context, count) - def get_next_partner_only(self, cr, uid, offset=0, context=None): + def list_partners_to_reconcile(self, cr, uid, context=None): cr.execute( """ - SELECT p.id - FROM res_partner p - RIGHT JOIN ( - SELECT l.partner_id AS partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit + SELECT partner_id + FROM ( + SELECT l.partner_id, p.last_reconciliation_date, SUM(l.debit) AS debit, SUM(l.credit) AS credit FROM account_move_line l - LEFT JOIN account_account a ON (a.id = l.account_id) - LEFT JOIN res_partner p ON (l.partner_id = p.id) + RIGHT JOIN account_account a ON (a.id = l.account_id) + RIGHT JOIN res_partner p ON (l.partner_id = p.id) WHERE a.reconcile IS TRUE AND l.reconcile_id IS NULL AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date) AND l.state <> 'draft' - GROUP BY l.partner_id - ) AS s ON (p.id = s.partner_id) + GROUP BY l.partner_id, p.last_reconciliation_date + ) AS s WHERE debit > 0 AND credit > 0 - ORDER BY p.last_reconciliation_date LIMIT 1 OFFSET %s""", (offset, ) - ) - return cr.fetchone() + ORDER BY last_reconciliation_date""") + ids = cr.fetchall() + ids = len(ids) and [x[0] for x in ids] or [] + return self.pool.get('res.partner').name_get(cr, uid, ids, context=context) def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False): move_rec_obj = self.pool.get('account.move.reconcile') @@ -915,8 +917,8 @@ class account_move_line(osv.osv): if lines and lines[0]: partner_id = lines[0].partner_id and lines[0].partner_id.id or False - if partner_id and context and context.get('stop_reconcile', False): - partner_obj.write(cr, uid, [partner_id], {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}) + if not partner_obj.has_something_to_reconcile(cr, uid, partner_id, context=context): + partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context) return r_id def view_header_get(self, cr, user, view_id, view_type, context=None): diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 874adb417d3..2c204fdf707 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -101,29 +101,29 @@ account.period
-
-
- - - - - - - - - - - - - +
+
+ + + + + + + + + + + + +
@@ -1039,7 +1039,26 @@ Entries lines --> - + + account.move.line.reconcile.tree + account.move.line + + + + + + + + + + + + + + + + + account.move.line.tree account.move.line @@ -1074,64 +1093,64 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -1513,7 +1532,6 @@ Journal Items - ir.actions.act_window account.move.line form tree,form @@ -1532,15 +1550,31 @@ - - + + {'search_default_unreconciled': 1,'view_mode':True} + Journal Items to Reconcile + account.move.line + + form + account_reconciliation_list + +

+ Good job! +

+ There is nothing to reconcile. All invoices and payments + have been reconciled, your partner balance is clean. +

+
+
+ diff --git a/addons/account/demo/account_minimal.xml b/addons/account/demo/account_minimal.xml index 53f2b54e0ef..8f858491edc 100644 --- a/addons/account/demo/account_minimal.xml +++ b/addons/account/demo/account_minimal.xml @@ -122,6 +122,14 @@ other
+ + X11007 + USD Bank Account - (test) + + liquidity + + + Liabilities - (test) @@ -360,8 +368,8 @@ bank - - + + @@ -384,7 +392,12 @@ - + + @@ -412,6 +425,16 @@
+ + + USD Bank Journal - (test) + TUBK + bank + + + + + diff --git a/addons/account/partner.py b/addons/account/partner.py index 36fd88183f2..f2b9f79bb8a 100644 --- a/addons/account/partner.py +++ b/addons/account/partner.py @@ -20,8 +20,8 @@ ############################################################################## from operator import itemgetter - from osv import fields, osv +import time class account_fiscal_position(osv.osv): _name = 'account.fiscal.position' @@ -145,6 +145,29 @@ class res_partner(osv.osv): def _debit_search(self, cr, uid, obj, name, args, context=None): return self._asset_difference_search(cr, uid, obj, name, 'payable', args, context=context) + def has_something_to_reconcile(self, cr, uid, partner_id, context=None): + ''' + at least a debit, a credit and a line older than the last reconciliation date of the partner + ''' + cr.execute(''' + SELECT l.partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit + FROM account_move_line l + RIGHT JOIN account_account a ON (a.id = l.account_id) + RIGHT JOIN res_partner p ON (l.partner_id = p.id) + WHERE a.reconcile IS TRUE + AND p.id = %s + AND l.reconcile_id IS NULL + AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date) + AND l.state <> 'draft' + GROUP BY l.partner_id''', (partner_id,)) + res = cr.dictfetchone() + if res: + return bool(res['debit'] and res['credit']) + return False + + def mark_as_reconciled(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) + _columns = { 'credit': fields.function(_credit_debit_get, fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."), @@ -185,7 +208,7 @@ class res_partner(osv.osv): help="This payment term will be used instead of the default one for the current partner"), 'ref_companies': fields.one2many('res.company', 'partner_id', 'Companies that refers to partner'), - 'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were reconciled last time') + 'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the date of the last reconciliation made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 ways: either the last debit/credit entry was reconciled, either the user pressed the button "Fully Reconciled" in the manual reconciliation process') } res_partner() diff --git a/addons/account/res_config.py b/addons/account/res_config.py index ea903654a4e..17df4377548 100644 --- a/addons/account/res_config.py +++ b/addons/account/res_config.py @@ -117,6 +117,9 @@ class account_config_settings(osv.osv_memory): 'group_multi_currency': fields.boolean('Allow multi currencies', implied_group='base.group_multi_currency', help="Allows you multi currency environment"), + 'group_analytic_accounting': fields.boolean('Analytic accounting', + implied_group='analytic.group_analytic_accounting', + help="Allows you to use the analytic accounting."), } def _default_company(self, cr, uid, context=None): diff --git a/addons/account/res_config_view.xml b/addons/account/res_config_view.xml index d7618fbff5a..0e4b1fa64c4 100644 --- a/addons/account/res_config_view.xml +++ b/addons/account/res_config_view.xml @@ -129,6 +129,10 @@