GithubHelp home page GithubHelp logo

msupply-foundation / excel-report-email-scheduler Goto Github PK

View Code? Open in Web Editor NEW
6.0 6.0 3.0 20.76 MB

The plugin takes data from panels of mSupply dashboard to generate excel reports which are then emailed to a custom user group created with mSupply users pulled from mSupply Dashboard's datasource. The timing of the scheduler can be set in the plugin.

License: Apache License 2.0

JavaScript 5.86% Go 48.37% TypeScript 45.58% Dockerfile 0.19%
app golang grafana plugin react

excel-report-email-scheduler's People

Contributors

anildahalsussol avatar josh-griffin avatar mark-prins avatar sworup avatar wlthomson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

excel-report-email-scheduler's Issues

Report Template

Create a report template which will be filled with data during report generation

Signing issues

Having some troubles signing and building the frontend app

Handle custom variables

Some variables in grafana can be custom, so you have a query which is like:

select * from item_line where ven_category in (${VEN})

Where VEN is a variable with the options defined as V,E,N. Then when viewing a dashboard, there is a drop down to select which character. This character then transforms the query to be:

select * from item_line where ven_category in ('V')

There can be multi-select or non-multi select custom variables.

The Variable definition object you get from grafana looks roughly like:

{
    query: 'V,E,N'
    options: [{selected: true, text: "V", value: "V"}, .. {selected: false, text: "N", value: "N"}]
    name: "VEN"
    label: "VEN"
    multi: true
    includeAll: false // this will give an "ALL" option - setting "V", "E", "N" to true.
}

Grafana takes this definition and creates a drop down which then also enables transforms on the query, according to the format provided. I.e.: ${VEN:sqlstring} transforms it to be "V", "E", "N" where as ${VEN} will transform it to be: V,E,N


Solution:

For each panel, iterate through the variables for the panels dashboard, and determine if the variable is used within the sql. If it is, generate and display the drop down to choose the variable to use. Save this in the msupply sqlite and use it for generating reports.

Saving: Saving it as a JSON stringified object ๐Ÿ˜ข in ReportContent (A 'panel' record) - because each panel can have multiple variables, and multiple values for each variable:

{
  VEN: ["V", "E"]
  status: ["fn"]
}

Even if they're not multi-selectable, store in an array.

Limitations:

  • There are other variable types other than custom. Also other formatting types. JUST going to implement custom, sqlstring formatted.
  • The reporter won't be able to keep in sync well enough - i.e. if you set up variables for a panel, then go edit those variables.. ๐Ÿคท But this is pretty same same, i.e. if you set up panels and then go delete panels.. ๐Ÿคท

Report Groups: a couple of bugs to show users

  1. User filter does not work properly. It shows other names not including letters from the input box.
  2. Group should not be included in this list.

dashboard_bug

dashboard_bug2

  1. Only user names with active = true in the mSupply user table should show in the list. Currently, there are many duplications in the list if there are the same user names in mSupply.

Screen Shot 2022-03-03 at 4 01 33 PM

dashboard_bug3

Emailing not working

C:\\Program Files\\mSupply Dashboard\\bin\\data\\template.xlsx: The system cannot find the path specified.

The revert of homePath, _ := filepath.Abs(".") might not have been done properly ๐Ÿ™„

Excel formatting

A request to improve the formatting of the spreadsheet

  • column widths should be relevant to content
  • dates should be formatted as dates

other suggestions? @joshxg @craigdrown

Permission error in Edit Report Schedule when user role is not Admin

When user open the report group page and the report schedule page, it shows permission error and does not show available panels if user's role is not admin.

permission

To access to the path api/datasources/XXXX seems denied to viewer.

Screen Shot 2021-12-08 at 2 05 50 PM

Screen Shot 2021-12-08 at 2 05 57 PM

However, admin user can access the same page properly.

Screen Shot 2021-12-08 at 2 12 55 PM

I assume that it's because Grafana organization roles restrict editors and viewers to access to data sources.

Action Admin Editor Viewer
View dashboards x x x
Add, edit, delete dashboards x x
Add, edit, delete folders x x
View playlists x x x
Create, update, delete playlists x x
Access Explore x x
Add, edit, delete data sources x ย 
Add and edit users x ย 
Add and edit teams x ย 
Change organizations settings x ย 
Change team settings x ย 
Configure app plugins x

If user can not access to the report schedule page because of permissions, it would be better restrict menu icon visibility itself?
https://github.com/openmsupply/msupply-dashboard-app/blob/3be59cd164d659ef04dddb78a80ce2b07d4fe07f/frontend/src/plugin.json#L31-L48

Additional info

Also one thing works different from above is report group page.
Even with viewer user, the list of users shows and we can save it.

Version

Grafana version 7.3.0

Right align numbers in spreadsheet

When populating data in the sheet, determine if a value is numeric. If it is, right align it.

Perhaps have this as a configuration option too?

handle refreshing variables

Currently when a variable is set to refresh as anything but "never", the "options" field is not populated. This field holds an array of the options available in the drop down.

Would need to query for and map the options on loading the panels.

Error building on windows x86_64

When trying to build the backend code on Windows, getting the following error:

$ go run mage.go 
# github.com/grafana/grafana-plugin-sdk-go/build
..\..\..\..\go\pkg\mod\github.com\grafana\[email protected]\build\common.go:91:10: undefined: syscall.Kill
Error: error compiling magefiles
exit status 1

OS: Microsoft Windows 10 Pro.
Version: 10.0.18362 Build 18362.
Architecture: x86_64.

Exact time of day and better intervals between reports being sent

Should change the implementation to send, for example, everyday at 7am.

Current implementation is set to daily, weekly, 30 days (monthly) etc is just the interval being the number of seconds in that duration. Then the initial "nextReportTime" is set to 0. Every 10 mins the scheduler checks if the current time is greater than any nextReportTime, if there is, sends that scheduled report and increments the nextReportTime by the unix timestamp in interval.

Need to : Change UI to select an interval: Daily, Weekly, Monthly etc and also a time of day: 7am, 8am etc. and possibly, if it's weekly: What day of the week, if its monthly, what day of the month (Or potentially also "last day of month", "first of the month" etc??)

Not sure exactly what to do as there is quite a lot there. I suppose you would treat them all seperately, and have an initial step: Daily, Weekly, Monthly, then if it's daily: Time of day, otherwise weekly: Number of weeks (to handle fortnightly), day of week, then time of day. Then for monthly, number of months, day of week, time of day?

If it was done like this, I suppose you could map this into a cron scheduler string and then just start a cron job for each schedule.. but I'm not convinced this is a good idea, i'd rather save an exact time of the next report in a persistent db and check against that and increment, I think it seems safer! But determining a way to do that with these changes is more difficult, so I dunno.

Export to excel

Add the option to export a table directly to excel and then download the result.
To be used with the msupply-table plugin

Getting plugin not found error

Details

t=2022-03-08T23:52:22+1300 lvl=eror msg="Could not start plugin" logger=plugin.manager pluginId=msupplyfoundation-datasource err="Unrecognized remote plugin message: 2022/03/08 23:52:22 notifying bugsnag: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub\n\nThis usually means that the plugin is either invalid or simply needs to be recompiled to support the latest protocol."

In mac grafana tries to use the ARM version of the executable which also breaks saying could not find file.

I did recompiled the app in my m1 mac system but it was broken before I tinkered. I forgot to take the error log entry though.

Definitely getting this error because Grafana for some reasons cannot run the backend executable.

Downloadable default template

Add a feature to download the default template from some API so we don't have to change the default on every instance

Test button sends incorrect report

Clicking the SEND TEST button always send the first schedule in the list and not the current schedule.

The front end is sending the correct schedule ID and this is parsed correctly in testEmail - but the schedule instantiated is always the first one.

More logging

Need to add some more logging for in correct reports being generated as 0kb files

Error if invalid character in password

Configured an instance where the user password has a % in the password and the following shows in the logs:

lvl=eror msg="GetEmails: http.Post: parse \"https://[redacted]/api/tsdb/query\": invalid URL escape \"%[some other chars]\"" logger=plugins.backend pluginId=msupplyfoundation-datasource

lvl=eror msg="ReportEmailer.createReport: emailsFromUsers: parse \"https://[redacted]/api/tsdb/query\": invalid URL escape \"%[some other chars]\"" logger=plugins.backend pluginId=msupplyfoundation-datasource

Docs

Need these docs:

  • supported variables
  • supported macros
  • template requirements
  • examples
  • email requirements (smtp)
  • sqlite schema

Properly run the schedule

Currently when the plugin boots it tries to send emails, and the scheduler isn't properly running.

Instead: Try send emails instantly, but also start the scheduler

installer

need to add this app to the msupply-grafana fork installer?

Report Groups: a couple of feature request to show users

Currently, it is a little bit difficult to find users if there are many users on the list.
So this change would be helpful.

  • To show the list in alphabetical order. Currently, it seems not to line up in order.
  • To show only users who have an email address in mSupply.
    dashboard_feature

Query variable replacement

In a query there are sometimes variables.

i.e. [store] or time macros $timeFilter(..

For variables: These are replaced by sub queries within the dashboard definition.

For example:

Select store.name as \"Store\",
 item_department.department as \"Program\",
 item_name as \"Item Name\",
 unit.units as \"Units\",
 pack_size as \"Pack Size\", 
 available as \"Packs Available\",
 pack_size*available as \"units left\",
 batch as \"Batch No.\",
 to_char(expiry_date, 'YYYY/MM/DD') as \"Expiry Date\",
 location.code as \"Location\"
 from item_line join item on item.id = item_line.item_ID
 join store on store.id = item_line.store_ID
 join unit on item.unit_id = unit.id
 join item_department on item.department_ID = item_department.ID
 join location on location.id = item_line.location_ID
 where expiry_date > now() + interval '($monthsFrom) months'
 and expiry_date < now() + interval '($monthsTo) months'
 and available > 0
 and store.name in ([[store]]) 
 and item.item_name in ([[item]])
 and item_department.department in ([[department]])
 order by 1, 2"

The above query has variables and macros.

Variables are for example ([[store]]). This needs to be replaced with the sub query which is in the dashboard definition where the panel lives:

The dashboard has a templating field which has a list of variable objects like:

{
	"0": {
		"allValue": null,
		"current": {
			"selected": true,
			"text": "Caldwell",
			"value": [
				"Caldwell"
			]
		},
		"datasource": "PostgreSQL",
		"definition": "select distinct name from store where disabled=false and store_mode in ('store', 'dispensary');",
		"hide": 0,
		"includeAll": true,
		"label": "Store",
		"multi": true,
		"name": "store",
		"options": [],
		"query": "select distinct name from store where disabled=false and store_mode in ('store', 'dispensary');",
		"refresh": 1,
		"regex": "",
		"skipUrlSync": false,
		"sort": 0,
		"tagValuesQuery": "",
		"tags": [],
		"tagsQuery": "",
		"type": "query",
		"useTags": false
	}
}

So, for variables: Replace the ([[store]]) with the query field.

For macros as above there is interval '($monthsFrom) months' and interval '($monthsTo) months'

In the request body of the POST for executing the query, there are two fields from and to which seem to be used for these macros.

More defensive code

Need to add a bit more defensive code to give more insight into errors as well as stopping the app completely crashing when the db can't be opened

datasource id changes

Whenever the grafana server changes the postgres datasource ID increments.

I.e. it is set to 10 - reset server, goes to 11.

Ugh.

Could do something like using the default datasource, probably?

Create initial scheduler

Create a simple scheduler and outlining structure of a scheduler to generate reports with a static interval

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.