Browse Source

[IMP] Extend customer_outstanding_statement to display also payables

pull/440/head
mreficent 7 years ago
committed by Jordi Ballester Alomar
parent
commit
209a424161
  1. 18
      customer_outstanding_statement/README.rst
  2. 4
      customer_outstanding_statement/__manifest__.py
  3. 28
      customer_outstanding_statement/report/customer_outstanding_statement.py
  4. 10
      customer_outstanding_statement/static/description/index.html
  5. 7
      customer_outstanding_statement/views/statement.xml
  6. 4
      customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.py
  7. 13
      customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.xml

18
customer_outstanding_statement/README.rst

@ -3,15 +3,15 @@
:alt: License: AGPL-3 :alt: License: AGPL-3
==================================== ====================================
Print Customer Outstanding Statement
Print Partner Outstanding Statement
==================================== ====================================
The outstanding statement provides details of all outstanding customer receivables
The outstanding statement provides details of all outstanding partner receivables or payables
up to a particular date. This includes all unpaid invoices, unclaimed refunds and up to a particular date. This includes all unpaid invoices, unclaimed refunds and
outstanding payments. The list is displayed in chronological order and is split by currencies. outstanding payments. The list is displayed in chronological order and is split by currencies.
Aging details can be shown in the report, expressed in aging buckets (30 days Aging details can be shown in the report, expressed in aging buckets (30 days
due, ...), so the customer can review how much is open, due or overdue.
due, ...), so the customer or vendor can review how much is open, due or overdue.
Configuration Configuration
============= =============
@ -20,16 +20,16 @@ Users willing to access to this report should have proper Accounting & Finance r
#. Go to *Settings / Users* and edit your user to add the corresponding access rights as follows. #. Go to *Settings / Users* and edit your user to add the corresponding access rights as follows.
#. In *Application / Accounting & Finance*, select *Billing* or *Billing Manager* #. In *Application / Accounting & Finance*, select *Billing* or *Billing Manager*
#. In *Technical Setting* mark *Show Full Accounting Features* options.
#. In *Technical Settings* mark *Show Full Accounting Features* options.
Usage Usage
===== =====
To use this module, you need to: To use this module, you need to:
#. Go to Invoicing > Sales > Master Data > Customers and select one or more
#. Press 'Action > Customer Outstanding Statement'
#. Indicate if you want to display aging buckets
#. Go to Invoicing > Sales > Master Data > Customers or or Invoicing > Purchases > Master Data > Vendors and select one or more
#. Press 'Action > Partner Outstanding Statement'
#. Indicate if you want to display receivables or payables, and if you want to display aging buckets
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
@ -39,8 +39,8 @@ To use this module, you need to:
Roadmap Roadmap
======= =======
Have an action that prints specific report for all partners that have due amounts,
at a specific date.
* In v12, the module should be renamed to `Partner Outstanding Statement`.
Maybe merge this module with the `Partner Activity Statement` module.
Bug Tracker Bug Tracker
=========== ===========

4
customer_outstanding_statement/__manifest__.py

@ -3,8 +3,8 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{ {
'name': 'Customer Outstanding Statement',
'version': '11.0.1.0.0',
'name': 'Partner Outstanding Statement',
'version': '11.0.2.0.0',
'category': 'Accounting & Finance', 'category': 'Accounting & Finance',
'summary': 'OCA Financial Reports', 'summary': 'OCA Financial Reports',
'author': "Eficent, Odoo Community Association (OCA)", 'author': "Eficent, Odoo Community Association (OCA)",

28
customer_outstanding_statement/report/customer_outstanding_statement.py

@ -43,7 +43,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
GROUP BY l1.id GROUP BY l1.id
""" % (date_end, date_end) """ % (date_end, date_end)
def _display_lines_sql_q1(self, partners, date_end):
def _display_lines_sql_q1(self, partners, date_end, account_type):
return """ return """
SELECT m.name as move_id, l.partner_id, l.date, l.name, SELECT m.name as move_id, l.partner_id, l.date, l.name,
l.ref, l.blocked, l.currency_id, l.company_id, l.ref, l.blocked, l.currency_id, l.company_id,
@ -83,14 +83,14 @@ class CustomerOutstandingStatement(models.AbstractModel):
ON pr.debit_move_id = l2.id ON pr.debit_move_id = l2.id
WHERE l2.date <= '%s' WHERE l2.date <= '%s'
) as pc ON pc.credit_move_id = l.id ) as pc ON pc.credit_move_id = l.id
WHERE l.partner_id IN (%s) AND at.type = 'receivable'
WHERE l.partner_id IN (%s) AND at.type = '%s'
AND (Q0.reconciled_date is null or AND (Q0.reconciled_date is null or
Q0.reconciled_date > '%s') Q0.reconciled_date > '%s')
AND l.date <= '%s' AND l.date <= '%s'
GROUP BY l.partner_id, m.name, l.date, l.date_maturity, l.name, GROUP BY l.partner_id, m.name, l.date, l.date_maturity, l.name,
l.ref, l.blocked, l.currency_id, l.ref, l.blocked, l.currency_id,
l.balance, l.amount_currency, l.company_id l.balance, l.amount_currency, l.company_id
""" % (date_end, date_end, partners, date_end, date_end)
""" % (date_end, date_end, partners, account_type, date_end, date_end)
def _display_lines_sql_q2(self): def _display_lines_sql_q2(self):
return """ return """
@ -113,7 +113,8 @@ class CustomerOutstandingStatement(models.AbstractModel):
WHERE c.id = %s WHERE c.id = %s
""" % company_id """ % company_id
def _get_account_display_lines(self, company_id, partner_ids, date_end):
def _get_account_display_lines(self, company_id, partner_ids, date_end,
account_type):
res = dict(map(lambda x: (x, []), partner_ids)) res = dict(map(lambda x: (x, []), partner_ids))
partners = ', '.join([str(i) for i in partner_ids]) partners = ', '.join([str(i) for i in partner_ids])
date_end = datetime.strptime( date_end = datetime.strptime(
@ -126,7 +127,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
FROM Q3 FROM Q3
ORDER BY date, date_maturity, move_id""" % ( ORDER BY date, date_maturity, move_id""" % (
self._display_lines_sql_q0(date_end), self._display_lines_sql_q0(date_end),
self._display_lines_sql_q1(partners, date_end),
self._display_lines_sql_q1(partners, date_end, account_type),
self._display_lines_sql_q2(), self._display_lines_sql_q2(),
self._display_lines_sql_q3(company_id))) self._display_lines_sql_q3(company_id)))
for row in self.env.cr.dictfetchall(): for row in self.env.cr.dictfetchall():
@ -158,7 +159,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
GROUP BY l1.id GROUP BY l1.id
""" % (date_end, date_end) """ % (date_end, date_end)
def _show_buckets_sql_q1(self, partners, date_end):
def _show_buckets_sql_q1(self, partners, date_end, account_type):
return """ return """
SELECT l.partner_id, l.currency_id, l.company_id, l.move_id, SELECT l.partner_id, l.currency_id, l.company_id, l.move_id,
CASE WHEN l.balance > 0.0 CASE WHEN l.balance > 0.0
@ -189,14 +190,14 @@ class CustomerOutstandingStatement(models.AbstractModel):
ON pr.debit_move_id = l2.id ON pr.debit_move_id = l2.id
WHERE l2.date <= '%s' WHERE l2.date <= '%s'
) as pc ON pc.credit_move_id = l.id ) as pc ON pc.credit_move_id = l.id
WHERE l.partner_id IN (%s) AND at.type = 'receivable'
WHERE l.partner_id IN (%s) AND at.type = '%s'
AND (Q0.reconciled_date is null or AND (Q0.reconciled_date is null or
Q0.reconciled_date > '%s') Q0.reconciled_date > '%s')
AND l.date <= '%s' AND not l.blocked AND l.date <= '%s' AND not l.blocked
GROUP BY l.partner_id, l.currency_id, l.date, l.date_maturity, GROUP BY l.partner_id, l.currency_id, l.date, l.date_maturity,
l.amount_currency, l.balance, l.move_id, l.amount_currency, l.balance, l.move_id,
l.company_id l.company_id
""" % (date_end, date_end, partners, date_end, date_end)
""" % (date_end, date_end, partners, account_type, date_end, date_end)
def _show_buckets_sql_q2(self, date_end, minus_30, minus_60, minus_90, def _show_buckets_sql_q2(self, date_end, minus_30, minus_60, minus_90,
minus_120): minus_120):
@ -288,7 +289,8 @@ class CustomerOutstandingStatement(models.AbstractModel):
'minus_120': date_end - timedelta(days=120), 'minus_120': date_end - timedelta(days=120),
} }
def _get_account_show_buckets(self, company_id, partner_ids, date_end):
def _get_account_show_buckets(self, company_id, partner_ids, date_end,
account_type):
res = dict(map(lambda x: (x, []), partner_ids)) res = dict(map(lambda x: (x, []), partner_ids))
partners = ', '.join([str(i) for i in partner_ids]) partners = ', '.join([str(i) for i in partner_ids])
date_end = datetime.strptime( date_end = datetime.strptime(
@ -305,7 +307,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
GROUP BY partner_id, currency_id, current, b_1_30, b_30_60, b_60_90, GROUP BY partner_id, currency_id, current, b_1_30, b_30_60, b_60_90,
b_90_120, b_over_120""" % ( b_90_120, b_over_120""" % (
self._show_buckets_sql_q0(date_end), self._show_buckets_sql_q0(date_end),
self._show_buckets_sql_q1(partners, date_end),
self._show_buckets_sql_q1(partners, date_end, account_type),
self._show_buckets_sql_q2( self._show_buckets_sql_q2(
full_dates['date_end'], full_dates['date_end'],
full_dates['minus_30'], full_dates['minus_30'],
@ -323,6 +325,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
company_id = data['company_id'] company_id = data['company_id']
partner_ids = data['partner_ids'] partner_ids = data['partner_ids']
date_end = data['date_end'] date_end = data['date_end']
account_type = data['account_type']
today = fields.Date.today() today = fields.Date.today()
buckets_to_display = {} buckets_to_display = {}
@ -331,7 +334,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
today_display, date_end_display = {}, {} today_display, date_end_display = {}, {}
lines = self._get_account_display_lines( lines = self._get_account_display_lines(
company_id, partner_ids, date_end)
company_id, partner_ids, date_end, account_type)
for partner_id in partner_ids: for partner_id in partner_ids:
lines_to_display[partner_id], amount_due[partner_id] = {}, {} lines_to_display[partner_id], amount_due[partner_id] = {}, {}
@ -357,7 +360,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
if data['show_aging_buckets']: if data['show_aging_buckets']:
buckets = self._get_account_show_buckets( buckets = self._get_account_show_buckets(
company_id, partner_ids, date_end)
company_id, partner_ids, date_end, account_type)
for partner_id in partner_ids: for partner_id in partner_ids:
buckets_to_display[partner_id] = {} buckets_to_display[partner_id] = {}
for line in buckets[partner_id]: for line in buckets[partner_id]:
@ -379,4 +382,5 @@ class CustomerOutstandingStatement(models.AbstractModel):
'Filter_non_due_partners': data['filter_non_due_partners'], 'Filter_non_due_partners': data['filter_non_due_partners'],
'Date_end': date_end_display, 'Date_end': date_end_display,
'Date': today_display, 'Date': today_display,
'account_type': account_type,
} }

10
customer_outstanding_statement/static/description/index.html

@ -1,7 +1,7 @@
<section class="oe_container"> <section class="oe_container">
<div class="oe_row oe_spaced"> <div class="oe_row oe_spaced">
<div class="oe_span12"> <div class="oe_span12">
<h2 class="oe_slogan">Customer Outstanding Statement</h2>
<h2 class="oe_slogan">Partner Outstanding Statement</h2>
</div> </div>
<div class="oe_span6"> <div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot"> <div class="oe_demo oe_picture oe_screenshot">
@ -10,10 +10,10 @@
</div> </div>
<div class="oe_span4"> <div class="oe_span4">
<p class="oe_mt32"><div style="text-align:justify">The outstanding statement provides details of all outstanding <p class="oe_mt32"><div style="text-align:justify">The outstanding statement provides details of all outstanding
customer receivables up to a particular date. This includes all unpaid invoices, unclaimed
receivables or payables of a partner up to a particular date. This includes all unpaid invoices, unclaimed
refunds and outstanding payments. The list is displayed in chronological order and is split refunds and outstanding payments. The list is displayed in chronological order and is split
by currencies.<br><br>Aging details can be shown in the report, expressed in aging buckets (30 days by currencies.<br><br>Aging details can be shown in the report, expressed in aging buckets (30 days
due, ...), so the customer can review how much is open, due or overdue.</div></p>
due, ...), so the customer or vendor can review how much is open, due or overdue.</div></p>
</div> </div>
</div> </div>
</section> </section>
@ -43,8 +43,8 @@ due, ...), so the customer can review how much is open, due or overdue.</div></p
<div class="oe_span12"> <div class="oe_span12">
<p class="oe_mt32">To use this module, you need to: <p class="oe_mt32">To use this module, you need to:
<ul> <ul>
<li>Go to <code>Invoicing > Sales > Master Data > Customers</code> and select one or more</li>
<li>Press '<code>Action > Customer Outstanding Statement</code>'</li>
<li>Go to <code>Invoicing > Sales > Master Data > Customers</code> or <code>Invoicing > Purchases > Master Data > Vendors</code> and select one or more</li>
<li>Press '<code>Action > Partner Outstanding Statement</code>'</li>
<li>Indicate if you want to display aging buckets</li> <li>Indicate if you want to display aging buckets</li>
</ul> </ul>
</p> </p>

7
customer_outstanding_statement/views/statement.xml

@ -23,8 +23,11 @@
<br/> <br/>
<t t-foreach="Lines[o.id]" t-as="currency"> <t t-foreach="Lines[o.id]" t-as="currency">
<br t-if="not currency_first" /> <br t-if="not currency_first" />
<p>
Outstanding Statement at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
<p t-if="account_type == 'receivable'">
+ Customer Outstanding Statement at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
+ </p>
<p t-if="account_type == 'payable'">
+ Supplier Outstanding Statement at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
</p> </p>
<table class="table table-condensed" style="border: 1px solid black; border-collapse: collapse;"> <table class="table table-condensed" style="border: 1px solid black; border-collapse: collapse;">
<thead> <thead>

4
customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.py

@ -27,6 +27,9 @@ class CustomerOutstandingStatementWizard(models.TransientModel):
) )
filter_partners_non_due = fields.Boolean( filter_partners_non_due = fields.Boolean(
string='Don\'t show partners with no due entries', default=True) string='Don\'t show partners with no due entries', default=True)
account_type = fields.Selection(
[('receivable', 'Receivable'),
('payable', 'Payable')], string='Account type', default='receivable')
@api.multi @api.multi
def button_export_pdf(self): def button_export_pdf(self):
@ -41,6 +44,7 @@ class CustomerOutstandingStatementWizard(models.TransientModel):
'partner_ids': self._context['active_ids'], 'partner_ids': self._context['active_ids'],
'show_aging_buckets': self.show_aging_buckets, 'show_aging_buckets': self.show_aging_buckets,
'filter_non_due_partners': self.filter_partners_non_due, 'filter_non_due_partners': self.filter_partners_non_due,
'account_type': self.account_type,
} }
def _export(self): def _export(self):

13
customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.xml

@ -4,7 +4,7 @@
<odoo> <odoo>
<!-- wizard action on res.partner --> <!-- wizard action on res.partner -->
<act_window id="customer_outstanding_statement_wizard_action" <act_window id="customer_outstanding_statement_wizard_action"
name="Customer Outstanding Statement"
name="Partner Outstanding Statement"
src_model="res.partner" src_model="res.partner"
res_model="customer.outstanding.statement.wizard" res_model="customer.outstanding.statement.wizard"
view_type="form" view_mode="form" view_type="form" view_mode="form"
@ -18,16 +18,21 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form name="Report Options"> <form name="Report Options">
<div style="text-align:justify"> <div style="text-align:justify">
<label string="The outstanding statement provides details of all outstanding
customer receivables up to a particular date. This includes all unpaid invoices, unclaimed
<label string="The outstanding statement provides details of all partner's outstanding
receivables and payables up to a particular date. This includes all unpaid invoices, unclaimed
refunds and outstanding payments. The list is displayed in chronological order and is refunds and outstanding payments. The list is displayed in chronological order and is
split by currencies."/><br/><br/> split by currencies."/><br/><br/>
<label string="Aging details can be shown in the report, expressed in aging <label string="Aging details can be shown in the report, expressed in aging
buckets (30 days due, ...), so the customer can review how much is open, due or overdue."/>
buckets (30 days due, ...), so the customer or vendor can review how much is open, due or overdue."/>
</div><hr/> </div><hr/>
<group name="main_info"> <group name="main_info">
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/> <field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group> </group>
<group name="account_type">
<label for="account_type"/>
<field name="account_type" nolabel="1" widget="radio"/>
</group>
<group name="dates"> <group name="dates">
<field name="date_end"/> <field name="date_end"/>
</group> </group>

Loading…
Cancel
Save