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