Customer Statement

Hi @hifyaan,

have you considered adding a custom print format to the customer record? This way you can aggregate the data from this customer and get a statement of account. Something like this

 {% set unpaid_sales_invoices = frappe.get_all('Sales Invoice', filters={'docstatus': 1, 'customer':}, fields=['name', 'outstanding_amount', 'posting_date', 'due_date', 'rounded_total', 'grand_total' ]) %} 

<!-- positions -->
<p><br /></p>
<table style="width: 100%;">
  <tr style="border-bottom: 1px solid silver;">
	<td style="width: 18%; "><strong>{{ _("Document number") }}</strong></td>
	<td style="width: 15%; "><strong>{{ _("Date") }}</strong></td>
	<td style="width: 17%; "><strong>{{ _("Text") }}</strong></td>
	<td style="width: 12%; text-align: right; "><strong>{{ _("Amount") }}</strong></td>
	<td style="width: 13%; text-align: right; "><strong>{{ _("Due till") }}</strong></td>
	<td style="width: 12%; text-align: right; "><strong>{{ _("Reminder") }}</strong></td>
	<td style="width: 13%; text-align: right; "><strong>{{ _("Outstanding") }}</strong></td>
 {% set now = %}
 {% set vars = {'sum': 0} %}
 {% for sales_invoice in unpaid_sales_invoices %}
   {% if sales_invoice.outstanding_amount %}
	 <tr style="border-top: 1px solid silver; ">
	   <td>{{ }}</td>
	   <td>{{ frappe.format_value(sales_invoice.posting_date, {'fieldtype': 'Date'}) }}</td>
	   <td>{{ _("Sales Invoice") }}</td>
	   <td style="text-align: right; ">{{ "{:,.2f}".format(sales_invoice.grand_total).replace(",", "'").replace(".", ",").replace("'", ".") }}</td>
	   <td style="text-align: right; ">{{ frappe.format_value(sales_invoice.due_date, {'fieldtype': 'Date'}) }}</td>
	   {% set age = frappe.utils.date_diff(now, sales_invoice.due_date) %}
	   <td style="text-align: right; ">
		 {% if age > 60 %}3{% elif age > 30 %}2{% elif age > 0 %}1{% else %}0{% endif %}</td>
	   <td style="text-align: right; ">{{ "{:,.2f}".format(sales_invoice.outstanding_amount).replace(",", "'").replace(".", ",").replace("'", ".") }}</td>
	   {% if vars.update({'sum': vars.sum + sales_invoice.outstanding_amount}) %}{% endif %}
  {% endif %}
{% endfor %}
	 <tr style="border-top: 1px solid silver; ">
	   <td colspan=5><strong>{{ _("Balance") }}</strong></td>
	   <td colspan=2 style="text-align: right; "><strong>EUR {{ "{:,.2f}".format(vars.sum).replace(",", "'").replace(".", ",").replace("'", ".") }}</strong></td>

Hope this helps.


Good Day

Hope this could help someone:

Hope someone could implement this into ERPNext.

Thank You

Albertus Geyser

I think the point here is that it should be standard in any ERP software and your workaround may be fine for one individual customer statement. The issue is when you need to run customer statements at the end/beginning of every month for ALL customers at one time. Ideally, there would be a Customer Statements module and you’d click to email/print customer statements to everyone at the same time.


Why do you consider this a workaround? This is actually a neat solution to generate statements of account from the customer (or supplier). It also works on a range/selection of customers, simply filter your list for the ones with outstanding_balance > 0, select all and click print…

If you need this in bulk, the use case might be different. For example payment reminders. But that then is not only a statement of account, but also includes payment reminder levels and charges. A module for that is available (not in the core though)…

Ahh… that’s a good idea to filter and the select multiple. I was thinking v10, which would not have allowed the multiple selection with as many options. I will give this a shot.

What about emailing the customer statements? I’m assuming this will only email to the primary contact on the account? We need to email to the Accounts Payable contact.

Thank you!

How do we add Logo at the top ?

Where do we add start and end dates ? Do we have to change data in the code for this ?

It is a normal print format, you can include for example a normal letter head to have your logo and header printed:

<!-- HEAD -->
<div id="header-html" class="hidden-pdf">
  {% set letter_head = frappe.get_doc("Letter Head", "Standard") %}
  {% if letter_head %}
    {{ letter_head.content }}
  {% else %}
    <p>Letter head Standard not found. Please define the letter head under print settings.</p>
  {% endif %}

In this form it is not date-drive, it will shown all sales invoices based on outstanding_amount. If you want this based on a time period, you will have to change the lookup code, e.g. like this (current year):

 {% set year =[0:4] | int %}
 {% set sales_invoices = frappe.get_all('Sales Invoice', 
  filters=[['docstatus', '=', 1], 
  ['customer', '=',],
  ['posting_date', '>=', "{0}-01-01".format(year)],
  ['posting_date', '<', "{0}-01-01".format(year + 1)]], 
  fields=['name', 'outstanding_amount', 'posting_date', 'due_date', 'rounded_total', 'grand_total' ]) %}

Good Day

We using my Jasper Reports Statement and must say a nice alternative for nothing else.
In my report you select first day of month and will calculate last day of month and then you select customer and will generate your statement ready to send out as pdf with links on document number to open actual document on ERPNext.

I agree that this should be standard on ERPNext.

This is Elegant and Beautiful.

Works as advertised

Thanks @lasalesi

1 Like

sorry was out of town for some time
i had a look at this it looks good …but its only for outstanding inv the wau i see it
a statements should run from month to month like how albertus has shown
or maybe i have missed something
the second one that is date driven i get an error
expected name name tag but got something else
i must gave done something wrong


Just to note: you can’t select multiple and email it automatically to the contact on file. You still have a lot of manual steps to use this if you plan on emailing your statements rather than print and send via mail.

am i missing something but is there still no customer statements build into erp next
just dumb struck at this
can anyone shed some light on this
oh not any work arounds just old plain fashioned statements
which is so vital to any business
this was a comment from jaichavan " Hello,
We will evaluate the request and see how it can be implemented in the future versions.
We appreciate your patience and cooperation. Thanks." when nov 2018
one year ago
one year later niks nada nothing

1 Like

I posted a solution for this a few days ago.

Please wait a day or two before evaulating. There was a bug in calculating the balance in the general ledger report from which this was based introduced by the update_payment_reference() function call. I just corrected the bug in my statement solution and I am busy testing.

The bug fix been applied and is available on the Client Statements branch.

I would really like to see this basic feature too.

The solution posted above seems to be developed for server side scripting. Is there a client side solution?

The Jinja solution, altough being server-sided, can be configured in the print format… Or is there a specific reason for a client-side solution?

1 Like

Client side because prefer to use hosted

This solution is based on a custom print format, which can be implemented on hosted instances without any issue:

1 Like

I am getting this same error message :upside_down_face: