Browse Source

Merge pull request #9 from savoirfairelinux/7.0_account_partner_aged_statement

7.0 account partner aged statement
pull/171/head
Maxime Chambreuil - http://www.savoirfairelinux.com 9 years ago
parent
commit
5193f5cccd
  1. 4
      .travis.yml
  2. 26
      account_partner_aged_statement_webkit/__init__.py
  3. 66
      account_partner_aged_statement_webkit/__openerp__.py
  4. 267
      account_partner_aged_statement_webkit/i18n/account_partner_aged_statement_webkit.pot
  5. 319
      account_partner_aged_statement_webkit/i18n/fr.po
  6. 76
      account_partner_aged_statement_webkit/partner_aged_statement.py
  7. 74
      account_partner_aged_statement_webkit/partner_aged_statement_data.xml
  8. 32
      account_partner_aged_statement_webkit/partner_aged_statement_report.xml
  9. 21
      account_partner_aged_statement_webkit/partner_aged_statement_view.xml
  10. 26
      account_partner_aged_statement_webkit/report/__init__.py
  11. 214
      account_partner_aged_statement_webkit/report/partner_aged_statement.mako
  12. 324
      account_partner_aged_statement_webkit/report/partner_aged_statement_report.py
  13. 49
      account_partner_aged_statement_webkit/report/supplier_aged_statement_report.py
  14. 28
      account_partner_aged_statement_webkit/tests/__init__.py
  15. 220
      account_partner_aged_statement_webkit/tests/test_aged_statement.py

4
.travis.yml

@ -29,6 +29,10 @@ before_install:
install:
- git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
- git clone https://github.com/OCA/webkit-tools.git ${HOME}/webkit-tools -b ${VERSION}
- sudo apt-get install xfonts-75dpi
- sudo wget http://sourceforge.net/projects/wkhtmltopdf/files/0.12.2.1/wkhtmltox-0.12.2.1_linux-precise-amd64.deb -P /tmp/
- sudo dpkg -i /tmp/wkhtmltox-0.12.2.1_linux-precise-amd64.deb
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- travis_install_nightly

26
account_partner_aged_statement_webkit/__init__.py

@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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 (
partner_aged_statement,
report,
)

66
account_partner_aged_statement_webkit/__openerp__.py

@ -0,0 +1,66 @@
# -*- encoding: utf-8 -*-
###############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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': 'Partner Aged Statement',
"version": "1.0",
'author': 'Savoir-faire Linux',
'website': 'http://www.savoirfairelinux.com',
'depends': [
'report_webkit',
'base_headers_webkit',
'mail',
'account',
],
'category': 'Accounting',
'description': """
Print & Send Partner Aged Statement by email
============================================
This module adds in the system :
* a new mail template "Aged Statement Letter";
* the ability to print the partner aged statement;
* a button "Send by email" in the partner form view which load the template
and attach the statement to the email.
Comparing to 'Overdue Payment' report provided with OpenERP, this one adds more
informations :
* the summary per period
* the list of invoices per period
* the invoices are also shown with the foreign currency
Both messages, in the PDF and the email are taken from the Overdue Payments
Message defined on the Company's configuration.
Contributors
------------
* Marc Cassuto (marc.cassuto@savoirfairelinux.com)
* Vincent Vinet (vincent.vinet@savoirfairelinux.com)
""",
'data': [
'partner_aged_statement_report.xml',
'partner_aged_statement_view.xml',
'partner_aged_statement_data.xml',
],
'active': False,
'installable': True
}

267
account_partner_aged_statement_webkit/i18n/account_partner_aged_statement_webkit.pot

@ -0,0 +1,267 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_partner_aged_statement_webkit
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-12-24 18:15+0000\n"
"PO-Revision-Date: 2014-12-24 18:15+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_partner_aged_statement_webkit
#: model:email.template,subject:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "${object.company_id.name} - Your aged balance"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: model:ir.actions.report.xml,name:account_partner_aged_statement_webkit.partner_aged_statement_report
msgid "Partner Aged Statement"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: model:ir.actions.report.xml,name:account_partner_aged_statement_webkit.supplier_aged_statement_report
msgid "Supplier Aged Statement"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:60
msgid "Not Due"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:141
msgid "+60"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:89
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:117
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:145
msgid "Description"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Overdue Statement"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:82
msgid "List of Due Invoices"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:62
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:113
msgid "30-60"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: model:email.template,report_name:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "\n"
" ${(object.name or '').replace('/','_')}\n"
" "
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:93
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:121
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:149
msgid "Paid"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:35
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:88
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:116
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:144
msgid "Date"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:64
msgid "90-120"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:52
msgid "Nothing due for this partner"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: model:email.template,body_html:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "\n"
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
" <!--<p>${user.company_id.overdue_msg.replace('\\n', '&lt;br/&gt;')} </p>-->\n"
" % for line in user.company_id.overdue_msg.split('\\n'):\n"
" <p> ${line}<br/> </p>\n"
" % endfor\n"
"\n"
" <br/>\n"
" ${user.name}\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p style=\"border-left: 1px solid #8e0000; margin-left: 30px;\">\n"
" &nbsp;&nbsp;<strong>REFERENCES</strong><br />\n"
" &nbsp;&nbsp;Total overdue amount: ${object.credit} ${user.company_id.currency_id.name}<br/>\n"
" </p>\n"
"\n"
" <br/>\n"
" <br/>\n"
" <div style=\"width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;\">\n"
" <h3 style=\"margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;\">\n"
" <strong style=\"text-transform:uppercase;\">${user.company_id.name}</strong></h3>\n"
" </div>\n"
" <div style=\"width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;\">\n"
" <span style=\"color: #222; margin-bottom: 5px; display: block; \">\n"
" % if user.company_id.street:\n"
" ${user.company_id.street}<br/>\n"
" % endif\n"
" % if user.company_id.street2:\n"
" ${user.company_id.street2}<br/>\n"
" % endif\n"
" % if user.company_id.city or user.company_id.zip:\n"
" ${user.company_id.zip} ${user.company_id.city}<br/>\n"
" % endif\n"
" % if user.company_id.country_id:\n"
" ${user.company_id.state_id and ('%s, ' % user.company_id.state_id.name) or ''} ${user.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" </span>\n"
" % if user.company_id.phone:\n"
" <div style=\"margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; \">\n"
" Phone:&nbsp; ${user.company_id.phone}\n"
" </div>\n"
" % endif\n"
" % if user.company_id.website:\n"
" <div>\n"
" Web :&nbsp;<a href=\"${user.company_id.website}\">${user.company_id.website}</a>\n"
" </div>\n"
" %endif\n"
" <p></p>\n"
" </div>\n"
"</div>\n"
" "
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:63
msgid "60-90"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Currency"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: view:res.partner:0
msgid "Send Aged Statement"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:92
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:120
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:148
msgid "Amount"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:90
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:118
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:146
msgid "Reference"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:91
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:119
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:147
msgid "Due date"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:54
msgid "Aged Balance"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:65
msgid "+120"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:61
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:85
msgid "0-30"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:37
#: model:ir.model,name:account_partner_aged_statement_webkit.model_res_partner
msgid "Partner"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:66
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:94
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:95
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:122
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:123
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:150
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:151
msgid "Total"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Subject"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Phone:"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Mail:"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of current invoices"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of overdue invoices"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Sum of Customer Refunds"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of Customer Refunds"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Sum of Supplier Refunds"
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of Supplier Refunds"
msgstr ""

319
account_partner_aged_statement_webkit/i18n/fr.po

@ -0,0 +1,319 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_partner_aged_statement_webkit
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-12-24 18:15+0000\n"
"PO-Revision-Date: 2014-12-24 18:15+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_partner_aged_statement_webkit
#: model:email.template,subject:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "${object.company_id.name} - Your aged balance"
msgstr "${object.company_id.name} - Votre balance âgée"
#. module: account_partner_aged_statement_webkit
#: model:ir.actions.report.xml,name:account_partner_aged_statement_webkit.partner_aged_statement_report
msgid "Partner Aged Statement"
msgstr "Relevé de balance âgée"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:60
msgid "Not Due"
msgstr "Non dû"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:141
msgid "+60"
msgstr "+60"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:89
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:117
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:145
msgid "Description"
msgstr "Description"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Overdue Statement"
msgstr "Déclaration en retard"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:82
msgid "List of Due Invoices"
msgstr "Liste de factures dues"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:62
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:113
msgid "30-60"
msgstr "30-60"
#. module: account_partner_aged_statement_webkit
#: model:email.template,report_name:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "\n"
" ${(object.name or '').replace('/','_')}\n"
" "
msgstr ""
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:93
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:121
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:149
msgid "Paid"
msgstr "Payé"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:35
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:88
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:116
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:144
msgid "Date"
msgstr "Date"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:64
msgid "90-120"
msgstr "90-120"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:52
msgid "Nothing due for this partner"
msgstr "Rien de dû pour ce partenaire"
#. module: account_partner_aged_statement_webkit
#: model:email.template,body_html:account_partner_aged_statement_webkit.email_template_aged_statement
msgid "\n"
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
" <!--<p>${user.company_id.overdue_msg.replace('\\n', '&lt;br/&gt;')} </p>-->\n"
" % for line in user.company_id.overdue_msg.split('\\n'):\n"
" <p> ${line}<br/> </p>\n"
" % endfor\n"
"\n"
" <br/>\n"
" ${user.name}\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p style=\"border-left: 1px solid #8e0000; margin-left: 30px;\">\n"
" &nbsp;&nbsp;<strong>REFERENCES</strong><br />\n"
" &nbsp;&nbsp;Total overdue amount: ${object.credit} ${user.company_id.currency_id.name}<br/>\n"
" </p>\n"
"\n"
" <br/>\n"
" <br/>\n"
" <div style=\"width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;\">\n"
" <h3 style=\"margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;\">\n"
" <strong style=\"text-transform:uppercase;\">${user.company_id.name}</strong></h3>\n"
" </div>\n"
" <div style=\"width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;\">\n"
" <span style=\"color: #222; margin-bottom: 5px; display: block; \">\n"
" % if user.company_id.street:\n"
" ${user.company_id.street}<br/>\n"
" % endif\n"
" % if user.company_id.street2:\n"
" ${user.company_id.street2}<br/>\n"
" % endif\n"
" % if user.company_id.city or user.company_id.zip:\n"
" ${user.company_id.zip} ${user.company_id.city}<br/>\n"
" % endif\n"
" % if user.company_id.country_id:\n"
" ${user.company_id.state_id and ('%s, ' % user.company_id.state_id.name) or ''} ${user.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" </span>\n"
" % if user.company_id.phone:\n"
" <div style=\"margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; \">\n"
" Phone:&nbsp; ${user.company_id.phone}\n"
" </div>\n"
" % endif\n"
" % if user.company_id.website:\n"
" <div>\n"
" Web :&nbsp;<a href=\"${user.company_id.website}\">${user.company_id.website}</a>\n"
" </div>\n"
" %endif\n"
" <p></p>\n"
" </div>\n"
"</div>\n"
" "
msgstr "\n"
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
" <!--<p>${user.company_id.overdue_msg.replace('\\n', '&lt;br/&gt;')} </p>-->\n"
" % for line in user.company_id.overdue_msg.split('\\n'):\n"
" <p> ${line}<br/> </p>\n"
" % endfor\n"
"\n"
" <br/>\n"
" ${user.name}\n"
" <br/>\n"
" <br/>\n"
"\n"
" <p style=\"border-left: 1px solid #8e0000; margin-left: 30px;\">\n"
" &nbsp;&nbsp;<strong>RÉFÉRENCES</strong><br />\n"
" &nbsp;&nbsp;Total du montant en retard: ${object.credit} ${user.company_id.currency_id.name}<br/>\n"
" </p>\n"
"\n"
" <br/>\n"
" <br/>\n"
" <div style=\"width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;\">\n"
" <h3 style=\"margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;\">\n"
" <strong style=\"text-transform:uppercase;\">${user.company_id.name}</strong></h3>\n"
" </div>\n"
" <div style=\"width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;\">\n"
" <span style=\"color: #222; margin-bottom: 5px; display: block; \">\n"
" % if user.company_id.street:\n"
" ${user.company_id.street}<br/>\n"
" % endif\n"
" % if user.company_id.street2:\n"
" ${user.company_id.street2}<br/>\n"
" % endif\n"
" % if user.company_id.city or user.company_id.zip:\n"
" ${user.company_id.zip} ${user.company_id.city}<br/>\n"
" % endif\n"
" % if user.company_id.country_id:\n"
" ${user.company_id.state_id and ('%s, ' % user.company_id.state_id.name) or ''} ${user.company_id.country_id.name or ''}<br/>\n"
" % endif\n"
" </span>\n"
" % if user.company_id.phone:\n"
" <div style=\"margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; \">\n"
" Téléphone:&nbsp; ${user.company_id.phone}\n"
" </div>\n"
" % endif\n"
" % if user.company_id.website:\n"
" <div>\n"
" Site :&nbsp;<a href=\"${user.company_id.website}\">${user.company_id.website}</a>\n"
" </div>\n"
" %endif\n"
" <p></p>\n"
" </div>\n"
"</div>\n"
" "
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:63
msgid "60-90"
msgstr "60-90"
#. module: account_partner_aged_statement_webkit
#: view:res.partner:0
msgid "Send Aged Statement"
msgstr "Envoyer le relevé de balance âgées"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:92
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:120
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:148
msgid "Amount"
msgstr "Montant"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:90
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:118
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:146
msgid "Reference"
msgstr "Référence"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:91
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:119
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:147
msgid "Due date"
msgstr "Date due"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:54
msgid "Aged Balance"
msgstr "Balance âgée"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of current invoices"
msgstr "Liste de factures en cours"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of overdue invoices"
msgstr "Liste de factures dues"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:65
msgid "+120"
msgstr "+120"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:61
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:85
msgid "0-30"
msgstr "0-30"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Currency"
msgstr "Devise"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:37
#: model:ir.model,name:account_partner_aged_statement_webkit.model_res_partner
msgid "Partner"
msgstr "Partenaire"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:66
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:94
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:95
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:122
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:123
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:150
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:151
msgid "Total"
msgstr "Total"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Subject"
msgstr "Sujet"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Phone:"
msgstr "Téléphone:"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:39
msgid "Mail:"
msgstr "Courriel:"
#. module: account_partner_aged_statement_webkit
#: model:ir.actions.report.xml,name:account_partner_aged_statement_webkit.supplier_aged_statement_report
msgid "Supplier Aged Statement"
msgstr "Relevé de balance âgée FRS"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Sum of Customer Refunds"
msgstr "Somme des notes de crédit"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of Customer Refunds"
msgstr "Liste des notes de crédit"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "Sum of Supplier Refunds"
msgstr "Somme des notes de crédit"
#. module: account_partner_aged_statement_webkit
#: report:addons/account_partner_aged_statement_webkit/report/partner_aged_statement.mako:0
msgid "List of Supplier Refunds"
msgstr "Liste des notes de crédit"

76
account_partner_aged_statement_webkit/partner_aged_statement.py

@ -0,0 +1,76 @@
# -*- encoding: utf-8 -*-
###############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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 orm
class PartnerAgedStatement(orm.Model):
_inherit = 'res.partner'
def action_aged_statement_send(self, cr, uid, ids, context=None):
# This function opens a window to compose an email,
# with the partner aged statemen template message loaded by default
# This option should only be used for a single id at a time.
assert len(ids) == 1
ir_model_data = self.pool.get('ir.model.data')
try:
template_id = ir_model_data.get_object_reference(
cr, uid,
'account_partner_aged_statement_webkit',
'email_template_aged_statement')[1]
except ValueError:
template_id = False
try:
compose_form_id = ir_model_data.get_object_reference(
cr, uid, 'mail', 'email_compose_message_wizard_form')[1]
except ValueError:
compose_form_id = False
# When doing search with related company, it creates a bug saying
# the xx id doesn't exist in mail.message.
# The default_parent_id is used by mail.compose.message model
# to get the message_id. It must be false when doing search with
# related company
if 'default_parent_id' in context:
del context['default_parent_id']
ctx = dict(context)
ctx.update({
'default_model': 'res.partner',
'default_res_id': ids[0],
'default_use_template': bool(template_id),
'default_template_id': template_id,
'default_composition_mode': 'comment',
})
# Full explanation of this return is here :
# http://stackoverflow.com/questions/12634031
return {
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(compose_form_id, 'form')],
'view_id': compose_form_id,
'target': 'new',
'context': ctx,
}

74
account_partner_aged_statement_webkit/partner_aged_statement_data.xml

@ -0,0 +1,74 @@
<?xml version="1.0" ?>
<openerp>
<!-- Mail template is done in a NOUPDATE block
so users can freely customize/delete them -->
<data noupdate="0">
<!--Email template -->
<record id="email_template_aged_statement" model="email.template">
<field name="name">Aged Statement Letter</field>
<field name="email_from">${(user.email or '')|safe}</field>
<field name="subject">${object.company_id.name} - Your aged balance</field>
<field name="email_recipients">${object.id or ''|safe}</field>
<field name="model_id" ref="account.model_res_partner"/>
<field name="auto_delete" eval="True"/>
<field name="report_template" ref="partner_aged_statement_report"/>
<field name="report_name">
${(object.name or '').replace('/','_')}
</field>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">
<!--<p>${user.company_id.overdue_msg.replace('\n', '&lt;br/&gt;')} </p>-->
% for line in user.company_id.overdue_msg.split('\n'):
<p> ${line}<br/> </p>
% endfor
<br/>
${user.name}
<br/>
<br/>
<p style="border-left: 1px solid #8e0000; margin-left: 30px;">
&nbsp;&nbsp;<strong>REFERENCES</strong><br />
&nbsp;&nbsp;Total overdue amount: ${object.credit} ${user.company_id.currency_id.name}<br/>
</p>
<br/>
<br/>
<div style="width: 375px; margin: 0px; padding: 0px; background-color: #8E0000; border-top-left-radius: 5px 5px; border-top-right-radius: 5px 5px; background-repeat: repeat no-repeat;">
<h3 style="margin: 0px; padding: 2px 14px; font-size: 12px; color: #DDD;">
<strong style="text-transform:uppercase;">${user.company_id.name}</strong></h3>
</div>
<div style="width: 347px; margin: 0px; padding: 5px 14px; line-height: 16px; background-color: #F2F2F2;">
<span style="color: #222; margin-bottom: 5px; display: block; ">
% if user.company_id.street:
${user.company_id.street}<br/>
% endif
% if user.company_id.street2:
${user.company_id.street2}<br/>
% endif
% if user.company_id.city or user.company_id.zip:
${user.company_id.zip} ${user.company_id.city}<br/>
% endif
% if user.company_id.country_id:
${user.company_id.state_id and ('%s, ' % user.company_id.state_id.name) or ''} ${user.company_id.country_id.name or ''}<br/>
% endif
</span>
% if user.company_id.phone:
<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">
Phone:&nbsp; ${user.company_id.phone}
</div>
% endif
% if user.company_id.website:
<div>
Web :&nbsp;<a href="${user.company_id.website}">${user.company_id.website}</a>
</div>
%endif
<p></p>
</div>
</div>
]]></field>
</record>
</data>
</openerp>

32
account_partner_aged_statement_webkit/partner_aged_statement_report.xml

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<report
auto="False"
id="partner_aged_statement_report"
model="res.partner"
string="Partner Aged Statement"
name="webkit.partner_aged_statement_report"
file="account_partner_aged_statement_webkit/report/partner_aged_statement.mako"
report_type="webkit"
webkit_header="base_headers_webkit.base_reports_portrait_header"
/>
<!-- name="account.aged_trial_balance_partner"
file="account/report/account_aged_partner_balance.rml"
report_type="pdf"-->
<report
auto="False"
id="supplier_aged_statement_report"
model="res.partner"
string="Supplier Aged Statement (fournisseur)"
name="webkit.supplier_aged_statement_report"
file="account_partner_aged_statement_webkit/report/partner_aged_statement.mako"
report_type="webkit"
webkit_header="base_headers_webkit.base_reports_portrait_header"
/>
</data>
</openerp>

21
account_partner_aged_statement_webkit/partner_aged_statement_view.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="partner_aged_statement_view" model="ir.ui.view">
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<xpath expr="//form/*[1]" position="before">
<header>
<button
name="action_aged_statement_send"
type="object" string="Send Aged Statement"
class="oe_highlight"/>
</header>
</xpath>
</field>
</record>
</data>
</openerp>

26
account_partner_aged_statement_webkit/report/__init__.py

@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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 (
partner_aged_statement_report,
supplier_aged_statement_report,
)

214
account_partner_aged_statement_webkit/report/partner_aged_statement.mako

@ -0,0 +1,214 @@
## -*- coding: utf-8 -*-
<!DOCTYPE html SYSTEM
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
.total{
font-weight:bold;
}
.break{
display: block;
clear: both;
page-break-after: always;
}
${css}
</style>
</head>
<%!
def amount(text):
# replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers)
return text.replace('-', '&#8209;')
%>
<body>
%for idx, partner in enumerate(objects):
<%setLang(partner.lang)%>
%if idx > 0:
<div class="break"></div>
%endif
<br/>
<br/>
<%from datetime import date %>
${_('Date')}: ${formatLang(str(date.today()), date=True)}
<br/>
${_('Partner')}: ${partner.name}
<br/>
${_('Subject')}: <b>${_('Overdue Statement')}</b>
<br/>
<br/>
%if show_message:
%for message_line in message(partner, company):
<p>
${message_line}
</p>
%endfor
%endif
<br/>
${user.name}
<br/>
<br/>
%if (partner.credit + partner.debit == 0) :
<div class="title">${_('Nothing due for this partner')}</div>
%else:
<div class="title">${_('Aged Balance')}</div>
<br/>
%if get_balance(partner, company):
<table class="basic_table" style="width: 100%;">
<tr>
<th>${_('Current')}</th>
<th>${_('31-60')}</th>
<th>${_('61-90')}</th>
<th>${_('91-120')}</th>
<th>${_('+120')}</th>
<th>${_('Total')}</th>
<th>${_('Currency')}</th>
</tr>
%for l in get_balance(partner, company):
<tr>
<td>${ l['current'] }</td>
<td>${ l['3160'] }</td>
<td>${ l['6190'] }</td>
<td>${ l['91120'] }</td>
<td>${ l['121'] }</td>
<td>${ l['total'] }</td>
<td>${ l['currency_name']}</td>
</tr>
%endfor
</table>
%endif
<br/>
<br/>
%if get_refunds_total(partner, company):
<div>${_('Sum of Customer Refunds') if ttype == 'receipt' else _('Sum of Supplier Refunds')} : ${ get_refunds_total(partner, company) }</div>
<br/>
<br/>
%endif
%if getLinesCurrent(partner, company):
<div class="title">${_('List of current invoices')}</div>
<br/>
<table class="basic_table" style="width: 100%;">
<tr>
<th>${_('Date')}</th>
<th>${_('Description')}</th>
<th>${_('Reference')}</th>
<th>${_('Due date')}</th>
<th>${_('Amount')}</th>
<th>${_('Paid')}</th>
<th>${_('Total')}</th>
<th>${_('Currency')}</th>
</tr>
%for line in getLinesCurrent(partner, company):
<tr>
<td>${ formatLang(line['date_original'], date=True) }</td>
<td>${ line['name'] }</td>
<td>${ line['ref'] }</td>
<td>${ line['date_due'] and formatLang(line['date_due'], date=True) or '' }</td>
<td style="text-align: right;">${ formatLang(line['amount_original']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_original'] - line['amount_unreconciled']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_unreconciled']) }</td>
<td>${ line['currency_name'] }</td>
</tr>
%endfor ## for line in getLinesCurrent(partner, company)
</table>
<br/>
<br/>
%endif ## if getLinesCurrent(partner, company)
<div class="title">${_('List of overdue invoices')}</div>
%if getLines3160(partner, company):
<br/>
<div class="total">${_('31-60')}</div>
<table class="basic_table" style="width: 100%;">
<tr>
<th>${_('Date')}</th>
<th>${_('Description')}</th>
<th>${_('Reference')}</th>
<th>${_('Due date')}</th>
<th>${_('Amount')}</th>
<th>${_('Paid')}</th>
<th>${_('Total')}</th>
<th>${_('Currency')}</th>
</tr>
%for line in getLines3160(partner, company):
<tr>
<td>${ formatLang(line['date_original'], date=True) }</td>
<td>${ line['name'] }</td>
<td>${ line['ref'] }</td>
<td>${ line['date_due'] and formatLang(line['date_due'], date=True) or '' }</td>
<td style="text-align: right;">${ formatLang(line['amount_original']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_original'] - line['amount_unreconciled']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_unreconciled']) }</td>
<td>${ line['currency_name'] }</td>
</tr>
%endfor ## for line in getLines3160(partner, company)
</table>
%endif ## if getLines3160(partner, company)
%if getLines61(partner, company):
<br/>
<div class="total">${_('+60')}</div>
<table class="basic_table" style="width: 100%;">
<tr>
<th>${_('Date')}</th>
<th>${_('Description')}</th>
<th>${_('Reference')}</th>
<th>${_('Due date')}</th>
<th>${_('Amount')}</th>
<th>${_('Paid')}</th>
<th>${_('Total')}</th>
<th>${_('Currency')}</th>
</tr>
%for line in getLines61(partner, company):
<tr>
<td>${ formatLang(line['date_original'], date=True) }</td>
<td>${ line['name'] }</td>
<td>${ line['ref'] }</td>
<td>${ line['date_due'] and formatLang(line['date_due'], date=True) or '' }</td>
<td style="text-align: right;">${ formatLang(line['amount_original']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_original'] - line['amount_unreconciled']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_unreconciled']) }</td>
<td>${ line['currency_name'] }</td>
</tr>
%endfor ## for line in getLines61(partner, company)
</table>
%endif ## if getLines61(partner)
%if getLinesRefunds(partner, company):
<br/>
<br/>
<div class="title">${_('List of Customer Refunds') if ttype == 'receipt' else _('List of Supplier Refunds')}</div>
<br/>
<table class="basic_table" style="width: 100%;">
<tr>
<th>${_('Date')}</th>
<th>${_('Description')}</th>
<th>${_('Reference')}</th>
<th>${_('Due date')}</th>
<th>${_('Amount')}</th>
<th>${_('Paid')}</th>
<th>${_('Total')}</th>
<th>${_('Currency')}</th>
</tr>
%for line in getLinesRefunds(partner, company):
<tr>
<td>${ formatLang(line['date_original'], date=True) }</td>
<td>${ line['name'] }</td>
<td>${ line['ref'] }</td>
<td>${ line['date_due'] and formatLang(line['date_due'], date=True) or '' }</td>
<td style="text-align: right;">${ formatLang(line['amount_original']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_original'] - line['amount_unreconciled']) }</td>
<td style="text-align: right;">${ formatLang(line['amount_unreconciled']) }</td>
<td>${ line['currency_name'] }</td>
</tr>
%endfor ## for line in getLinesCurrent(partner, company)
</table>
%endif ## if getLinesRefunds(partner, company)
%endif ## if (partner.credit + partner.debit == 0
%endfor ## for partner in objects
</body>
</html>

324
account_partner_aged_statement_webkit/report/partner_aged_statement_report.py

@ -0,0 +1,324 @@
# -*- encoding: utf-8 -*-
###############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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/>.
#
###############################################################################
import time
import pytz
from datetime import datetime
from dateutil.relativedelta import relativedelta
import itertools
from openerp import pooler
from openerp.addons.report_webkit.webkit_report import WebKitParser
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp.addons.account.report.account_aged_partner_balance import (
aged_trial_report
)
class PartnerAgedTrialReport(aged_trial_report):
_partners = None
def __init__(self, cr, uid, name, context):
super(PartnerAgedTrialReport, self).__init__(cr, uid, name, context)
current_user = self.localcontext["user"]
self._company = current_user.company_id
if self.localcontext.get("active_model", "") == "res.partner":
self._partners = self.localcontext["active_ids"]
self.ttype = 'receipt'
self.localcontext.update({
'message': self._message,
'getLinesCurrent': self._lines_get_current,
'getLines3160': self._lines_get_31_60,
'getLines61': self._lines_get_61,
'getLinesRefunds': self._lines_get_refunds,
'show_message': True,
'get_current_invoice_lines': self._get_current_invoice_lines,
'get_balance': self._get_balance,
'get_refunds_total': self._refunds_total,
'ttype': self.ttype,
})
self.partner_invoices_dict = {}
tz = self.localcontext.get('tz', False)
tz = tz and pytz.timezone(tz) or pytz.utc
self.today = datetime.now(tz)
def _get_balance(self, partner, company):
"""
Get the lines of balance to display in the report
"""
today = self.today
date_30 = today - relativedelta(days=30)
date_60 = today - relativedelta(days=60)
date_90 = today - relativedelta(days=90)
date_120 = today - relativedelta(days=120)
today = today.strftime(DEFAULT_SERVER_DATE_FORMAT)
date_30 = date_30.strftime(DEFAULT_SERVER_DATE_FORMAT)
date_60 = date_60.strftime(DEFAULT_SERVER_DATE_FORMAT)
date_90 = date_90.strftime(DEFAULT_SERVER_DATE_FORMAT)
date_120 = date_120.strftime(DEFAULT_SERVER_DATE_FORMAT)
movelines = [
line for line in
self._get_current_invoice_lines(partner, company, today)
if line['type'] in ['in_invoice', 'out_invoice']
]
movelines = sorted(movelines, key=lambda x: x['currency_name'])
grouped_movelines = [
(key, list(group)) for key, group in itertools.groupby(
movelines, key=lambda x: x['currency_name'])
]
res = {}
for currency_name, lines in grouped_movelines:
res[currency_name] = {
'current': 0,
'30': 0,
'3160': 0,
'6190': 0,
'91120': 0,
'121': 0,
'total': 0,
'currency_name': currency_name,
}
current_dict = res[currency_name]
for line in lines:
amount = line['amount_unreconciled']
if (
not line['date_original'] or
line['date_original'] >= date_30
):
current_dict['current'] += amount
elif line['date_original'] >= date_60:
current_dict['3160'] += amount
elif line['date_original'] >= date_90:
current_dict['6190'] += amount
elif line['date_original'] >= date_120:
current_dict['91120'] += amount
else:
current_dict['121'] += amount
current_dict['total'] += amount
return res.values()
def _get_current_invoice_lines(self, partner, company, date):
"""
Get all invoices with unpaid amounts for the given supplier
:return: a list of dict containing invoice data
{
'date_due': the date of maturity
'date_original': the date of the invoice
'ref': the partner reference on the invoice
'amount_original': the original date
'amount_unreconciled': the amount left to pay
'currency_id': the currency of the invoice
'currency_name': the name of the currency
'name': the number of the invoice
}
"""
# Only compute this method one time per partner
if partner.id in self.partner_invoices_dict:
return self.partner_invoices_dict[partner.id]
pool = pooler.get_pool(self.cr.dbname)
cr, uid, context = self.cr, self.uid, self.localcontext
inv_obj = pool['account.invoice']
invoice_types = (
['out_invoice', 'out_refund'] if self.ttype == 'receipt'
else ['in_invoice', 'in_refund'])
invoice_ids = inv_obj.search(cr, uid, [
('state', '=', 'open'),
('company_id', '=', company.id),
('partner_id', '=', partner.id),
('type', 'in', invoice_types),
], context=context)
invoices = inv_obj.browse(cr, uid, invoice_ids, context=context)
res = sorted([
{
'date_due': inv.date_due or '',
'date_original': inv.date_invoice or '',
'amount_original': inv.amount_total,
'amount_unreconciled': inv.residual,
'currency_id': inv.currency_id.id,
'currency_name': inv.currency_id.name,
'name': inv.number,
'ref': inv.reference or '',
'id': inv.id,
'type': inv.type,
} for inv in invoices
], key=lambda inv: inv['date_original'])
res.reverse()
return res
def _lines_get_current(self, partner, company):
today = self.today
stop = today - relativedelta(days=30)
stop = stop.strftime(DEFAULT_SERVER_DATE_FORMAT)
movelines = self._get_current_invoice_lines(partner, company, today)
movelines = [
line for line in movelines
if ((
not line['date_original'] or
line['date_original'] >= stop
) and line['type'] in ['in_invoice', 'out_invoice'])
]
print movelines
return movelines
def _lines_get_31_60(self, partner, company):
today = self.today
start = today - relativedelta(days=31)
stop = today - relativedelta(days=60)
today = today.strftime(DEFAULT_SERVER_DATE_FORMAT)
start = start.strftime(DEFAULT_SERVER_DATE_FORMAT)
stop = stop.strftime(DEFAULT_SERVER_DATE_FORMAT)
movelines = self._get_current_invoice_lines(partner, company, today)
movelines = [
line for line in movelines
if ((
line['date_original'] and
stop <= line['date_original'] <= start
) and line['type'] in ['in_invoice', 'out_invoice'])
]
return movelines
def _lines_get_61(self, partner, company):
today = self.today
start = today - relativedelta(days=61)
today = today.strftime(DEFAULT_SERVER_DATE_FORMAT)
start = start.strftime(DEFAULT_SERVER_DATE_FORMAT)
movelines = self._get_current_invoice_lines(partner, company, today)
movelines = [
line for line in movelines
if ((
line['date_original'] and
line['date_original'] <= start
) and line['type'] in ['in_invoice', 'out_invoice'])
]
return movelines
def _refunds_total(self, partner, company):
today = self.today
movelines = self._get_current_invoice_lines(partner, company, today)
return sum(
line['amount_unreconciled'] for line in movelines
if line['type'] in ['in_refund', 'out_refund']
)
def _lines_get_refunds(self, partner, company):
today = self.today
movelines = self._get_current_invoice_lines(partner, company, today)
movelines = [
line for line in movelines
if line['type'] in ['in_refund', 'out_refund']
]
return movelines
def _message(self, obj, company):
company_pool = pooler.get_pool(self.cr.dbname)['res.company']
message = company_pool.browse(
self.cr, self.uid, company.id, {'lang': obj.lang}).overdue_msg
return message and message.split('\n') or ''
def _get_company(self, data):
return self._company.name
def _get_currency(self, data):
return self._company.currency_id.symbol
def set_context(self, objects, data, ids, report_type=None):
period_length = 30
form = {
"direction_selection": "past",
"period_length": period_length,
"result_selection": "customer",
"date_from": time.strftime("%Y-%m-%d"),
}
# Taken from 'account/wizard/account_report_aged_partner_balance.py
# which sets data from the form
start = datetime.now()
for i in range(4, -1, -1):
stop = start - relativedelta(days=period_length)
form[str(i)] = {
'name': (i != 0 and "{0}-{1}".format(
5 - (i + 1), (5 - i) * period_length,
) or '+{0}'.format(4 * period_length)),
'stop': start.strftime('%Y-%m-%d'),
'start': (i != 0 and stop.strftime('%Y-%m-%d') or False),
}
start = stop - relativedelta(days=1)
data["form"] = form
res = super(PartnerAgedTrialReport, self).set_context(
objects, data, ids, report_type=report_type)
self.orig_query = self.query
if self._partners is not None:
self.query = "{0} AND l.partner_id = {1}".format(
self.query,
", ".join(str(int(i)) for i in self._partners),
)
self.ACCOUNT_TYPE = ['receivable']
return res
def _get_lines(self, form, partner):
# self.query is used to get the lines in super()._get_lines
self.query = "{0} AND l.partner_id = {1}".format(
self.orig_query,
partner.id,)
res = super(PartnerAgedTrialReport, self)._get_lines(form)
self.query = self.orig_query
return res
WebKitParser(
'report.webkit.partner_aged_statement_report',
'res.partner',
('addons/'
'account_partner_aged_statement_webkit/'
'report/'
'partner_aged_statement.mako'),
parser=PartnerAgedTrialReport,
)

49
account_partner_aged_statement_webkit/report/supplier_aged_statement_report.py

@ -0,0 +1,49 @@
# -*- encoding: utf-8 -*-
###############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2010 - 2014 Savoir-faire Linux
# (<http://www.savoirfairelinux.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 .partner_aged_statement_report import PartnerAgedTrialReport
from openerp.addons.report_webkit.webkit_report import WebKitParser
class SupplierAgedTrialReport(PartnerAgedTrialReport):
"""
This report is like partner_aged_statement_report but it returns only
the amounts payable to the supplier
"""
def __init__(self, cr, uid, name, context):
super(SupplierAgedTrialReport, self).__init__(cr, uid, name, context)
self.ttype = 'payment'
self.localcontext.update({
'show_message': False,
'ttype': self.ttype,
})
WebKitParser(
'report.webkit.supplier_aged_statement_report',
'res.partner',
('addons/'
'account_partner_aged_statement_webkit/'
'report/'
'partner_aged_statement.mako'),
parser=SupplierAgedTrialReport,
)

28
account_partner_aged_statement_webkit/tests/__init__.py

@ -0,0 +1,28 @@
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (C) 2015 Savoir-faire Linux. 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_aged_statement,
)
checks = [
test_aged_statement,
]

220
account_partner_aged_statement_webkit/tests/test_aged_statement.py

@ -0,0 +1,220 @@
# -*- coding:utf-8 -*-
##############################################################################
#
# Copyright (C) 2015 Savoir-faire Linux. 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 import netsvc
from datetime import datetime
from openerp.tests import common
from ..report.partner_aged_statement_report import PartnerAgedTrialReport
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from dateutil.relativedelta import relativedelta
class test_aged_statement(common.TransactionCase):
def create_fiscal_year(self, year):
cr, uid, context = self.cr, self.uid, self.context
fy_id = self.fiscal_year_model.create(cr, uid, {
'name': 'Test %s' % year,
'code': 'FY%s' % year,
'company_id': self.company_id,
'date_start': datetime(year, 1, 1),
'date_stop': datetime(year, 12, 31),
}, context=context)
fy = self.fiscal_year_model.browse(cr, uid, fy_id, context=context)
fy.create_period()
def setUp(self):
super(test_aged_statement, self).setUp()
self.user_model = self.registry("res.users")
self.partner_model = self.registry("res.partner")
self.invoice_model = self.registry("account.invoice")
self.account_model = self.registry("account.account")
self.journal_model = self.registry("account.journal")
self.company_model = self.registry("res.company")
self.fiscal_year_model = self.registry("account.fiscalyear")
self.context = self.user_model.context_get(self.cr, self.uid)
cr, uid, context = self.cr, self.uid, self.context
self.company_id = self.user_model.browse(
cr, uid, uid, context=context).company_id.id
self.partner_id = self.partner_model.create(
cr, uid, {'name': 'Test', 'customer': True}, context=context)
self.account_id = self.account_model.search(
cr, uid, [
('type', '=', 'receivable'),
('currency_id', '=', False),
], context=context)[0]
self.account_2_id = self.account_model.search(
cr, uid, [
('type', '=', 'other'),
('currency_id', '=', False),
], context=context)[0]
self.journal_id = self.journal_model.search(
cr, uid, [('type', '=', 'sale')], context=context)[0]
self.today = datetime.now()
self.create_fiscal_year(self.today.year - 1)
self.date1 = self.today - relativedelta(weeks=2)
self.date2 = self.today - relativedelta(months=1, weeks=1)
self.date3 = self.today - relativedelta(months=2, weeks=1)
self.date4 = self.today - relativedelta(months=3, weeks=1)
self.date5 = self.today - relativedelta(months=4, weeks=1)
self.invoice_ids = [
self.invoice_model.create(
cr, uid, {
'journal_id': self.journal_id,
'account_id': self.account_id,
'partner_id': self.partner_id,
'date_invoice': invoice[0],
'invoice_line': [(0, 0, {
'name': 'Test',
'account_id': self.account_2_id,
'price_unit': invoice[1],
'quantity': 1,
})],
'type': invoice[2],
}, context=context)
for invoice in [
(self.today, 300, 'out_invoice'),
(self.date1, 100, 'out_invoice'),
(self.date2, 150, 'out_invoice'),
(self.date3, 200, 'out_invoice'),
(self.date4, 250, 'out_invoice'),
(self.date5, 500, 'out_invoice'),
(self.date2, 600, 'out_refund'),
(self.date4, 700, 'out_refund'),
]
]
wf_service = netsvc.LocalService("workflow")
for inv_id in self.invoice_ids:
wf_service.trg_validate(
uid, 'account.invoice', inv_id, 'invoice_open', cr)
self.report = PartnerAgedTrialReport(
cr, uid, 'webkit.partner_aged_statement_report',
context=context)
self.partner = self.partner_model.browse(
cr, uid, self.partner_id, context=context)
self.company = self.company_model.browse(
cr, uid, self.company_id, context=context)
def test_get_balance(self):
balance = self.report._get_balance(self.partner, self.company)
self.assertEqual(len(balance), 1)
self.assertEqual(balance[0]['current'], 400)
self.assertEqual(balance[0]['3160'], 150)
self.assertEqual(balance[0]['6190'], 200)
self.assertEqual(balance[0]['91120'], 250)
self.assertEqual(balance[0]['121'], 500)
self.assertEqual(balance[0]['total'], 400 + 150 + 200 + 250 + 500)
def compare_vals(self, line, vals):
self.assertEqual(
line['date_original'], vals['date_original'].strftime(
DEFAULT_SERVER_DATE_FORMAT))
self.assertEqual(line['amount_original'], vals['amount_original'])
self.assertEqual(
line['amount_unreconciled'], vals['amount_unreconciled'])
def test_line_get_current(self):
lines = self.report._lines_get_current(self.partner, self.company)
self.compare_vals(lines[0], {
'date_original': self.today,
'amount_original': 300,
'amount_unreconciled': 300,
})
self.compare_vals(lines[1], {
'date_original': self.date1,
'amount_original': 100,
'amount_unreconciled': 100,
})
def test_line_get_31_60(self):
lines = self.report._lines_get_31_60(self.partner, self.company)
self.compare_vals(lines[0], {
'date_original': self.date2,
'amount_original': 150,
'amount_unreconciled': 150,
})
def test_line_get_61(self):
lines = sorted(
self.report._lines_get_61(self.partner, self.company),
key=lambda l: l['date_original'])
self.compare_vals(lines[0], {
'date_original': self.date5,
'amount_original': 500,
'amount_unreconciled': 500,
})
self.compare_vals(lines[1], {
'date_original': self.date4,
'amount_original': 250,
'amount_unreconciled': 250,
})
self.compare_vals(lines[2], {
'date_original': self.date3,
'amount_original': 200,
'amount_unreconciled': 200,
})
def test_line_get_refunds(self):
lines = sorted(
self.report._lines_get_refunds(self.partner, self.company),
key=lambda l: l['date_original'])
self.compare_vals(lines[0], {
'date_original': self.date4,
'amount_original': 700,
'amount_unreconciled': 700,
})
self.compare_vals(lines[1], {
'date_original': self.date2,
'amount_original': 600,
'amount_unreconciled': 600,
})
def test_refunds_total(self):
res = self.report._refunds_total(self.partner, self.company)
self.assertEqual(res, 1300)
Loading…
Cancel
Save