ima-worldhealth / bhima Goto Github PK
View Code? Open in Web Editor NEWA hospital information management application for rural Congolese hospitals
License: GNU General Public License v2.0
A hospital information management application for rural Congolese hospitals
License: GNU General Public License v2.0
API should provide
This API will drive the management pages required for administering locations as well as provide data the for the location select directive and any modules that requires locations.
There are two exchange rate modules, ExchangeService
and ExchangeRateService
. ExchangeService continues to require a daily rate and has an impossible API. Earlier last year, it was rewritten as ExchangeRateService
. As part of the bhima-2.X milestone, we should establish a goal to completely remove ExchangeService
in favor of the ExchangeRateService
.
Angular 1.5 was just released. The most significant advantage is first-class support for angular.component()
which we should seriously consider implementing anywhere we would use a directive (and potentially re-writing some of our old directives as components).
Both the changelog and migration guide seem to suggest that we will not have any breaking changes - only security and potentially performance improvements.
There are currently two accounts controllers in the application's server-side controllers.
It's confusing for developers that both exist. I recommend that we delete "accounts.js" and rename "account.js" --> "accounts.js". @DedrickEnc wrote the latter one and provided tests for it. It should be preferred over the previous.
GreenKeeper is a useful tool for keeping dependencies up to date. As soon as #24 and #25 land, we'll be able to catch regressions easily in our code base. In order to keep up to date with security fixes, features, and optimizations in the underlying NPM modules, I propose we use GreenKeeper to test branches with new versions of our dependencies when they are updated. These, of course, would only be merged provided that they pass the tests.
We currently use morgan middleware for logging HTTP requests and connections. Unfortunately, it does not support generic logging (for example, events or thrown errors) and only listens to HTTP connections (not available in libraries).
Winston provides a highly configurable logger that gives us the remaining functionality we lack. It supports the idea of log levels (for example, verbose, production, silent, ...) and outputs seamlessly to files. I propose we use it to compliment morgan, which seems to do a good job at logging HTTP requests.
The application has never handled state well. For simple cases (do we have a primary cashbox or not?), the controller has often just used an ng-if
directly in the HTML to show/hide components. For more complex cases, the controller uses an ng-switch
(create/update/success/failure). Admin modules are good examples of these. In the most complex cases, sometimes an ng-switch
is coupled with an ng-include
and even a new controller is templated in. Receipts is a good example of this condition.
One solution is to use the router to manage state. Our current router (ngRouter
) is limited to only directly mapping URLs to individual templates and controllers, 1-1-1. A different project, ui-router
allows you to nest controllers and views, so that child states can inherit properties of the parent states, and you can have multiple views on a single page (we currently only have on ng-view).
Advantages of ui-router:
/patients
<- /patients/:id
<- /patients/:id/groups
) to reduce the need for services and extra $http requests.Dis-advantages of ui-router:
link.
Since we are entering a sprint focused on testing, I propose we swap out our dependency on the library guid
on the server in favor of a tested UUID library. It doesn't matter too much which one we use, but node-uuid is highly depended upon by other projects. The API is slightly different from our library, but that shouldn't be a big deal.
A quite popular functional programming library is lodash. We've run into a couple use cases where it would be very useful to have on the server. Considering we are valuing testing, lodash is well-tested and would do well to replace out current util
library functions.
Here are a few applications:
dotjs
with lodash templates (templating).util
with lodash/lang
.Interestingly, lodash is the most depended upon npm package [src]. You can bet it is well tested!
We use localForage for our local storage wrapper. There currently isn't a good way to selectively delete items from a localForage instance, during e2e tests. It would be nice to have a generic function to allow clearing a localforage namespace, usable from our e2e tests. Something like:
it('clears the provided namespace', function () {
var namespace = 'example';
clearLocalStorage(namespace);
// .. other tests ..
});
There may be a need to use browser.wait()
or browser.executeAsyncScript()
to accomplish this. As we begin testing functionality, we'll need this tool.
... alternatively, we could drop support for localForage and use the window storage directly (through some Angular wrapper). I see no reason to support such a flexible storage solution if our only browser support is for Chrome. We could also simply write our own wrapper.
After some analysis of the bhima-1.X primary cash module, I think we could model the entire functionality of the primary cash, with the exception of payroll, as journal vouchers.
Benefits:
Costs:
In order to use Journal Vouchers for Primary Cash operations, we will need to have a Journal Voucher table in the database. This is different from the current method, where Journal Vouchers simply send data directly to the posting_journal
. We need the voucher table so that we have an immutable record (like sale
or cash
) of the journal voucher created and can re-print the receipt at any time.
The table should be called voucher
with fields uuid
, date
, project_id
, reference
, currency_id
, amount
, description
, document_uuid
, and user_id
. There will be a joiner table voucher_items
with columns uuid
, account_id
, debit
, credit
, voucher_uuid
.
I strongly feel that our Primary Cash module is confusing and over-extended. It also fits our test site well, but probably will not make any sense when scaling to other hospitals. What happens if employees are not paid out of the primary cash, but instead the bank? One whole part of the module is useless.
As we are focusing on Primary Cash next, I would be interested in having a discussion with @IMA-WorldHealth/local-contributors to get feedback on this proposal.
We are writting a new version of BHIMA (V2), some decision must be taken and now is the best moment to take them.
Our system is coupled we have angularjs and nodejs, angular is designed to force programmer using services, controllers and views but it is not the case for nodejs.
We should continue to amend our server side, for now our controllers at the server side contain some data operation which can be isolate to a low level (Data Access Layer).
We should find business rules only in our controller and data access operations in our kind of model or data object.
This proposal, if applied will reduce the number of code line in our route.js
file and will make the server side code maintainable.
Exposing the controllers interfaces directly instead of exposing each http method one by one is advantageous.
The current journal code uses string matching and a function that takes in six parameters - some of them objects, numbers, or functions. We should re-write this interface to provide direct posting without the need for anything but a UUID. For example:
// inside controllers/finance/sales.js
// create a sale with some uuid
journal.postPatientInvoice(uuid);
// inside controllers/finance/cash.js
// create a cash payment with some uuid
journal.postCashPayment(uuid);
All information needed to post any record should already exist in the database.
During our daily meeting we decided to add a new module in finance to let the cashier veer money between the cash and the transfer account, so that the primary cash responsibility and auxiliary cash responsibility will be clearly separated.
Since the auxiliary cash is formatted for income only, the transfer module will write directly in the posting_journal table.
What do you think?
@IMA-WorldHealth/local-contributors
The npm dotenv module would help us manage production/development/testing environments much more clearly and efficiently than our current JSON setup. It would also give us a clear way to add new environmental variables (such as database configuration parameters, timers, etc) in the future.
For bhima, the basic idea would be to define an .env
file (and .env.example
for reference) that would not be synced to Github. It would have keys such as PORT
, DB_PASS
, DB_USER
, DB_HOST
, EMAIL_FREQUENCY
, LOG_LEVEL
etc, that are currently stored in /server/environment/config
. The dotenv module would allow the server to load these configuration properties once to be shared with all child modules, rather than passing around a JSON object from module to module.
A huge refactor of the CSS + logic powering bhima's Tree Navigation component just landed (#42). The tree is functional and re-skinned for 2.X standards. This issue is to track new features we might want to add to the navigation either for bhima 2.X or beyond. If a PR lands with any of these features, feel free to link them and tick the checkbox.
One major difficulty that bhima has faced is users double-clicking the submit button. This results in multiple form submissions. This proposal is for a submit button that has state so that it is disabled and shows a loading indication when submitting when submitting, and behaves like a regular button at all other times. The idea would be something like this:
Ready State
Loading State
When loading, the button shows a loading indicator and disables itself. When not loading it is a regular button. This button in the HTML might look like this:
<button submit-button="Ctrl.loadingState" class="btn btn-primary" ng-click="Ctrl.submit()" type="submit"></button>
In order to facilitate easily reading and reviewing the code (as well as nice JSDoc layouts), I propose we adopt the following guidelines for creating services within the application.
var service = this
at the top of the service function.service
at the bottom of the service function declaration.Here is an example:
angular.module('bhima.services') // note: we are creating a 'service' instead of a 'factory'
.service('SomeService', SomeService); // note: this name contains the suffix Service
SomeService.$inject = [ '$http', 'util' /*, other injects ... */];
function SomeService($http, util) {
var service = this; // note: we are aliasing the `this` reference.
/** @method detail */
service.detail = detail;
/** @method someOtherMethod */
service.someOtherMethod = someOtherMethod;
// ....
/**
* @desc The detail methods returns detailed records from the database
* @param {Number} id A numerical id found in the database
* @example
* SomeService.detail(id)
* .then(function (record) {
* vm.record = record;
* });
* @returns {Object} promise A promise object with the response.body inside.
*/
function detail(id) {
return $http.get('/some/endpoint' + id)
.then(util.unwrapHttpResponse);
}
/**
* @desc blah, blah, blah
* .... more JSDoc documentation
*/
function someOtherMethod() {
// ... code ...
}
return service; // Note: returning service at the bottom of the service.
}
The application currently depends on session-file-store
, which seems to work, but doesn't inspire much confidence. This is my terminal:
I think we can do better.
We have had a number of issues with session timeouts and session persistence in the past. @sfount has previously proposed using redis to manage sessions (via connect-redis or an alternative), which may be investigated. Another interesting solution might be to use sqlite3 wrapped with connect-sqlite3.
For reference, the list of supported session stores is here.
The current bhima production builds ship individual files to the client in a large number of script tags (see index.html). This is bad practice. The correct way to distribute our JavaScript app is to minify and package the entire application in a single file and ship that once to the client.
For this issue to be satisfied, our index.html must contain this script tag as the only script tag:
<script src="js/app.min.js"></script>
This is a request for a polyfill/decorator that will allow me to write much cleaner client-side code. Angular's $q
service provides a tiny API. I've found myself writing the following code several times:
Service.detail(id)
.then(function (entitiy) {
return [
ServiceA.detail(entity.idA),
ServiceB.detail(entity.idB),
ServiceC.list(),
ServiceD.methodX()
}).then(function (promises) {
var entityA = promises[0];
var entityB = promises[1];
var entityC = promises[2];
var entityD = promises[3];
// logic!
})
.catch(handler);
This code is obtuse and hard to read. If we decorated $q
with $q.spread()
I could write:
Service.detail(id)
.then(function (entitiy) {
return [
ServiceA.detail(entity.idA),
ServiceB.detail(entity.idB),
ServiceC.list(),
ServiceD.methodX()
}).spread(function (entityA, entityB, entityC, entityD) {
// logic!
})
.catch(handler);
which is certainly much prettier. Adding methods to AngularJS services is easy with Angular.decorator.
This proposal concerns the MySQL tables posting_journal
and general_ledger
.
There is no clear way to reference an invoice in the Posting Journal or General Ledger. There should be an easy way to look up transactions in the database and following links between transactions to relate dependencies. For example, a cash transaction may reference a previous patient invoice, or a stock increase may reference the purchase order's cash transaction.
I propose that we drop the columns doc_num
and inv_po_id
entirely. These will be replaced with more meaningfully named columns record_uuid
and reference_uuid
. The record_uuid
should be the uuid of the table which posted the record to the posting journal. For example, if it were a cash payment, it would be the cash.uuid
. For a patient invoice, the sale.uuid
associated with that record. This is a required field, and it will be the same uuid for an entire transaction.
The reference_uuid
will reference other record_uuid
s in the posting journal, forming the link between multiple transactions in a series. One line in a transaction will never have a reference_uuid
, but all other lines may have one or none.
#### Why two columns?
You could model the same functionality with a single column. However, two columns also greater flexibility in application logic. Two columns distinguish between the idea of an ID and a reference. We can use this idea to build business logic that warns the user if they are deleting a transaction that is referenced in a subsequent transaction. With a single column, you cannot be sure if you are deleting the ID or the reference. With two columns, all you need to do is check the column name.
Interested in any feedback @IMA-WorldHealth/local-contributors.
This recommendation replaces the #91 issue by recommending we move to an alternative storage provider, removing the dependency on both localForage
and angular-localforage
. My formal recommendation is to move to ngStorage, which looks like a nice lightweight alternative. It only supports key-value storage, but all browsers have good support for key-value stores.
I'd be interested in seeing a prototype PR built with ngStorage. It does not use promises, so our code could potentially be much cleaner! Removing localForage would slim the application by a few kb.
This proposal is for a generic receipt (modal) for any given transaction in the General Ledger or Posting Journal.
Use Case
1 . Many of our Primary Cash transactions are really just account-to-account transactions with a nicer UI in front of them. Most, if not all, of these modules could use the same "Transaction Receipt" interface to print out the details of a transaction, instead of creating a custom receipt for each one.
Technical Details
The transaction receipt must be a modal, showing all the important details of the transaction. This includes:
As headers, the receipt should include:
As footers, the receipt should include:
Our database tables and associated routes are all named "hollydays" or "holydays", in some cases, which should be corrected as we revisit these routes. The correct spelling is "holiday" (singular) or "holidays" (plural).
The find-patient directive has been updated to BHIMA 2.X standards and is now a very solid base.
There are a few additional features that could be added to improve user experience and simplify use - as this directive is used in so many different modules it can be tackled by any developer that would like to address an issue.
required
hook for form validationI will add any comments that are made below into this list of proposed features for the find-patient directive
The convention module need a loading indicator for notify the user about the debitor receipts are being loaded when we select a debitor.
The process take too long time for loading debitor receipts and also when we click on "submit" for a payment.
The connect-multiparty README recommends using the multiparty API directly. However, the multiparty README recommends that implementers look into busboy as a faster alternative. It seems that none of these projects are very stable.
I have experience using multer in a separate app, and it is part of the official ExpressJS ecosystem. I suggest we migrate to using it for future uploads and migrate our existing code to use that module instead.
There are a few places we need to display telephone numbers in the application (receipts, reports, lists of users, etc). A handy component to have would be a telephone filter. Something that could be easily embedded in a view such as this:
<span>{{ patient.telephone | telephone }}</span>
... to yield a nicely formatted telephone number (e.g. +243 821 453 233).
Directive to display a read only date that can enter a discrete manual update state to allow the date to be changed only if required.
This pattern has been used in a number of places and it would be good to standardise/ test it.
The component would have to states
Along with this issue #57 there are a number of components we used in many places in BHIMA that should be well researched, proposed and implemented.
As part of the bhima 2.X release cycle, I propose we migrate as many tables as possible to using DATETIME column types instead of DATE for storing date datapoints. Under this direction, we will design our table columns following these guidelines:
Date()
object. The SQL datatype does not convert records from their original timezone to UTC (like a TIMESTAMP does), preferring to store them in the time zone of the server.It is worth reading the page on MySQL dates [1]. Also useful is this [2] Stack Overflow discussion (see top two answers).
[1] http://dev.mysql.com/doc/refman/5.7/en/datetime.html.
[2] http://stackoverflow.com/questions/409286/should-i-use-field-datetime-or-timestamp.
Angular UI's datepicker has come a long way in recent releases. The advantages of using uib-datepicker
for (certain, if not all) date inputs are the following:
uib-datepicker
implementation, whereas styling for the <input type="date">
is limited and browser specific.uib-datepicker
dynamically using $translate
, which removes a dependency on the users' browser settings.May be related to #58.
Our translations files have become far to big to work with efficiently. This leads to repeating the same keys in different contexts, and collisions in our git repository on almost every commit.
The fundamental question is how to break the translation files up. For a start, we could try splitting on top-level domains, such as hospital.en.json
, finance.fr.json
, shared.fr.json
, etc. What do @IMA-WorldHealth/local-contributors think?
These are components that we will need to build to make the application modular and testable. This list is subject to change, and each component should be described in its own issue.
This proposal should be split into two parts:
This proposal can then be implemented across 2.X modules.
So far, we've been using q as our Promise implementation on the server. An alternative is to use bluebird, a fast promise implementation that is built with NodeJS specifically in mind. I'd like to change library for three reasons:
.done()
syntax, built-in support for .map()
, etc.q
and native promises.bluebird.promisify()
to replace db.exec()
.A third alternative is to simply use NodeJS promises, but it seems that bluebird is faster than Native promises and gives us more flexibility in the API than a strictly A+/Promise implementation.
Since we are currently rewriting APIs, it makes sense for this change to land now. Curious to know what other developers think though.
Apparently Bootstrap 4 will be written in SASS, not LESS. Since we are in a period of change, we might as well make the migration before the Bootstrap 4 community, in order to remain compatible for the future. Bootstrap maintains an official Bootstrap 3 SASS port, available via bower as bootstrap-sass
.
This could be proposed as a requirement for bhima-2.X pages (like form validation etc.)
Anywhere a module elements waits on an asynchronous request it can cause the user interface to 'hang' or wait for the data to be populated - if this is indicated clearly it is very clear what the page is doing.
This is especially noticeable when loading modals that require additional data to be downloads, for a demonstration of the problem:
As the modal downloads the available patient groups, nothing is displayed and the application is allowed to enter a broken or unhandled state.
This feature proposal expands the medical history records of the application.
One way to preserve patient documents is to scan them into the computer, upload them, and directly link them to a patient entity. In order to successfully accomplish this, we'll need to develop an appropriate method of linking, storing, backing up, and syncing patient documents.
In brief, a new database table, patient_attachment
, will need to be created with the following columns: patient_uuid
, document_uuid
, label
, timestamp
. Any uploaded document will have the file name rewritten to a new uuid()
. The patient_attachment
table stores the original document name in the label
field (editable in the future). The documents are stored on disk in a folder specified by the environmental variable UPLOAD_DIR
.
We will need to design a way to sync documents across radio networks as well. Something like rsync might come in handy there.
The server side API should support the following routes:
POST /patients
should allow an additional array of "attachments" (five maximum)POST /patients/:uuid/attachments
should add attachments to the patientDELETE /patients/:uuid/attachments/:uuid
should delete an attachment from the patient's attachments matching the provided ID.DELETE /patients/:uuid/attachments
should delete all attachments from the patient entity.GET /patients/:uuid
should return an attachments
array on the patient object with ids for all of the entity's attachmentsGET /patients/:uuid/attachments/
should return a list of patient attachmentsGET /patients/:uuid/attachments/:uuid
should serve the attachment to the browser as a download.On the client side, the /patients/:uuid/edit
route should allow a user to upload, remove, and show attachments much like patient groups or debtor groups.
Interested in feedback on this @IMA-WorldHealth/local-contributors.
This proposal concerns conceptually changing the exchange rate. We currently treat exchange rates as only valid the day they are defined. I propose change the exchange rate handling to be valid from the time of definition to the next time of change.
Proposed Database Changes:
enterprise_currency_id
and replace with enterprise_id
.date
column's data type will be DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP.foreign_currency_id
to simply currency_id
.Proposed API changes:
GET /exchange
lists all the exchange rates in the databasePOST /exchange
will create an exchange rate. If no date is provided, use the current timestamp.PUT /exchange/:id
update an exchange rate in the database.DELETE /exchange/:id
will delete an exchange rate from the database.Proposed algorithm changes:
ExchangeService
will get exchange rates based on the current time. The exchange rates will be kept in an ordered list. Given a date, the algorithm will walk down the list of exchange rates, setting the most recent rate prior to the given date as a valid rate. If no valid rate exists, the service should throw an error. This part of the proposal has already been implemented in ExchangeRateService.Additionally, we should support both editing and deleting exchange records. This would allow the enterprise to correct previous records by editing a faulty exchange rate and recalculating the rates for the data in the posting journal.
Once #24 lands, bhima-2.X will have automatic testing of integration tests to prevent regressions. This will greatly speed up PR reviews and ensure that we are always moving forward without breaking things in the past.
The next logical step is to move our e2e tests onto an external service. Travis integrates well with SauceLabs which gives unlimited testing instances to open source projects. It's my personal goal to have automatic e2e and integration testing for each PR by the end of the month.
Re: The comment at the top of the location directive.
* Note : Directive should have a separate template and link method;
* - Angular doesn't allow you to template ng-model
* - I'm too stubborn to let that win, and (simplify everything) just hard-code in location selects
* - This doesn't need to be this generic, and should be re-factored if required
*/
This directive should be updated to the latest 2.X standards. Specifically:
Travis allows hooks to automatically deploy the application if the test suite successfully passes. My only experience is with OpenShift, though I would be interested in exploring other options (OpenShift uses out-of-date NodeJS versions).
After both #24 and #25 are satisfied, I propose we make it a project goal to have automatic deployment to a cloud provider. Not only will this require us to have a simplified build, it will force us to begin dealing with bandwidth constraints and allow external parties to review the application without any effort to configure it.
I'd be interested to hear if anyone else thinks this idea is worthwhile.
This is a request for a generic "signature" component that would allow users to insert custom signatures into reports. At minimum, the developer should be able to specify a signature with a signer key to display. The code would like like this...
<bh-signature signer="SIGNATURES.ACCOUNTANT"></bh-signature>
.. rendering a signature field for the accountant. The signer
field would accept a key to be passed to $translate
and templated into the HTML template. Adding signatures to a receipt would become incredibly easy.
Any form which requires a location (using the location select component #35), will probably need to add a new location at some point. Instead of forcing navigation away from the page to a "location management page" as we did in bhima-1.X, we should instead drop in a modal to let the user specify a new location immediately.
The modal should allow a user to create a new location - a combination of country, province, sector, and village. The modal should accept an object of uuids (countryUuid, provinceUuid sectorUuid) to be injected into the controller via resolve()
, and preselect that contry, province, and/or sector from the dropdown menus.
This component will directly link to #35.
This proposal is for a currency input directive. The cash module currently uses a <input type="number">
that is very simplistic and does not give appropriate user feedback. Here is an image of it:
I imagine the directive's signature to look like this:
<div class="form-group">
<label>The Currency Directive</label>
<bh-currency-directive currency="Ctrl.currencyId" relaxed required></bh-currency-directive>
</div>
The currency input directive must fit the following criteria:
currency={ currencyId }
(one way binding to controller currency id)required
Boolean attribute to apply to the underlying <input>
elementrelaxed
Boolean attribute to determine if rule 3 of this list is followed. If true, do let any positive value be inputed. If false, follow the constraint describe in rule 3.min_monentary_unit
of the currency as the minimum value acceptable in the currency input.A directive such as this would greatly improve the speed we develop the Primary Cash modules.
For a while we have known that storing UUIDs as a 36 character (VARCHAR(36)) string is non optimal, both for the storage space it requires and for how long it takes to read/join tables on long strings.
Proposal:
8598abec-c985-11e5-975b-6c29955775b0
8598abecc98511e5975b6c29955775b0
UNHEX(8598abecc98511e5975b6c29955775b0)
HEX(Table.Uuid)
There are a number of research articles that seem to show storing UUIDs in this format reduces both space required and most importantly access/ join speed.
The change would mostly affect how UUIDs are written and read from the database and should not change very much application logic.
@IMA-WorldHealth/local-contributors This can be discussed and prioritised accordingly.
According to the gulp-minify-css page, the plugin is deprecated and should be swapped out for css-nano.
This proposal concerns the bhima build system.
I propose that we allow optional SSL. In production, you should always use HTTPS to protect your data; however, many virtualization and testing frameworks do not support SSL. It would certainly make our integration and end to end tests more clear.
To accomplish this, we will include the following flag in the .env
environmental variables:
BHIMA_USE_TLS
= { 0 || 1 }We should also rename the previous TLS_CERT
and TLS_KEY
flags to use the BHIMA
prefix.
An application built with TLS will continue to function as the current build. An app built without TLS enabled will import http
instead of https
and not require the certificate or keys to be imported.
Finally, if the application is not built with TLS, there should be prominent console warnings on boot up, telling the user that running data over an unencrypted network is dangerous.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.