Browse Source

Merge 40d1ca1016 into 1ac8744ae8

pull/537/merge
Miquel Raïch 3 years ago
committed by GitHub
parent
commit
133be46c8f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      customer_activity_statement/README.rst
  2. 4
      customer_activity_statement/__manifest__.py
  3. 49
      customer_activity_statement/report/customer_activity_statement.py
  4. 10
      customer_activity_statement/static/description/index.html
  5. 25
      customer_activity_statement/static/src/less/layout_statement.less
  6. 214
      customer_activity_statement/views/statement.xml
  7. 4
      customer_activity_statement/wizard/customer_activity_statement_wizard.py
  8. 11
      customer_activity_statement/wizard/customer_activity_statement_wizard.xml
  9. 16
      customer_outstanding_statement/README.rst
  10. 4
      customer_outstanding_statement/__manifest__.py
  11. 43
      customer_outstanding_statement/report/customer_outstanding_statement.py
  12. 10
      customer_outstanding_statement/static/description/index.html
  13. 25
      customer_outstanding_statement/static/src/less/layout_statement.less
  14. 271
      customer_outstanding_statement/views/statement.xml
  15. 4
      customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.py
  16. 13
      customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.xml

16
customer_activity_statement/README.rst

@ -2,18 +2,18 @@
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
=================================
Print Customer Activity Statement
=================================
================================
Print Partner Activity Statement
================================
The activity statement provides details of all activity on the customer receivables
The activity statement provides details of all activity on the partner receivables or payables
between two selected dates. This includes all invoices, refunds and payments.
Any outstanding balance dated prior to the chosen statement period will appear
as a forward balance at the top of the statement. 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
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
=============
@ -28,9 +28,9 @@ Usage
To use this module, you need to:
#. Go to Customers and select one or more
#. Press 'Action > Customer Activity Statement'
#. Indicate if you want to display aging buckets
#. Go to Customers or Vendors and select one or more
#. Press 'Action > Partner Activity 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

4
customer_activity_statement/__manifest__.py

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

49
customer_activity_statement/report/customer_activity_statement.py

@ -19,7 +19,7 @@ class CustomerActivityStatement(models.AbstractModel):
date = datetime.strptime(str_date, DEFAULT_SERVER_DATE_FORMAT).date()
return date.strftime(lang.date_format)
def _initial_balance_sql_q1(self, partners, date_start):
def _initial_balance_sql_q1(self, partners, date_start, account_type):
return """
SELECT l.partner_id, l.currency_id, l.company_id,
CASE WHEN l.currency_id is not null AND l.amount_currency > 0.0
@ -33,11 +33,11 @@ class CustomerActivityStatement(models.AbstractModel):
FROM account_move_line l
JOIN account_account_type at ON (at.id = l.user_type_id)
JOIN account_move m ON (l.move_id = m.id)
WHERE l.partner_id IN (%s) AND at.type = 'receivable'
WHERE l.partner_id IN (%s) AND at.type = '%s'
AND l.date < '%s' AND not l.blocked
GROUP BY l.partner_id, l.currency_id, l.amount_currency,
l.company_id
""" % (partners, date_start)
""" % (partners, account_type, date_start)
def _initial_balance_sql_q2(self, company_id):
return """
@ -49,7 +49,7 @@ class CustomerActivityStatement(models.AbstractModel):
""" % company_id
def _get_account_initial_balance(self, company_id, partner_ids,
date_start):
date_start, account_type):
res = dict(map(lambda x: (x, []), partner_ids))
partners = ', '.join([str(i) for i in partner_ids])
date_start = datetime.strptime(
@ -57,13 +57,15 @@ class CustomerActivityStatement(models.AbstractModel):
# pylint: disable=E8103
self.env.cr.execute("""WITH Q1 AS (%s), Q2 AS (%s)
SELECT partner_id, currency_id, balance
FROM Q2""" % (self._initial_balance_sql_q1(partners, date_start),
FROM Q2""" % (self._initial_balance_sql_q1(partners, date_start,
account_type),
self._initial_balance_sql_q2(company_id)))
for row in self.env.cr.dictfetchall():
res[row.pop('partner_id')].append(row)
return res
def _display_lines_sql_q1(self, partners, date_start, date_end):
def _display_lines_sql_q1(self, partners, date_start, date_end,
account_type):
return """
SELECT m.name AS move_id, l.partner_id, l.date, l.name,
l.ref, l.blocked, l.currency_id, l.company_id,
@ -82,25 +84,26 @@ class CustomerActivityStatement(models.AbstractModel):
FROM account_move_line l
JOIN account_account_type at ON (at.id = l.user_type_id)
JOIN account_move m ON (l.move_id = m.id)
WHERE l.partner_id IN (%s) AND at.type = 'receivable'
WHERE l.partner_id IN (%s) AND at.type = '%s'
AND '%s' <= l.date AND l.date <= '%s'
GROUP BY l.partner_id, m.name, l.date, l.date_maturity, l.name,
l.ref, l.blocked, l.currency_id,
l.amount_currency, l.company_id
""" % (partners, date_start, date_end)
""" % (partners, account_type, date_start, date_end)
def _display_lines_sql_q2(self, company_id):
return """
SELECT Q1.partner_id, move_id, date, date_maturity, Q1.name, ref,
debit, credit, debit-credit as amount, blocked,
COALESCE(Q1.currency_id, c.currency_id) AS currency_id
SELECT Q1.partner_id, Q1.move_id, Q1.date, Q1.date_maturity,
Q1.name, Q1.ref, Q1.debit, Q1.credit,
Q1.debit-Q1.credit as amount, Q1.blocked,
COALESCE(Q1.currency_id, c.currency_id) AS currency_id
FROM Q1
JOIN res_company c ON (c.id = Q1.company_id)
WHERE c.id = %s
""" % company_id
def _get_account_display_lines(self, company_id, partner_ids, date_start,
date_end):
date_end, account_type):
# pylint: disable=sql-injection
res = dict(map(lambda x: (x, []), partner_ids))
partners = ', '.join([str(i) for i in partner_ids])
@ -113,7 +116,8 @@ class CustomerActivityStatement(models.AbstractModel):
credit, amount, blocked, currency_id
FROM Q2
ORDER BY date, date_maturity, move_id""" % (
self._display_lines_sql_q1(partners, date_start, date_end),
self._display_lines_sql_q1(partners, date_start, date_end,
account_type),
self._display_lines_sql_q2(company_id)))
for row in self.env.cr.dictfetchall():
res[row.pop('partner_id')].append(row)
@ -176,7 +180,7 @@ class CustomerActivityStatement(models.AbstractModel):
""" % (self._get_reconcile_date(), date_end,
self._get_reconcile_date(), date_end)
def _show_buckets_sql_q1(self, partners, date_end):
def _show_buckets_sql_q1(self, partners, date_end, account_type):
return """
SELECT l.partner_id, l.currency_id, l.company_id, l.move_id,
CASE WHEN l.balance > 0.0
@ -207,14 +211,14 @@ class CustomerActivityStatement(models.AbstractModel):
ON pr.debit_move_id = l2.id
WHERE l2.date <= '%s'
) 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
Q0.reconciled_date > '%s')
AND l.date <= '%s' AND not l.blocked
GROUP BY l.partner_id, l.currency_id, l.date, l.date_maturity,
l.amount_currency, l.balance, l.move_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,
minus_120):
@ -306,7 +310,8 @@ class CustomerActivityStatement(models.AbstractModel):
'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))
partners = ', '.join([str(i) for i in partner_ids])
date_end = datetime.strptime(
@ -323,7 +328,7 @@ class CustomerActivityStatement(models.AbstractModel):
GROUP BY partner_id, currency_id, current, b_1_30, b_30_60, b_60_90,
b_90_120, b_over_120""" % (
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(
full_dates['date_end'],
full_dates['minus_30'],
@ -342,6 +347,7 @@ class CustomerActivityStatement(models.AbstractModel):
partner_ids = data['partner_ids']
date_start = data['date_start']
date_end = data['date_end']
account_type = data['account_type']
today = fields.Date.today()
balance_start_to_display, buckets_to_display = {}, {}
@ -350,7 +356,7 @@ class CustomerActivityStatement(models.AbstractModel):
today_display, date_start_display, date_end_display = {}, {}, {}
balance_start = self._get_account_initial_balance(
company_id, partner_ids, date_start)
company_id, partner_ids, date_start, account_type)
for partner_id in partner_ids:
balance_start_to_display[partner_id] = {}
@ -362,7 +368,7 @@ class CustomerActivityStatement(models.AbstractModel):
line['balance']
lines = self._get_account_display_lines(
company_id, partner_ids, date_start, date_end)
company_id, partner_ids, date_start, date_end, account_type)
for partner_id in partner_ids:
lines_to_display[partner_id], amount_due[partner_id] = {}, {}
@ -394,7 +400,7 @@ class CustomerActivityStatement(models.AbstractModel):
if data['show_aging_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:
buckets_to_display[partner_id] = {}
for line in buckets[partner_id]:
@ -418,6 +424,7 @@ class CustomerActivityStatement(models.AbstractModel):
'Date_start': date_start_display,
'Date_end': date_end_display,
'Date': today_display,
'account_type': account_type,
}
return self.env['report'].render(
'customer_activity_statement.statement', values=docargs)

10
customer_activity_statement/static/description/index.html

@ -1,7 +1,7 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Customer Activity Statement</h2>
<h2 class="oe_slogan">Partner Activity Statement</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
@ -10,12 +10,12 @@
</div>
<div class="oe_span4">
<p class="oe_mt32"><div style="text-align:justify">The activity statement provides
details of all activity on the customer receivables between two selected dates. This
details of all activity on the receivables or payables of a partner between two selected dates. This
includes all invoices, refunds and payments. Any outstanding balance dated prior to
the chosen statement period will appear as a forward balance at the top of the statement.
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 due, ...),
so the customer can review how much is open, due or overdue.</div></p>
so the customer or vendor can review how much is open, due or overdue.</div></p>
</div>
</div>
</section>
@ -44,8 +44,8 @@ so the customer can review how much is open, due or overdue.</div></p>
<div class="oe_span12">
<p class="oe_mt32">To use this module, you need to:
<ul>
<li>Go to <code>Customers</code> and select one or more</li>
<li>Press '<code>Action > Customer Activity Statement</code>'</li>
<li>Go to <code>Customers</code> or <code>Vendors</code> and select one or more</li>
<li>Press '<code>Action > Partner Activity Statement</code>'</li>
<li>Indicate if you want to display aging buckets</li>
</ul>
</p>

25
customer_activity_statement/static/src/less/layout_statement.less

@ -0,0 +1,25 @@
@odoo-color-silver-darker: #d9d7d7;
@gray-lighter-darker: @odoo-color-silver-darker;
.table-statement {
.amount {
text-align: right !important;
width: 14% //spread 7 columns evenly
}
thead {
border-bottom: solid; // required for clean layout
tr th:first-child {
width: auto !important; // required for clean layout
}
tr th:last-child {
width: 16% !important; // required for boxed layout
}
}
}
.statement-blocked {
background-color: @gray-lighter-darker !important;
td:last-child {
background-color: @gray-lighter-darker !important;
}
}

214
customer_activity_statement/views/statement.xml

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_assets_common" name="oca_statements report assets" inherit_id="report.assets_common">
<xpath expr="." position="inside">
<link href="/customer_activity_statement/static/src/less/layout_statement.less" rel="stylesheet" type="text/less"/>
</xpath>
</template>
<template id="customer_activity_statement.statement_document">
<t t-call="report.external_layout">
<div class="page">
@ -21,160 +27,116 @@
<br/>
<t t-foreach="Lines[o.id]" t-as="currency">
<br t-if="not currency_first" />
<p>
Activity Statement between <span t-esc="Date_start[o.id]" /> and <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
<p >
<span t-esc="'Customer' if account_type == 'receivable' else 'Supplier'"/> Activity Statement between <span t-esc="Date_start[o.id]" /> and <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
</p>
<table class="table table-condensed" style="border: 1px solid black; border-collapse: collapse;">
<table class="table table-condensed table-statement" >
<thead>
<tr>
<th style="border-right: 1px solid black;">Reference number</th>
<th class="text-center" style="border-right: 1px solid black;">Date</th>
<th style="border-right: 1px solid black;">Description</th>
<th class="text-right" style="border-right: 1px solid black;">Amount</th>
<th class="text-right" style="border-right: 1px solid black;">Balance</th>
<th >Reference number</th>
<th >Date</th>
<th >Description</th>
<th class="amount" >Amount</th>
<th class="amount" >Balance</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border-right: 1px solid black;"></td>
<td style="border-right: 1px solid black;">
<td />
<td >
<span t-esc="Date_start[o.id]"/>
</td>
<td style="border-right: 1px solid black;">
<td >
Balance Forward
</td>
<td style="border-right: 1px solid black;"></td>
<td class="text-right" t-if="currency in Balance_forward[o.id]" style="border-right: 1px solid black;">
<span t-esc="Balance_forward[o.id][currency]" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" t-if="currency not in Balance_forward[o.id]" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
<td />
<td class="amount" >
<span t-esc="Balance_forward[o.id].get(currency, 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
<tr t-foreach="Lines[o.id][currency]" t-as="line">
<t t-if="not line['blocked']">
<td style="border-right: 1px solid black;">
<span t-esc="line['move_id']"/>
</td>
<td style="border-right: 1px solid black;">
<span t-esc="line['date']"/>
</td>
<td style="border-right: 1px solid black;">
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] not in line['name']"><span t-esc="line['ref']"/></t>
</t>
</t>
<t t-if="line['name'] == '/'"><span t-esc="line['ref']"/></t>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="line['amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="line['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</t>
<t t-if="line['blocked']">
<td style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['move_id']"/>
</td>
<td style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['date']"/>
</td>
<td style="border-right: 1px solid black; background-color: grey;">
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] not in line['name']"><span t-esc="line['ref']"/></t>
</t>
<tr t-foreach="Lines[o.id][currency]" t-as="line" t-att-class="'statement-blocked' if line['blocked'] else ''">
<td >
<span t-esc="line['move_id']"/>
</td>
<td >
<span t-esc="line['date']"/>
</td>
<td >
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] not in line['name']"><span t-esc="line['ref']"/></t>
</t>
<t t-if="line['name'] == '/'"><span t-esc="line['ref']"/></t>
</td>
<td class="text-right" style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</t>
</t>
<t t-if="line['name'] == '/'"><span t-esc="line['ref']"/></t>
</td>
<td class="amount" >
<span t-esc="line['amount']" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="line['balance']" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
<tr>
<td style="border-right: 1px solid black;"></td>
<td style="border-right: 1px solid black;">
<td />
<td >
<span t-esc="Date_end[o.id]"/>
</td>
<td style="border-right: 1px solid black;">
<td >
Ending Balance
</td>
<td style="border-right: 1px solid black;"></td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Amount_Due[o.id][currency]" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
<td />
<td class="amount" >
<span t-esc="Amount_Due[o.id][currency]" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
</tbody>
</table>
<p>
Aging Report at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
</p>
<table class="table table-condensed" t-if="Show_Buckets" style="border: 1px solid black; border-collapse: collapse;">
<table class="table table-condensed table-statement" t-if="Show_Buckets" >
<thead>
<tr>
<th class="text-center" style="border-right: 1px solid black;">Current Due</th>
<th class="text-center" style="border-right: 1px solid black;">1-30 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">30-60 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">60-90 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">90-120 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">+120 Days Due</th>
<th class="text-right" style="border-right: 1px solid black;">Balance Due</th>
<th class="amount" >Current Due</th>
<th class="amount" >1-30 Days Due</th>
<th class="amount" >30-60 Days Due</th>
<th class="amount" >60-90 Days Due</th>
<th class="amount" >90-120 Days Due</th>
<th class="amount" >+120 Days Due</th>
<th class="amount" >Balance Due</th>
</tr>
</thead>
<tr t-if="currency in Buckets[o.id]">
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['current']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_1_30']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_30_60']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_60_90']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_90_120']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_over_120']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</tr>
<tr t-if="currency not in Buckets[o.id]">
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</tr>
<t t-set="buckets" t-value="Buckets[o.id].get(currency, {})" />
<tbody >
<tr >
<td class="amount" >
<span t-esc="buckets.get('current', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('b_1_30', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('b_30_60', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('b_60_90', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('b_90_120', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('b_over_120', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount" >
<span t-esc="buckets.get('balance', 0.0)" t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
</tbody>
</table>
</t>
</t>
@ -200,7 +162,7 @@
model="res.partner"
report_type="qweb-pdf"
menu="False"
string="Statement Action to PDF"
string="Activity Statement"
name="customer_activity_statement.statement"
file="customer_activity_statement.statement"
/>

4
customer_activity_statement/wizard/customer_activity_statement_wizard.py

@ -31,6 +31,9 @@ class CustomerActivityStatementWizard(models.TransientModel):
)
filter_partners_non_due = fields.Boolean(
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
def button_export_pdf(self):
@ -46,6 +49,7 @@ class CustomerActivityStatementWizard(models.TransientModel):
'partner_ids': self._context['active_ids'],
'show_aging_buckets': self.show_aging_buckets,
'filter_non_due_partners': self.filter_partners_non_due,
'account_type': self.account_type,
}
def _export(self):

11
customer_activity_statement/wizard/customer_activity_statement_wizard.xml

@ -2,7 +2,7 @@
<odoo>
<!-- wizard action on res.partner -->
<act_window id="customer_activity_statement_wizard_action"
name="Customer Activity Statement"
name="Partner Activity Statement"
src_model="res.partner"
res_model="customer.activity.statement.wizard"
view_type="form" view_mode="form"
@ -17,16 +17,21 @@
<form name="Report Options">
<div style="text-align:justify">
<label string="The activity statement provides details of all activity on
the customer receivables between two selected dates. This includes all invoices,
a partner's receivables and payables between two selected dates. This includes all invoices,
refunds and payments. Any outstanding balance dated prior to the chosen statement
period will appear as a forward balance at the top of the statement. The list is
displayed in chronological order and is split by currencies."/><br/><br/>
<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/>
<group name="main_info">
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<group name="account_type">
<label for="account_type"/>
<field name="account_type" nolabel="1" widget="radio"/>
</group>
<group name="dates">
<field name="date_start"/>
<field name="date_end"/>

16
customer_outstanding_statement/README.rst

@ -2,16 +2,16 @@
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
: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
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
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
=============
@ -26,9 +26,9 @@ Usage
To use this module, you need to:
#. Go to Customers and select one or more
#. Press 'Action > Customer Outstanding Statement'
#. Indicate if you want to display aging buckets
#. Go to Customers or 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

4
customer_outstanding_statement/__manifest__.py

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

43
customer_outstanding_statement/report/customer_outstanding_statement.py

@ -47,7 +47,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
""" % (self._get_reconcile_date(), date_end,
self._get_reconcile_date(), date_end)
def _display_lines_sql_q1(self, partners, date_end):
def _display_lines_sql_q1(self, partners, date_end, account_type):
return """
SELECT m.name as move_id, l.partner_id, l.date, l.name,
l.ref, l.blocked, l.currency_id, l.company_id,
@ -87,20 +87,21 @@ class CustomerOutstandingStatement(models.AbstractModel):
ON pr.debit_move_id = l2.id
WHERE l2.date <= '%s'
) 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
Q0.reconciled_date > '%s')
AND l.date <= '%s'
GROUP BY l.partner_id, m.name, l.date, l.date_maturity, l.name,
l.ref, l.blocked, l.currency_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):
return """
SELECT partner_id, currency_id, move_id, date, date_maturity,
debit, credit, name, ref, blocked, company_id,
CASE WHEN currency_id is not null
SELECT Q1.partner_id, Q1.currency_id, Q1.move_id,
Q1.date, Q1.date_maturity, Q1.debit, Q1.credit,
Q1.name, Q1.ref, Q1.blocked, Q1.company_id,
CASE WHEN Q1.currency_id is not null
THEN open_amount_currency
ELSE open_amount
END as open_amount
@ -109,15 +110,18 @@ class CustomerOutstandingStatement(models.AbstractModel):
def _display_lines_sql_q3(self, company_id):
return """
SELECT Q2.partner_id, move_id, date, date_maturity, Q2.name, ref,
debit, credit, debit-credit AS amount, blocked,
COALESCE(Q2.currency_id, c.currency_id) AS currency_id, open_amount
SELECT Q2.partner_id, Q2.move_id, Q2.date, Q2.date_maturity,
Q2.name, Q2.ref, Q2.debit, Q2.credit,
Q2.debit-Q2.credit AS amount, blocked,
COALESCE(Q2.currency_id, c.currency_id) AS currency_id,
Q2.open_amount
FROM Q2
JOIN res_company c ON (c.id = Q2.company_id)
WHERE c.id = %s
""" % 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))
partners = ', '.join([str(i) for i in partner_ids])
date_end = datetime.strptime(
@ -130,7 +134,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
FROM Q3
ORDER BY date, date_maturity, move_id""" % (
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_q3(company_id)))
for row in self.env.cr.dictfetchall():
@ -194,7 +198,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
""" % (self._get_reconcile_date(), date_end,
self._get_reconcile_date(), date_end)
def _show_buckets_sql_q1(self, partners, date_end):
def _show_buckets_sql_q1(self, partners, date_end, account_type):
return """
SELECT l.partner_id, l.currency_id, l.company_id, l.move_id,
CASE WHEN l.balance > 0.0
@ -225,14 +229,14 @@ class CustomerOutstandingStatement(models.AbstractModel):
ON pr.debit_move_id = l2.id
WHERE l2.date <= '%s'
) 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
Q0.reconciled_date > '%s')
AND l.date <= '%s' AND not l.blocked
GROUP BY l.partner_id, l.currency_id, l.date, l.date_maturity,
l.amount_currency, l.balance, l.move_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,
minus_120):
@ -324,7 +328,8 @@ class CustomerOutstandingStatement(models.AbstractModel):
'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))
partners = ', '.join([str(i) for i in partner_ids])
date_end = datetime.strptime(
@ -341,7 +346,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
GROUP BY partner_id, currency_id, current, b_1_30, b_30_60, b_60_90,
b_90_120, b_over_120""" % (
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(
full_dates['date_end'],
full_dates['minus_30'],
@ -359,6 +364,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
company_id = data['company_id']
partner_ids = data['partner_ids']
date_end = data['date_end']
account_type = data['account_type']
today = fields.Date.today()
buckets_to_display = {}
@ -367,7 +373,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
today_display, date_end_display = {}, {}
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:
lines_to_display[partner_id], amount_due[partner_id] = {}, {}
@ -393,7 +399,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
if data['show_aging_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:
buckets_to_display[partner_id] = {}
for line in buckets[partner_id]:
@ -415,6 +421,7 @@ class CustomerOutstandingStatement(models.AbstractModel):
'Filter_non_due_partners': data['filter_non_due_partners'],
'Date_end': date_end_display,
'Date': today_display,
'account_type': account_type,
}
return self.env['report'].render(
'customer_outstanding_statement.statement', values=docargs)

10
customer_outstanding_statement/static/description/index.html

@ -1,7 +1,7 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Customer Outstanding Statement</h2>
<h2 class="oe_slogan">Partner Outstanding Statement</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
@ -10,10 +10,10 @@
</div>
<div class="oe_span4">
<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
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>
</section>
@ -42,8 +42,8 @@ due, ...), so the customer can review how much is open, due or overdue.</div></p
<div class="oe_span12">
<p class="oe_mt32">To use this module, you need to:
<ul>
<li>Go to <code>Customers</code> and select one or more</li>
<li>Press '<code>Action > Customer Outstanding Statement</code>'</li>
<li>Go to <code>Customers</code> or <code>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>
</ul>
</p>

25
customer_outstanding_statement/static/src/less/layout_statement.less

@ -0,0 +1,25 @@
@odoo-color-silver-darker: #d9d7d7;
@gray-lighter-darker: @odoo-color-silver-darker;
.table-statement {
.amount {
text-align: right !important;
width: 14% //spread 7 columns evenly
}
thead {
border-bottom: solid; // required for clean layout
tr th:first-child {
width: auto !important; // required for clean layout
}
tr th:last-child {
width: 16% !important; // required for boxed layout
}
}
}
.statement-blocked {
background-color: @gray-lighter-darker !important;
td:last-child {
background-color: @gray-lighter-darker !important;
}
}

271
customer_outstanding_statement/views/statement.xml

@ -1,180 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_assets_common" name="oca_statements report assets" inherit_id="report.assets_common">
<xpath expr="." position="inside">
<link href="/customer_outstanding_statement/static/src/less/layout_statement.less" rel="stylesheet" type="text/less"/>
</xpath>
</template>
<template id="customer_outstanding_statement.statement_document">
<t t-call="report.external_layout">
<div class="page">
<div class="row">
<div class="col-xs-5 col-xs-offset-7">
<span t-field="o.name"/><br/>
<span t-raw="o.contact_address.replace('\n\n', '\n').replace('\n', '&lt;br&gt;')"/>
<span t-field="o.vat"/>
<div name="statement_address" class="col-xs-5 col-xs-offset-7">
<address t-esc="o"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
<div t-if="o.vat" class="mt16"><t t-esc="o.country_id.vat_label or 'TIN'"/>:
<span t-field="o.vat"/>
</div>
</div>
<h4 style="padding-left:15em;padding-top:2em">
Outstanding Statement
</h4>
<p>
Date: <span t-esc="Date[o.id]" /><br/><!--Today-->
<t t-if="o.ref">Partner ref: <span t-field="o.ref"/></t>
Date: <span t-esc="Date[o.id]"/><br/><!--Today-->
<t t-if="o.ref">Partner ref:<span t-field="o.ref"/></t>
</p>
<t t-if="Lines[o.id]">
<br/>
<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"/>:
<span t-esc="'Customer' if account_type == 'receivable' else 'Supplier'"/>
Outstanding Statement at
<span t-esc="Date_end[o.id]"/>
in <span t-esc="Currencies[o.id][currency].name"/>:
</p>
<table class="table table-condensed" style="border: 1px solid black; border-collapse: collapse;">
<table class="table table-condensed table-statement">
<thead>
<tr>
<th style="border-right: 1px solid black;">Reference number</th>
<th class="text-center" style="border-right: 1px solid black;">Date</th>
<th class="text-center" style="border-right: 1px solid black;">Due Date</th>
<th style="border-right: 1px solid black;">Description</th>
<th class="text-right" style="border-right: 1px solid black;">Original Amount</th>
<th class="text-right" style="border-right: 1px solid black;">Open Amount</th>
<th class="text-right" style="border-right: 1px solid black;">Balance</th>
<th>Reference number</th>
<th>Date</th>
<th>Due Date</th>
<th>Description</th>
<th class="amount">Original Amount</th>
<th class="amount">Open Amount</th>
<th class="amount">Balance</th>
</tr>
</thead>
<tr t-foreach="Lines[o.id][currency]" t-as="line">
<t t-if="not line['blocked']">
<td style="border-right: 1px solid black;">
<span t-esc="line['move_id']"/>
</td>
<td style="border-right: 1px solid black;">
<span t-esc="line['date']"/>
</td>
<td style="border-right: 1px solid black;">
<span t-esc="line['date_maturity']"/>
</td>
<td style="border-right: 1px solid black;">
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] not in line['name']"><span t-esc="line['ref']"/></t>
</t>
<tr t-foreach="Lines[o.id][currency]" t-as="line"
t-att-class="'statement-blocked' if line['blocked'] else ''">
<td>
<span t-esc="line['move_id']"/>
</td>
<td>
<span t-esc="line['date']"/>
</td>
<td>
<span t-esc="line['date_maturity']"/>
</td>
<td>
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']">
<span t-esc="line['name']"/>
</t>
<t t-if="line['name'] == '/'"><span t-esc="line['ref']"/></t>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="line['amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="line['open_amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="line['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</t>
<t t-if="line['blocked']">
<td style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['move_id']"/>
</td>
<td style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['date']"/>
</td>
<td style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['date_maturity']"/>
</td>
<td style="border-right: 1px solid black; background-color: grey;">
<t t-if="line['name'] != '/'">
<t t-if="not line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']"><span t-esc="line['name']"/></t>
<t t-if="line['ref'] not in line['name']"><span t-esc="line['ref']"/></t>
<t t-if="line['ref'] and line['name']">
<t t-if="line['name'] not in line['ref']">
<span t-esc="line['name']"/>
</t>
<t t-if="line['ref'] not in line['name']">
<span t-esc="line['ref']"/>
</t>
</t>
<t t-if="line['name'] == '/'"><span t-esc="line['ref']"/></t>
</td>
<td class="text-right" style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['open_amount']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black; background-color: grey;">
<span t-esc="line['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</t>
</t>
<t t-if="line['name'] == '/'">
<span t-esc="line['ref']"/>
</t>
</td>
<td class="amount">
<span t-esc="line['amount']"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="line['open_amount']"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="line['balance']"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
<tr>
<td style="border-right: 1px solid black;"></td>
<td style="border-right: 1px solid black;">
<td/>
<td>
<span t-esc="Date_end[o.id]"/>
</td>
<td style="border-right: 1px solid black;"></td>
<td style="border-right: 1px solid black;">
<td/>
<td>
Ending Balance
</td>
<td style="border-right: 1px solid black;"></td>
<td style="border-right: 1px solid black;"></td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Amount_Due[o.id][currency]" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
<td/>
<td/>
<td class="amount">
<span t-esc="Amount_Due[o.id][currency]"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
</table>
<p>
Aging Report at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
<p t-if="Show_Buckets">
Aging Report at <span t-esc="Date_end[o.id]"/> in <span t-esc="Currencies[o.id][currency].name"/>:
</p>
<table class="table table-condensed" t-if="Show_Buckets" style="border: 1px solid black; border-collapse: collapse;">
<table class="table table-condensed table-statement" t-if="Show_Buckets">
<thead>
<tr>
<th class="text-center" style="border-right: 1px solid black;">Current Due</th>
<th class="text-center" style="border-right: 1px solid black;">1-30 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">30-60 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">60-90 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">90-120 Days Due</th>
<th class="text-center" style="border-right: 1px solid black;">+120 Days Due</th>
<th class="text-right" style="border-right: 1px solid black;">Balance Due</th>
<th class="amount">Current Due</th>
<th class="amount">1-30 Days</th>
<th class="amount">30-60 Days</th>
<th class="amount">60-90 Days</th>
<th class="amount">90-120 Days</th>
<th class="amount">+120 Days</th>
<th class="amount">Balance Due</th>
</tr>
</thead>
<tr t-if="currency in Buckets[o.id]">
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['current']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_1_30']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_30_60']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_60_90']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_90_120']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['b_over_120']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="Buckets[o.id][currency]['balance']" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</tr>
<tr t-if="currency not in Buckets[o.id]">
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
<td class="text-right" style="border-right: 1px solid black;">
<span t-esc="0.0" t-esc-options='{"widget": "monetary", "display_currency": "currency"}'/>
</td>
</tr>
<t t-set="buckets" t-value="Buckets[o.id].get(currency, {})"/>
<tbody>
<tr>
<td class="amount">
<span t-esc="buckets.get('current', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('b_1_30', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('b_30_60', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('b_60_90', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('b_90_120', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('b_over_120', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
<td class="amount">
<span t-esc="buckets.get('balance', 0.0)"
t-options="{'widget': 'monetary', 'display_currency': currency}"/>
</td>
</tr>
</tbody>
</table>
</t>
</t>
@ -183,7 +164,7 @@
</p>
</div>
</div>
</t>
</t>
</template>
<template id="statement">
@ -197,11 +178,11 @@
</template>
<report id="action_print_customer_outstanding_statement"
model="res.partner"
report_type="qweb-pdf"
menu="False"
string="Statement Action to PDF"
name="customer_outstanding_statement.statement"
file="customer_outstanding_statement.statement"
model="res.partner"
report_type="qweb-pdf"
menu="False"
string="Outstanding Statement"
name="customer_outstanding_statement.statement"
file="customer_outstanding_statement.statement"
/>
</odoo>

4
customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.py

@ -28,6 +28,9 @@ class CustomerOutstandingStatementWizard(models.TransientModel):
)
filter_partners_non_due = fields.Boolean(
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
def button_export_pdf(self):
@ -42,6 +45,7 @@ class CustomerOutstandingStatementWizard(models.TransientModel):
'partner_ids': self._context['active_ids'],
'show_aging_buckets': self.show_aging_buckets,
'filter_non_due_partners': self.filter_partners_non_due,
'account_type': self.account_type,
}
def _export(self):

13
customer_outstanding_statement/wizard/customer_outstanding_statement_wizard.xml

@ -2,7 +2,7 @@
<odoo>
<!-- wizard action on res.partner -->
<act_window id="customer_outstanding_statement_wizard_action"
name="Customer Outstanding Statement"
name="Partner Outstanding Statement"
src_model="res.partner"
res_model="customer.outstanding.statement.wizard"
view_type="form" view_mode="form"
@ -16,16 +16,21 @@
<field name="arch" type="xml">
<form name="Report Options">
<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
split by currencies."/><br/><br/>
<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/>
<group name="main_info">
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<group name="account_type">
<label for="account_type"/>
<field name="account_type" nolabel="1" widget="radio"/>
</group>
<group name="dates">
<field name="date_end"/>
</group>

Loading…
Cancel
Save