Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reporting feature #5155

Merged
merged 22 commits into from Jul 24, 2023
Merged

Conversation

NicolasDorier
Copy link
Member

@NicolasDorier NicolasDorier commented Jul 5, 2023

Features

  • Export to CSV. This can be easily interpreted by excel or google sheet for more complex use cases.
  • Some cells are links to easily navigate to details (a transaction on the blockchain explorer or an invoice for now)
  • Extendable by plugins
  • Sorting on all columns
  • Payments report
  • On-chain wallets report
  • Date inputs and outputs using the browser's timezone.
  • Filters
  • Basic grouping features, so user doesn't have to use excel to see some aggregates (like the total of payments in a month)
  • Brush up by @dennisreimann and @dstrukt
  • Tests

Out of scope

While the Greenfield route has been done, I think we should disable it for now, as we are still unsure of proper API design.

Additional reports will be in different PRs after we could validate the design of this PR.

To do later

  • Report for Off-Chain payments (will need to have date base filtering of invoices on lightning library)
  • Point of Sale/Crowdfunding stats on items sold (see Articles report / Payments report #4598)
  • Refund reports
  • Payouts reports

UX

This add a new page at store level: Reporting:

image

When clicking on it, a new page open

image

Note on the UX: The hard part is that the designer is unable to predict how many columns will be there. That said, cell content can be customized depending on the type of the column.

Implementation details

Backend

A new class ReportService is exposing report related methods.
A base class ReportProvider can be subclassed to implement new types of reports.
At the moment, only two implementations exists PaymentsReportProvider and OnChainWalletsReportProvider, but many more will come for next major release.

Front end

I am using VueJs, the whole page is coded as a single page application.

Linked discussions

#5095
#937
#2561
#2601
#4598

@NicolasDorier NicolasDorier marked this pull request as draft July 5, 2023 11:41
@@ -33,6 +33,8 @@
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.21" />
<PackageReference Include="NBitcoin" Version="7.0.24" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NodaTime" Version="3.1.9" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a whole new library on the client library level?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to remove it, we dont

}
};

$(function () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reduce jquery usage:

Suggested change
$(function () {
document.addEventListener("DOMContentLoaded", () => {

};

$(function () {
$(".flatdtpicker").on("input", function () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$(".flatdtpicker").on("input", function () {
document.querySelectorAll('.flatdtpicker').forEach(el => el.addEventListener("input", ()=>{

$(function () {
$(".flatdtpicker").on("input", function () {
// We don't use vue to bind dates, because VueJS break the flatpickr as soon as binding occurs.
var to = $("#toDate").val();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var to = $("#toDate").val();
const to = document.querySelector("#toDate").value

@NicolasDorier
Copy link
Member Author

What is the problem with jquery?

@NicolasDorier
Copy link
Member Author

@dstrukt @dennisreimann I just added a commit to generate fake data in the reporting.

  • When chosing a new view, I believe it is better to not show the raw data upfront unlike I am doing now. Reasons are:
    • For 10000 rows, the UI seems to be slow to render for some reason. (Probably something that can be fixed)
    • Few people would want to see the raw data, in general I expect they are more interested in the aggregates.
    • The raw data having many column, it can't look nice

@pavlenex pavlenex linked an issue Jul 11, 2023 that may be closed by this pull request
@dennisreimann
Copy link
Member

UX: This add a new page at store level: Reporting

I think we could either put it up between Dashboard and Settings or at the end of the Payments section. Regardless of where we position it, we need a new icon for this feature :) @dstrukt

@dennisreimann
Copy link
Member

dennisreimann commented Jul 11, 2023

Introduced a fixed header and made the tables auto-width, so that they read a bit better. Will experiment with sticky table header rows next.

Peek 2023-07-11 18-36

@NicolasDorier
Copy link
Member Author

The make me more happy

// filter(){ return filter1 && filter2 && filter3; }
var newData = [];
var o = {};
eval('function filter() {return ' + filterStrings.join(' && ') + ';}');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes 😬

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The basic idea is that the report provider can decide to filter rows before building the table.
I use it for the summary of lightning addresses payments. Without this, the datatable would show a row with empty ligthning address if none are present. Instead, I want this line to be gone.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the conversion from tabular data to a representation bindable to VueJS for summary tables is done JS side.
I am unsure this is good idea, I believe we could just do that C# side.

It would also make it easier to test.

@dstrukt dstrukt self-requested a review July 17, 2023 19:55
Copy link
Member

@dstrukt dstrukt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few initial thoughts after reviewing, some might be out of scope, others are minor nits and suggestions:

Happy to make some of these changes post-merge as well, if it makes more sense.

Search

  • Do we want the ability to search? e.g. something like this:
  • Calendar icons to the left of the inputs for the date selection could be nice too
Screen Shot 2023-07-17 at 3 02 49 PM

Balance Tables

  • Any reason we don't want to conserve a bit of space by doing two columns like so. Am I missing something? Might be nice to consolidate in the future, but for the time being.
Screen Shot 2023-07-17 at 1 49 54 PM

Payments

  • Could be improved with updated labels:
Screen Shot 2023-07-17 at 2 29 22 PM
  • Lightning Address label updates
  • Makes me think some of the other Amount labels could be Balance instead...hmm
Screen Shot 2023-07-17 at 3 51 15 PM

On-Chain

  • Could be improved with updating the label and pushing the header into the table key value for the on-chain view:
  • Context: I found the Balance Change aspect of the On-Chain table a little confusing... as the test data amounts were mostly negative values?
Screen Shot 2023-07-17 at 3 00 53 PM
  • Still exploring ways of consolidating the tables for more space and ease of parsing the data, just sharing, might be a later follow up if any of the explorations make sense:
Screen Shot 2023-07-17 at 4 18 18 PM

e.g: On-Chain/Lightning, doesn't hold up as well, but interesting nonetheless:
Screen Shot 2023-07-17 at 5 56 21 PM

works in a simple context as well:
Screen Shot 2023-07-17 at 6 27 36 PM

Products

  • Summary by items -> Summary Could this label just be shortened, and still make sense?
  • Should it be App ID or the App/Plugin Name? Or perhaps both?

Raw Data

Payments

  • Is the date formatting messed up? 2023-07-05T01:42:41-06:00
Screen Shot 2023-07-17 at 3 34 10 PM

On-Chain

  • Suggestions for improvements
  • Unconfirmed would be a red X icon instead of the green checkmark
  • Balance Change decrease would be -1.06150021 and be colored red
Screen Shot 2023-07-17 at 3 41 50 PM

Filter Dropdown

  • Copy suggestion: Items sold -> Products or Products Sold? To keep it consistent with the POS label
  • Copy suggestion: On-Chain Wallets -> On-Chain or Wallets? On second thought, might be fine with the original..
Screen Shot 2023-07-17 at 1 37 15 PM

General

  • I noticed there's an additional scrollbar at the bottom of the page, can we remove this? I think the table specific scrollbar makes sense, given the width of it's contents.
Screen Shot 2023-07-17 at 1 34 33 PM
  • The main CTA could arguably just be Export cleaner, as the CSV bit isn't necessary imo
Screen Shot 2023-07-17 at 2 14 43 PM

Really great work!

@NicolasDorier
Copy link
Member Author

About wallet balance confirmed/unconfirmed: I don't believe a bar make sense. In most case, unconfirmed will be ridiculously low compared to confirmed, so this doesn't add lot's of information.

For on-chain versus lightning, it might make more sense.

Also, I was thinking: Some tables are grouping on Invoice currency. I believe this is overkill, as most of the time, the invoice currency is the same.

Rather than grouping per currency, I will just make additional chart per currency?

@NicolasDorier
Copy link
Member Author

@dstrukt I want to add, the aggregated tables I am showing could potentially be replaced by any chart that make sense.

values.Add((string)r.order_id);
if (PaymentMethodId.TryParse((string)r.payment_type, out var paymentType))
{
if (paymentType.PaymentType == PaymentTypes.LightningLike || paymentType.PaymentType == PaymentTypes.LNURLPay)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the payment type tostring instead of hardcoding

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this because because the difference between lightning versus LNURL doesn't matter at all for merchants.

They want the consolidated view of how much they received on lightning, they don't care whether it come from LNURL or not, so we need to map them to the same value.

Copy link
Member

@Kukks Kukks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing api docs and tests! 😂

@NicolasDorier
Copy link
Member Author

Missing tests, will do. For the API, I will remove it from this PR, exposing it as a NonAction.

@dstrukt
Copy link
Member

dstrukt commented Jul 18, 2023

About wallet balance confirmed/unconfirmed: I don't believe a bar make sense. In most case, unconfirmed will be ridiculously low compared to confirmed, so this doesn't add lot's of information.

Tend to agree, it's a bit much for what would only be a pending state at best, and rarely visible for instances with low volume.

For on-chain versus lightning, it might make more sense.

Also agree, but wasn't intended to be included in this PR, just a quick visual exploration to see if it made sense / worth the time to implement!

Also, I was thinking: Some tables are grouping on Invoice currency. I believe this is overkill, as most of the time, the invoice currency is the same.

Rather than grouping per currency, I will just make additional chart per currency?

That could work, I do appreciate the flexibility/clarity of the current implementation, but I think I'd have to see it.

@pavlenex
Copy link
Contributor

@NicolasDorier Any chance fake data can generate items for POS? I think this is one of the highest-requested reports, so would be good to test it out.

@dstrukt
Copy link
Member

dstrukt commented Jul 19, 2023

ACK to fake data, if possible! Was my biggest challenge in providing more feedback as well.

@NicolasDorier
Copy link
Member Author

@dstrukt @pavlenex done

@dstrukt dstrukt self-requested a review July 20, 2023 22:16
@pavlenex
Copy link
Contributor

@NicolasDorier I've tested draft a bit, so far so good.
Question, is export always meant to give raw data, not data according to tables?
When do you plan to add fitlers and groups?
When do you think you'll be able to get this one out of draft?

We're thinking of RC for Monday, but unsure how much you have to do on this one.

Copy link
Member

@dstrukt dstrukt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, looks really solid, there's some more finessing of labels and UI I'd like to do, but I don't want to hold up the release to make these minor tweaks.

Especially if our RC deadline is monday, this is something @dennisreimann and I could easily do a follow up PR to address.

@NicolasDorier NicolasDorier marked this pull request as ready for review July 24, 2023 00:24
@NicolasDorier
Copy link
Member Author

it's bit tight, so let's merge this one and incrementally improve on dstrukt feedback

@NicolasDorier NicolasDorier merged commit dc98695 into btcpayserver:master Jul 24, 2023
4 checks passed
@NicolasDorier NicolasDorier deleted the qitntqbe branch July 24, 2023 00:24
@NicolasDorier
Copy link
Member Author

is export always meant to give raw data, not data according to tables?`

@pavlenex I don't know what you mean, but the CSV export is exporting the raw data, because all other structures can be trivially created again through Excel. The idea is to provide just enough feature to be useful for simple cases, delegating complex cases to Excel.

Filtering for now is only on date, I believe allowing some simple client side filters on the raw data.
We can do that in minor release or major release later.

About Grouping: The summary tables that you see is grouping. If what you want is letting the user drag and drop components to make their own group, I wished to do that but the existing open source components for pivot table just sucks and aren't maintained anymore.

@dstrukt
Copy link
Member

dstrukt commented Jul 24, 2023

it's bit tight, so let's merge this one and incrementally improve on dstrukt feedback

Sounds good - will make an issue with some of the remaining items post-release. Great work!

@JamesMessick1965
Copy link

Good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve invoice reporting
6 participants