Browse Source
[8.0] Fix account.move.line field last_rec_date (#213)
[8.0] Fix account.move.line field last_rec_date (#213)
[8.0] account_financial_report_webkit: Fix account.move.line field last_rec_datepull/216/head
David Dufresne
8 years ago
committed by
Pedro M. Baeza
20 changed files with 393 additions and 1762 deletions
-
182account_financial_report_webkit/README.rst
-
4account_financial_report_webkit/__init__.py
-
169account_financial_report_webkit/__openerp__.py
-
78account_financial_report_webkit/account_move_line.py
-
1523account_financial_report_webkit/i18n/account_financial_report_webkit.pot
-
2account_financial_report_webkit/i18n/es.po
-
2account_financial_report_webkit/i18n/lt.po
-
42account_financial_report_webkit/migrations/8.0.1.2.0/post-migration.py
-
7account_financial_report_webkit/models/__init__.py
-
0account_financial_report_webkit/models/account.py
-
39account_financial_report_webkit/models/account_move_line.py
-
0account_financial_report_webkit/test/account_move_line.yml
-
0account_financial_report_webkit/test/aged_trial_balance.yml
-
0account_financial_report_webkit/test/general_ledger.yml
-
0account_financial_report_webkit/test/open_invoices.yml
-
0account_financial_report_webkit/test/partner_balance.yml
-
0account_financial_report_webkit/test/partner_ledger.yml
-
0account_financial_report_webkit/test/trial_balance.yml
-
5account_financial_report_webkit/tests/__init__.py
-
102account_financial_report_webkit/tests/test_account_move_line.py
@ -0,0 +1,182 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
========================== |
|||
Financial Reports - Webkit |
|||
========================== |
|||
|
|||
This module adds or replaces the following standard OpenERP financial reports: |
|||
- General ledger |
|||
- Trial Balance (simple or comparative view) |
|||
- Partner ledger |
|||
- Partner balance |
|||
- Open invoices report |
|||
- Aged Partner Balance |
|||
|
|||
Main improvements per report: |
|||
----------------------------- |
|||
|
|||
The General ledger: details of all entries posted in your books sorted by |
|||
account. |
|||
|
|||
* Filter by account is available in the wizard (no need to go to the |
|||
Chart of Accounts to do this anymore) or by View account (the report |
|||
will display all regular children accounts) i.e. you can select all |
|||
P&L accounts. |
|||
* The report only prints accounts with moves OR with a non |
|||
null balance. No more endless report with empty accounts (field: |
|||
display account is hidden) |
|||
* initial balance computation on the fly if no open entry posted |
|||
* Thanks to a new checkbox in the account form, you will have the |
|||
possibility to centralize any account you like. This means you do |
|||
not want to see all entries posted under the account ‘VAT on sales’; |
|||
you will only see aggregated amounts by periods. |
|||
* Counterpart account is displayed for each transaction (3 accounts max.) |
|||
to ease searching. |
|||
* Better ergonomy on the wizard: important information is displayed in |
|||
the top part, filters are in the middle, and options are in the |
|||
bottom or on a separate tab. There is more specific filtering on |
|||
separate tabs. No more unique wizard layout for all financial |
|||
reports (we have removed the journal tab for the GL report) |
|||
* improved report style |
|||
|
|||
The partner ledger: details of entries relative to payable & |
|||
receivable accounts posted in your books sorted by account and |
|||
partner. |
|||
|
|||
* Filter by partner now available |
|||
* Now you can see Accounts then Partner with subtotals for each |
|||
account allowing you to check you data with trial balance and |
|||
partner balance for instance. Accounts are ordered in the same way as |
|||
in the Chart of account |
|||
* Period have been added (date only is not filled in since date can be |
|||
outside period) |
|||
* Reconciliation code added |
|||
* Subtotal by account |
|||
* Alphabetical sorting (same as in partner balance) |
|||
|
|||
Open invoice report : other version of the partner ledger showing |
|||
unreconciled / partially reconciled entries. |
|||
|
|||
* Possibility to print unreconciled transactions only at any date in |
|||
the past (thanks to the new field: `last_rec_date` which computes |
|||
the last move line reconciliation date). No more pain to get open |
|||
invoices at the last closing date. |
|||
* no initial balance computed because the report shows open invoices |
|||
from previous years. |
|||
|
|||
The Trial balance: list of accounts with balances |
|||
|
|||
* You can either see the columns: initial balance, debit, credit, |
|||
end balance or compare balances over 4 periods of your choice |
|||
* You can select the "opening" filter to get the opening trial balance |
|||
only |
|||
* If you create an extra virtual chart (using consolidated account) of |
|||
accounts for your P&L and your balance sheet, you can print your |
|||
statutory accounts (with comparison over years for instance) |
|||
* If you compare 2 periods, you will get the differences in values and |
|||
in percent |
|||
|
|||
The Partner balance: list of account with balances |
|||
|
|||
* Subtotal by account and partner |
|||
* Alphabetical sorting (same as in partner balance) |
|||
|
|||
|
|||
Aged Partner Balance: Summary of aged open amount per partner |
|||
|
|||
This report is an accounting tool helping in various tasks. |
|||
You can credit control or partner balance provisions computation for instance. |
|||
|
|||
The aged balance report allows you to print balances per partner |
|||
like the trial balance but add an extra information : |
|||
|
|||
* It will split balances into due amounts |
|||
(due date not reached à the end date of the report) and overdue amounts |
|||
Overdue data are also split by period. |
|||
* For each partner following columns will be displayed: |
|||
|
|||
* Total balance (all figures must match with same date partner balance |
|||
report). |
|||
This column equals the sum of all following columns) |
|||
|
|||
* Due |
|||
* Overdue <= 30 days |
|||
* Overdue <= 60 days |
|||
* Overdue <= 90 days |
|||
* Overdue <= 120 days |
|||
* Older |
|||
|
|||
Hypothesis / Contraints of aged partner balance |
|||
|
|||
* Overdues columns will be by default be based on 30 days range fix number of |
|||
days. This can be changed by changes the RANGES constraint |
|||
* All data will be displayed in company currency |
|||
* When partial payments, the payment must appear in the same colums than the |
|||
invoice (Except if multiple payment terms) |
|||
* Data granularity: partner (will not display figures at invoices level) |
|||
* The report aggregate data per account with sub-totals |
|||
* Initial balance must be calculated the same way that |
|||
the partner balance / Ignoring the opening entry |
|||
in special period (idem open invoice report) |
|||
* Only accounts with internal type payable or receivable are considered |
|||
(idem open invoice report) |
|||
* If maturity date is null then use move line date |
|||
|
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/91/8.0 |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
In order to run properly this module makes sure you have installed the |
|||
library `wkhtmltopdf` for the pdf rendering (the library path must be |
|||
set in a System Parameter `webkit_path`). |
|||
|
|||
Initial balances in these reports are based either on opening entry |
|||
posted in the opening period or computed on the fly. So make sure |
|||
that your past accounting opening entries are in an opening period. |
|||
Initials balances are not computed when using the Date filter (since a |
|||
date can be outside its logical period and the initial balance could |
|||
be different when computed by data or by initial balance for the |
|||
period). The opening period is assumed to be the Jan. 1st of the year |
|||
with an opening flag and the first period of the year must start also |
|||
on Jan 1st. |
|||
|
|||
Totals for amounts in currencies are effective if the partner belongs to |
|||
an account with a secondary currency. |
|||
|
|||
HTML headers and footers are deactivated for these reports because of |
|||
an issue in wkhtmltopdf |
|||
(http://code.google.com/p/wkhtmltopdf/issues/detail?id=656) Instead, |
|||
the header and footer are created as text with arguments passed to |
|||
wkhtmltopdf. The texts are defined inside the report classes. |
|||
|
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Nicolas Bessi |
|||
* Guewen Baconnier |
|||
* David Dufresne <david.dufresne@savoirfairelinux.com> |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: http://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: http://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit http://odoo-community.org. |
@ -1,78 +0,0 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi. |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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.osv import fields, orm |
|||
|
|||
|
|||
class AccountMoveLine(orm.Model): |
|||
|
|||
"""Overriding Account move line in order to add last_rec_date. |
|||
Last rec date is the date of the last reconciliation (full or partial) |
|||
account move line""" |
|||
_inherit = 'account.move.line' |
|||
|
|||
def _get_move_line_from_line_rec(self, cr, uid, ids, context=None): |
|||
moves = [] |
|||
for reconcile in self.pool['account.move.reconcile'].browse( |
|||
cr, uid, ids, context=context): |
|||
for move_line in reconcile.line_partial_ids: |
|||
moves.append(move_line.id) |
|||
for move_line in reconcile.line_id: |
|||
moves.append(move_line.id) |
|||
return list(set(moves)) |
|||
|
|||
def _get_last_rec_date(self, cursor, uid, ids, name, args, context=None): |
|||
if not isinstance(ids, list): |
|||
ids = [ids] |
|||
res = {} |
|||
for line in self.browse(cursor, uid, ids, context): |
|||
res[line.id] = {'last_rec_date': False} |
|||
rec = line.reconcile_id or line.reconcile_partial_id or False |
|||
if rec: |
|||
# we use cursor in order to gain some perfs. |
|||
# also, important point: LIMIT 1 is not used due to |
|||
# performance issues when in conjonction with "OR" |
|||
# (one backwards index scan instead of 2 scans and a sort) |
|||
cursor.execute('SELECT date from account_move_line' |
|||
' WHERE reconcile_id = %s' |
|||
' OR reconcile_partial_id = %s' |
|||
' ORDER BY date DESC', |
|||
(rec.id, rec.id)) |
|||
res_set = cursor.fetchone() |
|||
if res_set: |
|||
res[line.id] = {'last_rec_date': res_set[0]} |
|||
return res |
|||
|
|||
_columns = { |
|||
'last_rec_date': fields.function( |
|||
_get_last_rec_date, |
|||
method=True, |
|||
string='Last reconciliation date', |
|||
store={'account.move.line': (lambda self, cr, uid, ids, c={}: ids, |
|||
['date', 'reconcile_id', |
|||
'partial_reconcile_id'], 20), |
|||
'account.move.reconcile': (_get_move_line_from_line_rec, |
|||
None, 20)}, |
|||
type='date', |
|||
multi='all', |
|||
help="the date of the last reconciliation (full or partial) \ |
|||
account move line"), |
|||
} |
1523
account_financial_report_webkit/i18n/account_financial_report_webkit.pot
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,42 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Savoir-faire Linux |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
def migrate(cr, version): |
|||
if not version: |
|||
return |
|||
|
|||
_logger.info('Updating column last_rec_date on account_move_line') |
|||
|
|||
cr.execute( |
|||
""" |
|||
UPDATE account_move_line SET last_rec_date = rec_data.aml_date |
|||
FROM ( |
|||
SELECT rec.id, max(aml.date) as aml_date |
|||
FROM account_move_line aml |
|||
JOIN account_move_reconcile rec |
|||
ON rec.id = aml.reconcile_id |
|||
GROUP BY rec.id |
|||
) as rec_data |
|||
WHERE rec_data.id = account_move_line.reconcile_id |
|||
""" |
|||
) |
|||
|
|||
cr.execute( |
|||
""" |
|||
UPDATE account_move_line SET last_rec_date = rec_data.aml_date |
|||
FROM ( |
|||
SELECT rec.id, max(aml.date) as aml_date |
|||
FROM account_move_line aml |
|||
JOIN account_move_reconcile rec |
|||
ON rec.id = aml.reconcile_partial_id |
|||
GROUP BY rec.id |
|||
) as rec_data |
|||
WHERE rec_data.id = account_move_line.reconcile_partial_id |
|||
""" |
|||
) |
@ -0,0 +1,7 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2011 Camptocamp SA |
|||
# © 2016 Savoir-faire Linux |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from . import account |
|||
from . import account_move_line |
@ -0,0 +1,39 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2011 Camptocamp SA |
|||
# © 2016 Savoir-faire Linux |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import api, fields, models |
|||
|
|||
|
|||
class AccountMoveLine(models.Model): |
|||
""" |
|||
Overriding Account move line in order to add last_rec_date. |
|||
Last rec date is the date of the last reconciliation (full or partial) |
|||
account move line |
|||
""" |
|||
|
|||
_inherit = 'account.move.line' |
|||
|
|||
last_rec_date = fields.Date( |
|||
compute='_compute_last_rec_date', |
|||
store=True, |
|||
string='Last reconciliation date', |
|||
help="The date of the last reconciliation (full or partial) " |
|||
"account move line." |
|||
) |
|||
|
|||
@api.depends( |
|||
'reconcile_id.line_id.date', |
|||
'reconcile_partial_id.line_partial_ids.date') |
|||
def _compute_last_rec_date(self): |
|||
for line in self: |
|||
if line.reconcile_id: |
|||
move_lines = line.reconcile_id.line_id |
|||
last_line = move_lines.sorted(lambda l: l.date)[-1] |
|||
line.last_rec_date = last_line.date |
|||
|
|||
elif line.reconcile_partial_id: |
|||
move_lines = line.reconcile_partial_id.line_partial_ids |
|||
last_line = move_lines.sorted(lambda l: l.date)[-1] |
|||
line.last_rec_date = last_line.date |
@ -0,0 +1,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Savoir-faire Linux |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from . import test_account_move_line |
@ -0,0 +1,102 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Savoir-faire Linux |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from datetime import datetime |
|||
from dateutil.relativedelta import relativedelta |
|||
|
|||
from openerp import fields |
|||
from openerp.tests import common |
|||
to_string = fields.Date.to_string |
|||
|
|||
|
|||
class TestAccountMoveLine(common.TransactionCase): |
|||
|
|||
def setUp(self): |
|||
super(TestAccountMoveLine, self).setUp() |
|||
|
|||
self.date_1 = datetime.now() |
|||
self.date_2 = datetime.now() + relativedelta(days=1) |
|||
|
|||
self.account_expense = self.env['account.account'].search([ |
|||
('type', '=', 'other'), |
|||
], limit=1) |
|||
|
|||
self.account_receivable = self.env['account.account'].search([ |
|||
('type', '=', 'receivable'), |
|||
], limit=1) |
|||
|
|||
self.journal = self.env['account.journal'].search([ |
|||
('type', '=', 'bank'), |
|||
], limit=1) |
|||
|
|||
self.period_1 = self.env['account.period'].find(self.date_1) |
|||
self.period_2 = self.env['account.period'].find(self.date_2) |
|||
|
|||
self.move_1 = self.env['account.move'].create({ |
|||
'name': '/', |
|||
'journal_id': self.journal.id, |
|||
'date': self.date_1, |
|||
'period_id': self.period_1.id, |
|||
'line_id': [ |
|||
(0, 0, { |
|||
'name': '/', |
|||
'account_id': self.account_receivable.id, |
|||
'debit': 100, |
|||
}), |
|||
(0, 0, { |
|||
'name': '/', |
|||
'account_id': self.account_expense.id, |
|||
'credit': 100, |
|||
}), |
|||
] |
|||
}) |
|||
|
|||
self.line_1 = self.move_1.line_id.sorted(lambda l: l.id)[0] |
|||
|
|||
def create_payment_move(self, amount): |
|||
return self.env['account.move'].create({ |
|||
'name': '/', |
|||
'journal_id': self.journal.id, |
|||
'date': self.date_2, |
|||
'period_id': self.period_2.id, |
|||
'line_id': [ |
|||
(0, 0, { |
|||
'name': '/', |
|||
'account_id': self.account_receivable.id, |
|||
'credit': amount, |
|||
}), |
|||
(0, 0, { |
|||
'name': '/', |
|||
'account_id': self.account_expense.id, |
|||
'debit': amount, |
|||
}), |
|||
] |
|||
}) |
|||
|
|||
def test_01_last_rec_date(self): |
|||
self.move_2 = self.create_payment_move(100) |
|||
self.line_2 = self.move_2.line_id.sorted(lambda l: l.id)[0] |
|||
|
|||
self.reconcile = self.env['account.move.reconcile'].create({ |
|||
'name': 'A999', |
|||
'type': 'auto', |
|||
'line_id': [(4, self.line_1.id), (4, self.line_2.id)] |
|||
}) |
|||
self.assertEqual(self.line_1.last_rec_date, to_string(self.date_2)) |
|||
|
|||
def test_02_last_rec_date_with_partial_reconcile(self): |
|||
self.move_2 = self.create_payment_move(50) |
|||
self.line_2 = self.move_2.line_id.sorted(lambda l: l.id)[0] |
|||
|
|||
self.move_3 = self.create_payment_move(50) |
|||
self.line_3 = self.move_3.line_id.sorted(lambda l: l.id)[0] |
|||
|
|||
self.reconcile = self.env['account.move.reconcile'].create({ |
|||
'name': 'A999', |
|||
'type': 'auto', |
|||
'line_partial_ids': [ |
|||
(4, self.line_1.id), (4, self.line_2.id), (4, self.line_3.id) |
|||
] |
|||
}) |
|||
self.assertEqual(self.line_1.last_rec_date, to_string(self.date_2)) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue