Open roxy-dao opened 3 months ago
First of all, report are configurable and sync out to sites, and sites can be on different versions of omSupply (updating all sites is not an easy task). Consider this in the context of the following
For deployment
Standard reports will be moved to omSupply repository and cli can generate one json file containing all reports in a directory, this file is bundled into omSupply application and can also be uploaded to mSupply central to update all reports at once
When omSupply starts (or via cli command), these reports are upserted by the following rules:
found_report = find report with this code
if not found_report {
upsert report
return
}
if found_report.version >= this report.version {
return
}
upsert report
code is a new field that identifies the same report for different versions
version follows omSupply major and minor version, for omSupply to select correct report version for current omSupply instance, and patch identifies any updates to current report version
When omSupply generates report it will select report based on version with the follow rules
After narrowing down on report by context and sub context, and then by code
report_versions = all reports for code
if report_versions have custom reports {
report_versions = only custom reports
}
// Report selection logic will be such to satisfy the following use cases (path version is ignored)
report_version = [2.3.0, 2.3.5, 2.8.2, 2.8.3, 3.0.1, 3.5.1]
if omSupply.version = 2.3 selected report = 2.3.5
if omSupply.version = 2.4 selected report = 2.3.5
if omSupply.version = 2.8 selected report = 2.8.3
if omSupply.version = 3.2 selected report = 3.0.1
if omSupply.version = 4.5 selected report = 3.5.1
This will allow us to update existing report through mSupply without upgrading omSupply, for current and previous versions of omSupply. When omSupply is deployed are remote sites, it's not that easy to update them to later versions, but patching existing versions can be done through mSupply report configurations. Also custom reports would still be used instead of standard reports, where needed.
omSupply report builder cli will be changes to crawl a directory and find all matching manifest.json files, and then generate one json file containing all reports and extra metadata (version, arguments schemas etc), this file will be used to:
Custom report will still live in separate repository (can specify report builder arguments for folder to crawl)
Manifest file updated to:
{
"//": "optional",
"//": "default - false",
"//": "Is it a custom report, custom reports will override non custom reports when report is selected",
"isCustom": false,
"//": "Major and minor should follow omSupply versions, only the latest version will be bundled with omSupply, but previous or future versions may exist in database",
"//": "omSupply will match the version best suited to current omSup version",
"version": "2.1.1",
"//": "Report identifier, will be unique between reports but the same for different report versions",
"code": "item_usage",
"//": "Report context, see server/repository/src/db_diesel/report_row.rs",
"context": "Report",
"//": "Report name as it appears in omSupply UI",
"name": "Report",
"//": "optional",
"//": "Sub context for reports, applicable to Dispensary and Report context, see client/packages/reports/src/ListView/ListView.tsx",
"subContext": "StockAndItems",
"//": "All location/paths relative to manifest.json",
"//": "Location of template file",
"template": "template.html",
"queries": {
"//": "optional",
"//": "Location of gql query file file",
"gql": "query.gql",
"//": "optional",
"//": "Location of sql queries, without extension",
"//": "Each query will consist of one .sql file or two files .sqlite.sql and .postgres.sql",
"//": "In below example 'one' query works for both sqlite and postgres and 'two' has db specific syntax",
"//": "thus three sql files would exist in manifest.json folder 'one.sql', 'two.sqlite.sql' and 'two.postgres.sql'",
"sql": [
"one",
"two"
]
},
"//": "optional",
"arguments": {
"//": "Location of arguments json schema",
"schema": "arguments.json",
"//": "Location of Arguments json forms",
"ui": "arguments_ui.json",
},
"//": "optional",
"//": "Location of header",
"header": "header.html",
"//": "optional",
"//": "Location of footer",
"footer": "footer.html",
"test": {
"//": "optional",
"//": "Location of test arguments",
"arguments": "test_arguments.json",
"//": "Location of test reference data",
"referenceData": "data/reference1",
"//": "optional",
"//": "For report that have dataId, for example requisition or outbound shipment reports",
"dataId": "c92b740c-f271-4af0-be37-fa3068bdb0b2",
}
}
reports
item_usage
shared
one.sql
arguments.json
test_arguments.json
arguments_ui.json
2_3_1
manifest.json
two.postgres.sql
two.sqlite.sql
query.gql
template.html
2_4_3
manifest.json
two.postgres.sql
two.sqlite.sql
query.gql
template.html
With above structure, in manifest.json, locations of arguments and sql one query would have ../shared/
prefix
When report is patched the directory name for the version is updated (as well as version in manifest)
It's quite important to make sure existing reports are not broken by schema or api changes (we are trying to avoid these changes, however there is a small chance this could happen, for example when I did performance improvements for program work I moved some nodes to loaders, and from UI perspective everything was fine but it did break custom reports)
Currently we tests reports against a running omSupply version, for report unit tests we would need to have a data set that checks all of the query and template paths, thus using reference data and combining report builder and remote service cli (which allows us to upsert referenceData) would help with automating report tests for standard and custom reports (referenceData for custom reports will be located in custom report repo).
Unit tests should be created in such a way as to combine report tests that use the same reference file.
It's quite convenient to have print, show and upsert scripts when working with existing reports, these can be built into cli, we would need to specify the location of the report or report code to run with the cli. Cli can connect to current database and access service methods to print/show report. There would already exist a method to upsert report in case it needs to be checked via omSupply app UI.
When updating existing reports via patch, we would need to let support team know, generated reports would be committed to the repo (to omSupply repo for standard reports, and client specific json files in custom report repository), so they can be used by the build process and by support team to update existing reports in mSupply. We need to flag a support task for updating these reports.
Patches to previous versions should be done and tested on previous versions of omSupply (not in develop, but develop updated after)
We would need a way to import all reports to mSupply at once (here is mSupply issue)
This scripts should not touch or update reports that have not changed, and delete previous patch versions (to reduce sync traffic)
Since versioning is a foreign concept to existing omSupply, we would need to differentiate between versioned report and not versioned. This would require adding a new report 'type' (editor field in mSupply). We would also need to make sure that custom reports are re imported into mSupply for countries that will be updating to versioned report version of omSupply
mSupply - report table
in mSupply we would need to update the report UI to have this new type (maybe have one import script that populates all fields in that UI, we can import json with one report via this UI)
omSupply
In version upgrade we would remove existing reports, and mark reports in sync buffer to be re-integrated Report translator will only integrate "omsupply_versioned" type/editor reports
We might not want to bundle all the previous report version, but probably want to supply one json file to support with all of the versions, may need a parameter for bundle json (with latest) and for all report version json, and have a way to share the former with support
@andreievg as discussed, I think we could consider moving these versioned reports to open-mSupply Central.
Advantages
Disadvantages
I think the general plan for versioning looks good though! I like tying the compatibility to OMS Version.
There is an issue when a change is made that breaks an older version, e.g. removing a field in graphql (similar to loaders one) We can't tag the old version as incompatible and we'll have to be vigilant to upgrade. I think for standard reports, we should be ok as we'll be testing, but I think there's risk of breaking custom reports unexpectedly.
I haven't thought of any magic solutions for this, I guess we could try to add a test function to production for all custom reports?
That all looks great - thanks for the thought gone into the versioning and management of reports, that's super helpful
I agree with @jmbrunskill - would be good to take this opportunity and remove the OG dependency, and shift report admin to oms central server.
Custom reports are still a little tricky to manage compatibility and versioning; happy to keep that as a manual task. there's low likelihood of it happening and we can isolate a manual test task to specific clients prior to upgrading. It's a little tedious so it's worth investigating later if we can automate the testing of custom reports.
Add header with logo to all standard/general reports and make sure existing standard report (like requisition) works with the logo set on store
Make sure all standard reports and printouts are included in the bundling process (not just general reports)
In order of priority:
---- Future works ---
untriaged issues:
Apart from this we would want to add more internal docs about report creation (how to make report compliant with our excel export logic, etc..)