I am sponsoring a series of projects to improve the demographic section of OpenEMR.
The long-term goal of what I would like to do is outlined in the following post:
My intermediate goal is to normalize database tables to allow one-to-many relationships of contact information.
This will allow multiple entries for different types of contact information:
Addresses
Telephone Numbers
Email Addresses
Secondary Contacts
Employers
It will also more easily allow tracking of old contact information.
My first project is to add the ability to store multiple addresses.
I have created this forum to not only describe the project, but also for us to get guidance & feedback in regards to implementation, application architecture, and general programming approach.
Based upon discussion with Brady Miller, Stephen Nielson, and Jerry Padgett during the weekly conference calls, the following is an outline of the steps of this project:
Add Line & Data type to Layout Editor
Location: Administrator â Forms â Layouts
Edit layout: Core - Demographics
Add Field: âAddressesâ
Create Tables
Create table to store addresses.
Table to have one-to-many relationship with patient_data
File Locations:
sql/6_0_0-to-6_1_0_upgrade.sql
sql/database.sql
Create Code To Display & Save the Address Table
Create Data type for multiple addresses.
Create code that displays from and saves information to the address table.
Location of code:
Existing Code that Creates Similar Data types:
(1) Commit âPrevious Nameâ
It creates a data type that displays/edit columns in the table âpatient_historyâ.
The tables âpatient_dataâ and âpatient_historyâ have a one-to-many relationship.
(2) Commit âAdd Encounter to Transaction Formâ
Create Code for Database Queries
Centralized Location for Queries is in Services:
/src/Services/PatientService.php
/src/Services/AddressService.php
This is where the code will be written to query the new tables.
Unfortunately, this is newer and most existing queries do not use it.
PatientService returns query results in variable $processingResult.
$processingResult is of type class PatientValidator
/src/Validators/BaseValidator
/src/Validators/PatientValidator
Changing Queries that Query Address Info from patient_data (Street, City, etc)
This will be the most work intensive step, since there are a lot of queries.
Queries should be modified to get info from classes/functions created in:
PatientService.php
AddressService.php.
Migrate Data
From patient_data to our normalized address tables.
Remove Address Related Columns From patient_data
This will be the final step.
I have been giving this some thought and have some insights Iâd like to share.
While I am one of LBFâs biggest fan, we are finding it more difficult to expand Demographics with one to many type relationship inputs. One hold back is that demographics is hard wired to the patient_data table which over time has expanded greatly. What is needed is the ability in LBF Groups to define what the primary table for storage will be for the groups content. So diverging away from the patient_data table is just a first step.
Next is dealing with a more complicated form than just collecting data in static fields where over time the screen will become tiresome to view. In the case of additional addresses then four or five static fields times say three address datasets makes for rapidly expanding lost of screen space. So the natural pattern is to slide/popup the addition data which is fine however, LBF doesnât currently have that mechanism.
This is where Iâd purpose adding additional data types for handling sub forms or templates. The template could be another LBF with itâs own groups/sub groups where tables are defined or a custom HTML form called as a plug in. In this case the HTML plug in can handle the data distribution to storage. I also wouldnât rule out using twig templates so data types would need to consider this as well. Remember that LBF groups can have sub groups. For example:
This would mean developing data types with pointer to templates and a display type(slide/dialog).
The data type and supporting items could be something like:
data type: pop_template title Additional Addresses
List would be a list created in Lists for template by LBF name or path to HTML template.
There are numerous examples of using dialogs(dlgopen) throughout core. Dialogâs can be called as iframes, passed in content or fetched content via ajax. Dialogs can also return a promise for several events(all the normal modal events plus) which is how I recommend using or at least allowing for when implemented as promises become very useful in many form sceneries.
To manage on the backend Iâd recommend we create a new controller class and start migrating the procedural parser code(options.inc) to methods in a new service class or several. There are several ways to go about this but my first thought is an abstract class that could/would be extended.
For an LBF template, most likely the current engine could handle persisting data and an HTML template could have data handled as part of the template form similar to how the majority of our current forms are handled. Still, more thought is required perhaps concerning a generic MVC for such templates. For now Iâd keep it simple while getting the entire new pattern in place.
For the purpose of additional address etc. I would not follow my previous name input using select2 which if I had more time when I developed, Iâd gone in the direction Iâm talking about here.
Now all of this requires more fine tuning of course but, I hope the concept is somewhat clear however if not, please post a question or thoughts. Iâm going back to jamming to Alice Cooper.
@psoas@stephenwaite I just remembered I recently had to fix the insert in InsuranceService because it wasnât working.
So if the practice insurance is using it may be the issue with addresses.
Also InsuranceCompany does use the generateId from sequence table. Sometime when restoring partial backups the sequence table can create duplicates. Otherwise this should work.
Actually the whole bottom of the method is not right. Address is never created the way itâs written.
Because AddressService will return false on success and not a new id. sqlInsert will always return false on tables that donât have a auto increment id.
Not on an address insert is it. addresses table has primary but not auto increment unless maria vs mysql changed because in order to return an id, column needs to be an auto increment.
You may be getting back the fresh id for the new address row but not from the global.
It looks like the first column of the LBF is reserved for the label. I do not want to have and do not need a label. I would like my datatype âAddress Listâ to span the entire row, but I cannot find a set of LBF options that will allow this.
In âEdit Layoutâ, I tried to make the label blank and made âLabel Colsâ = 0. This did not work. Any advice on how I can adjust the LBF settings so that there is no blank area to the left of my address list?
PR not necessary because problem is not with my code.
The problem is with the display of LBF used by demographics, likely in the function display_layout_tabs_data.
You can recreate my problem with any datatype. For simplicity, try:
âinserting a field of datatype textbox into demographics layout
âleave label blank
âlabel cols = 0
âdata cols = 4
âoptions = âJump to next rowâ
âgo to demographics, enter info into new textbox, and click save.
In display mode, the textbox is in column 2 instead of column 1. (wrong)
In edit mode, the textbox is in column 1. (correct)
Please, let me know if you get a different result.