[IMP] Extend customer_outstanding_statement to display also payables
parent
ebdb5adbc0
commit
209a424161
|
@ -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
|
#. Go to Invoicing > Sales > Master Data > Customers or or Invoicing > Purchases > Master Data > Vendors and select one or more
|
||||||
#. Press 'Action > Customer Outstanding Statement'
|
#. Press 'Action > Partner Outstanding Statement'
|
||||||
#. Indicate if you want to display aging buckets
|
#. 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,
|
* In v12, the module should be renamed to `Partner Outstanding Statement`.
|
||||||
at a specific date.
|
Maybe merge this module with the `Partner Activity Statement` module.
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -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',
|
'name': 'Partner Outstanding Statement',
|
||||||
'version': '11.0.1.0.0',
|
'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)",
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>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 > Customer Outstanding Statement</code>'</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>
|
||||||
|
|
|
@ -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>
|
<p t-if="account_type == 'receivable'">
|
||||||
Outstanding Statement at <span t-esc="Date_end[o.id]" /> in <span t-esc="Currencies[o.id][currency].name"/>:
|
+ 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>
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
<label string="The outstanding statement provides details of all partner's outstanding
|
||||||
customer receivables up to a particular date. This includes all unpaid invoices, unclaimed
|
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…
Reference in New Issue