diff --git a/interface/main/tabs/menu/menus/standard.json b/interface/main/tabs/menu/menus/standard.json index dd22eec3ea5..785da1499e1 100644 --- a/interface/main/tabs/menu/menus/standard.json +++ b/interface/main/tabs/menu/menus/standard.json @@ -1239,21 +1239,6 @@ "global_req": [ "erx_enable" ] - }, - { - "label":"Weno Management", - "menu_id":"adm0", - "target":"adm", - "url":"/interface/weno/facilities.php", - "children":[], - "requirement":0, - "acl_req": [ - "admin", - "super" - ], - "global_req": [ - "weno_rx_enable" - ] } ], "requirement": 0, @@ -1328,21 +1313,6 @@ ], "global_req": "!disable_prescriptions" }, - { - "label":"Prescription Log", - "menu_id":"rep0", - "target":"rep", - "url":"/interface/weno/rxlogmanager.php", - "children":[], - "requirement":0, - "acl_req": [ - "patients", - "rx" - ], - "global_req": [ - "weno_rx_enable" - ] - }, { "label": "Patient List Creation", "menu_id": "rep0", diff --git a/interface/modules/custom_modules/README b/interface/modules/custom_modules/README deleted file mode 100644 index 2d89b07e342..00000000000 --- a/interface/modules/custom_modules/README +++ /dev/null @@ -1 +0,0 @@ -Custom Modules diff --git a/interface/modules/custom_modules/README.md b/interface/modules/custom_modules/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/interface/modules/custom_modules/oe-module-weno/LICENSE b/interface/modules/custom_modules/oe-module-weno/LICENSE new file mode 100644 index 00000000000..20d40b6bcec --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/README.md b/interface/modules/custom_modules/oe-module-weno/README.md new file mode 100644 index 00000000000..93ed8f76789 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/README.md @@ -0,0 +1,9 @@ +# Weno EZ Integration Module for OpenEMR +This module enables prescribers to make ePrescription through Weno's iFrame. + +## To Install the Weno EZ Integration Module +- On the top menu Modules -> Manage Modules. Click the unregistered button to display all unregistered modules. +- Find the Weno EZ Integration Module and click the "Register Button". +- On the Registered tab, click install and enable. +- After successful installation, headover to Admin -> Config -> Weno to enter the weno Admin settings. To register for an account, visit www.online.wenoexchange.com +- Follow the instructions on the Developer Page to configure your Weno EZ integration. \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/cleanup.sql b/interface/modules/custom_modules/oe-module-weno/cleanup.sql new file mode 100644 index 00000000000..e69de29bb2d diff --git a/interface/modules/custom_modules/oe-module-weno/composer.json b/interface/modules/custom_modules/oe-module-weno/composer.json new file mode 100644 index 00000000000..778f96e3c69 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/composer.json @@ -0,0 +1,20 @@ +{ + "name": "openemr/oe-module-weno", + "description": "Weno EZ Integration Module", + "type": "openemr-module", + "minimum-stability": "stable", + "license": "GPL-3.0", + "authors": [ + { + "name": "Kofi Appiah", + "email": "kkappiah@medsov.com" + } + ], + "require": { + }, + "conflict": { + "openemr/openemr": ">=7.0.1" + }, + "config": { + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/info.txt b/interface/modules/custom_modules/oe-module-weno/info.txt new file mode 100644 index 00000000000..16f17139939 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/info.txt @@ -0,0 +1 @@ +Weno EZ Integration Module \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/moduleConfig.php b/interface/modules/custom_modules/oe-module-weno/moduleConfig.php new file mode 100644 index 00000000000..6263c658fc8 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/moduleConfig.php @@ -0,0 +1,15 @@ + + * copyright Copyright (c )2021. Sherwin Gaddis + * license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + * + */ + +require_once dirname(__FILE__, 4) . '/globals.php'; + +$module_config = 1; diff --git a/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php b/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php new file mode 100644 index 00000000000..62921dd37ef --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php @@ -0,0 +1,29 @@ + + * Copyright (c) 2023 Omega Systems Group Corp + * @license GNU General Public License 3 + * + */ + +namespace OpenEMR\Modules\WenoModule; + +use OpenEMR\Core\ModulesClassLoader; + +/** + * @global OpenEMR\Core\ModulesClassLoader $classLoader + */ + +$classLoader->registerNamespaceIfNotExists('OpenEMR\\Modules\\WenoModule\\', __DIR__ . DIRECTORY_SEPARATOR . 'src'); + +/** + * @global EventDispatcher $eventDispatcher Injected by the OpenEMR module loader; + */ + +$bootstrap = new Bootstrap($eventDispatcher, $GLOBALS['kernel']); +$bootstrap->subscribeToEvents(); diff --git a/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js b/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js new file mode 100644 index 00000000000..acce62f21af --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js @@ -0,0 +1,55 @@ +function sync_weno(){ + var syncIcon = document.getElementById("sync-icon"); + var syncAlert = document.getElementById("sync-alert"); + const url = '../../modules/custom_modules/oe-module-weno/templates/synch.php'; + + syncIcon.classList.add("fa-spin"); + + let formData = new FormData(); + formData.append("key", "sync"); + + fetch(url, { + method: 'POST', + body: formData + }) + .then(response => { + if (!response.ok) { + // If the response status code is not in the 200-299 range, reject the promise + throw new Error('Server responded with an error status: ' + response.status); + } else { + //setting alert details + wenoAlertManager("success",syncAlert,syncIcon); + } + + }).catch(error=> { + console.log(error.message) + wenoAlertManager("failed",syncAlert,syncIcon); + }); +} + +function wenoAlertManager(option, element, spinElement){ + spinElement.classList.remove("fa-spin"); + if(option == "success"){ + element.classList.remove("d-none"); + element.classList.add("alert", "alert-success"); + element.innerHTML = "Successfully updated"; + window.location.reload(); + setTimeout( + function(){ + element.classList.add("d-none"); + element.classList.remove("alert", "alert-success"); + element.innerHTML = ""; + }, 3000 + ); + + } else { + setTimeout(function(){ + element.classList.add("d-none"); + element.classList.remove("alert", "alert-danger"); + element.innerHTML = ""; + }, 3000); + element.classList.remove("d-none"); + element.classList.add("alert", "alert-danger"); + element.innerHTML = "An error occurred"; + } +} \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php new file mode 100644 index 00000000000..a4b7185182f --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php @@ -0,0 +1,198 @@ +decryptStandard($GLOBALS['weno_admin_password']); +$encryption_key = $cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); +$baseurl = "https://online.wenoexchange.com/en/EPCS/DownloadPharmacyDirectory"; + +$data = array( + "UserEmail" => $weno_username, + "MD5Password" => md5($weno_password), + "ExcludeNonWenoTest" => "N", + "Daily" => "N" +); + +if (date("l") == "Monday") { //if today is Monday download the weekly file + $data["Daily"] = "N"; +} + +//check if there is history of download, if not do a weekly file +// $pharmacyService = new PharmacyService(); +// $db_exist = $pharmacyService->checkWenoPharmacyLog(); +// if($db_exist != "empty"){ +// $data["Daily"] = "Y"; +// } + + +$json_object = json_encode($data); +$method = 'aes-256-cbc'; + +$key = substr(hash('sha256', $encryption_key, true), 0, 32); + +$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0); + +$encrypted = base64_encode(openssl_encrypt($json_object, $method, $key, OPENSSL_RAW_DATA, $iv)); + +$fileUrl = $baseurl . "?useremail=" . urlencode($weno_username) . "&data=" . urlencode($encrypted); +$storelocation = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/weno_pharmacy.zip"; +$path_to_extract = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/"; + +// takes URL of image and Path for the image as parameter +function download_zipfile($fileUrl, $zipped_file) +{ + $fp = fopen($zipped_file, 'w+'); + + $ch = curl_init($fileUrl); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 1000); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); + curl_exec($ch); + + curl_close($ch); + fclose($fp); +} + +download_zipfile($fileUrl, $storelocation); + +$zip = new ZipArchive(); + +$wenolog = new WenoLogService(); + +if ($zip->open($storelocation) === true) { + $zip->extractTo($path_to_extract); + + $files = glob($path_to_extract . "/*.csv"); + if ($files) { + $csvFile = $files[1]; + $filename = basename($csvFile); + $csvFilename = $filename; + + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "File extracted successfully."); + echo 'File extracted successfully.'; + echo 'CSV filename: ' . text($csvFilename); + $zip->close(); + unlink($storelocation); + } else { + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "No CSV file found in the zip archive."); + echo 'No CSV file found in the zip archive.'; + } +} else { + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Failed to extract the file."); + echo 'Failed to extract the file.'; +} + +$insertPharmacy = new PharmacyService(); + +if ($data['Daily'] == 'N') { + $insertPharmacy->removeWenoPharmacies(); +} + +$insertdata = []; + +$l = 0; +if (file_exists($csvFile)) { + $records = fopen($csvFile, "r"); + + while (!feof($records)) { + $line = fgetcsv($records); + + if ($l <= 1) { + $l++; + continue; + } + if (!isset($line[1])) { + continue; + } + if (!isset($line[1])) { + continue; + } + if (!empty($line)) { + if ($data['Daily'] == 'N') { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[5]); + $business_name = $line[6]; + $address_line_1 = $line[7]; + $address_line_2 = $line[8]; + $city = $line[9]; + $state = $line[10]; + $zipcode = str_replace(['[', ']'], '', $line[11]); + $country = $line[12]; + $international = $line[13]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); + $on_weno = $line[21]; + $test_pharmacy = $line[17]; + $state_wide_mail = $line[18]; + $fullDay = $line[22]; + } else { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[7]); + $business_name = $line[8]; + $city = $line[11]; + $state = $line[12]; + $zipcode = str_replace(['[', ']'], '', $line[14]); + $country = $line[15]; + $address_line_1 = $line[9]; + $address_line_2 = $line[10]; + $international = $line[16]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); + $county = $line[33]; + $on_weno = $line[37]; + $compounding = $line[41]; + $medicaid_id = $line[45]; + $dea = $line[44]; + $test_pharmacy = $line[29]; + $fullDay = $line[40]; + $state_wide_mail = $line[47]; + } + + $insertdata['ncpdp'] = $ncpdp; + $insertdata['npi'] = $npi; + $insertdata['business_name'] = $business_name; + $insertdata['address_line_1'] = $address_line_1; + $insertdata['address_line_2'] = $address_line_2; + $insertdata['city'] = $city; + $insertdata['state'] = $state; + $insertdata['zipcode'] = $zipcode; + $insertdata['country'] = $country; + $insertdata['international'] = $international; + $insertdata['pharmacy_phone'] = $pharmacy_phone; + $insertdata['on_weno'] = $on_weno; + $insertdata['test_pharmacy'] = $test_pharmacy; + $insertdata['state_wide_mail'] = $state_wide_mail; + $insertdata['fullDay'] = $fullDay; + + if ($data['Daily'] == 'Y') { + $insertPharmacy->updatePharmacies($insertdata); + } else { + $insertPharmacy->insertPharmacies($insertdata); + } + + ++$l; + } + } + $wenolog->insertWenoLog("pharmacy", "Success"); + fclose($records); + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } + } + error_log("Pharmacy Imported"); +} else { + $wenolog->insertWenoLog("pharmacy", "Failed"); + error_log("file missing"); +} diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php new file mode 100644 index 00000000000..91d003185a4 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php @@ -0,0 +1,46 @@ + + * @copyright Copyright (c) 2021 Sherwin Gaddis + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ +use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Modules\WenoModule\Services\LogProperties; +use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesJson; + +if (isset($_GET['key']) && !empty(isset($_GET['key']))) { + start_weno(); +} +function start_weno() +{ + $logsync = new LogProperties(); + $logsync->logSync(); +} + +function downloadWenoPharmacy() +{ + $cryptoGen = new CryptoGen(); + $localPharmacyJson = new WenoPharmaciesJson( + $cryptoGen + ); + + //check if the background service is active and set intervals to once a day + //Weno has decided to not force the import of pharmacies since they are using the iframe + //and the pharmacy can be selected at the time of creating the prescription. + $value = $localPharmacyJson->checkBackgroundService(); + if ($value == 'active' || $value == 'live') { + $status = $localPharmacyJson->storePharmacyDataJson(); + error_log('Weno pharmacies download complete with status:' . text($status)); + die; + } +} + +function downloadWenoPrescriptionLog() +{ + $logsync = new LogProperties(); + $logsync->logSync(); + error_log("Background services completed for prescription log"); +} diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php new file mode 100644 index 00000000000..29591e9687c --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php @@ -0,0 +1,155 @@ + + * @copyright Copyright (c) 2023 Kofi Appiah + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +require_once(dirname(__DIR__, 5) . "/interface/globals.php"); + +use OpenEMR\Common\Csrf\CsrfUtils; +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Twig\TwigContainer; + +if (!AclMain::aclCheckCore('patients', 'med')) { + echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Pharmacy Selector")]); + exit; +} + +if (!CsrfUtils::verifyCsrfToken($_GET["csrf_token_form"])) { + CsrfUtils::csrfNotVerified(); +} + +$params = []; + +if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_city') { + $return_arr = array(); + $term = filter_input(INPUT_GET, "term"); + $val = '%' . $term . '%'; + + array_push($params, $val); + + $sql = "SELECT city, id FROM weno_pharmacy WHERE city LIKE ? LIMIT 10"; + $res = sqlStatement($sql, $params); + while ($row = sqlFetchArray($res)) { + $return_arr[] = $row['city']; + } + + echo json_encode($return_arr); +} + +if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_pharmacy') { + $term = filter_input(INPUT_GET, "term"); + $val = '%' . $term . '%'; + + array_push($params, $val); + + $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . + "FROM weno_pharmacy WHERE Business_Name LIKE ?"; + + $weno_coverage = $_GET['coverage'] ? $_GET['coverage'] : ''; + $weno_state = $_GET['weno_state'] ? $_GET['weno_state'] : ''; + $weno_city = $_GET['weno_city'] ? $_GET['weno_city'] : ''; + $full_day = $_GET['full_day'] ? 'Yes' : ''; + $weno_only = $_GET['weno_only'] ? 'True' : ''; + $weno_zipcode = $_GET['weno_zipcode'] ? $_GET['weno_zipcode'] : ''; + $weno_test_pharmacies = $_GET['test_pharmacy'] ? 'True' : ''; + + + if (!empty($weno_coverage)) { + $sql .= " AND state_wide_mail_order = ?"; + array_push($params, $weno_coverage); + } + if (!empty($weno_state)) { + $sql .= " AND state = ?"; + array_push($params, $weno_state); + } + if (!empty($weno_city)) { + $sql .= " AND city = ?"; + array_push($params, $weno_city); + } + if (!empty($weno_only)) { + $sql .= " AND on_weno = ?"; + array_push($params, $weno_only); + } + if (!empty($full_day)) { + $sql .= " AND 24HR = ?"; + array_push($params, $full_day); + } + if (!empty($weno_zipcode)) { + $sql .= " AND ZipCode = ?"; + array_push($params, $weno_zipcode); + } + if (!empty($weno_test_pharmacies)) { + $sql .= " AND test_pharmacy = ?"; + array_push($params, $weno_test_pharmacies); + } + + $sql .= " ORDER BY Business_Name ASC"; + + $res = sqlStatement($sql, $params); + while ($row = sqlFetchArray($res)) { + $return_arr[] = array( + "name" => $row['Business_Name'] . "/ " . $row['address_line_1'] . " / " . $row['city'], + "ncpdp" => $row['ncpdp'] + ); + } + echo json_encode($return_arr); +} + +if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_drop') { + $term = filter_input(INPUT_GET, "term"); + $val = '%' . $term . '%'; + array_push($params, $val); + + $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . + "FROM weno_pharmacy WHERE"; + + $weno_coverage = $_GET['coverage'] ? $_GET['coverage'] : ''; + $weno_state = $_GET['weno_state'] ? $_GET['weno_state'] : ''; + $weno_city = $_GET['weno_city'] ? $_GET['weno_city'] : ''; + $full_day = $_GET['full_day'] ? 'Yes' : ''; + $weno_zipcode = $_GET['weno_zipcode'] ? $_GET['weno_zipcode'] : ''; + $weno_test_pharmacies = $_GET['test_pharmacy'] ? 'True' : ''; + + if (!empty($weno_state)) { + $sql .= " state = ?"; + array_push($params, $weno_state); + } + if (!empty($weno_coverage)) { + $sql .= " AND state_wide_mail_order = ?"; + array_push($params, $weno_coverage); + } + if (!empty($weno_city)) { + $sql .= " AND city = ?"; + array_push($params, $weno_city); + } + if (!empty($full_day)) { + $sql .= " AND 24HR = ?"; + array_push($params, $full_day); + } + if (!empty($weno_zipcode)) { + $sql .= " AND ZipCode = ?"; + array_push($params, $weno_zipcode); + } + if (!empty($weno_test_pharmacies)) { + $sql .= " AND test_pharmacy = ?"; + array_push($params, $weno_test_pharmacies); + } + + $sql .= " ORDER BY Business_Name ASC"; + + $res = sqlStatement($sql, $params); + while ($row = sqlFetchArray($res)) { + $return_arr[] = array( + "name" => $row['Business_Name'] . "/ " . $row['address_line_1'] . " / " . $row['city'], + "ncpdp" => $row['ncpdp'] + ); + } + echo json_encode($return_arr); +} diff --git a/interface/modules/custom_modules/oe-module-weno/sql/table.sql b/interface/modules/custom_modules/oe-module-weno/sql/table.sql new file mode 100644 index 00000000000..a64137c9187 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/sql/table.sql @@ -0,0 +1,87 @@ +#IfNotTable weno_pharmacy +CREATE TABLE `weno_pharmacy` ( + `id` int(20) NOT NULL AUTO_INCREMENT, + `App` varchar(8) DEFAULT NULL, + `NCPDP` varchar(8) DEFAULT NULL, + `NCPDP_safe` varchar(7) DEFAULT NULL, + `Mutually_Defined_ID` varchar(10) DEFAULT NULL, + `Mutually_Defined_ID_safe` varchar(10) DEFAULT NULL, + `NPI` varchar(10) DEFAULT NULL, + `NPI_safe` varchar(10) DEFAULT NULL, + `Business_Name` varchar(255) DEFAULT NULL, + `Address_Line_1` varchar(255) DEFAULT NULL, + `Address_Line_2` varchar(255) DEFAULT NULL, + `City` varchar(20) DEFAULT NULL, + `State` varchar(20) DEFAULT NULL, + `ZipCode` varchar(5) DEFAULT NULL, + `ZipCode_safe` varchar(10) DEFAULT NULL, + `Country_Code` varchar(255) DEFAULT NULL, + `International` tinyint(1) DEFAULT NULL, + `Latitude` varchar(255) DEFAULT NULL, + `Longitude` varchar(255) DEFAULT NULL, + `Pharmacy_Phone` varchar(255) DEFAULT NULL, + `Pharmacy_Phone_safe` varchar(255) DEFAULT NULL, + `Pharmacy_Fax` varchar(255) DEFAULT NULL, + `Types` varchar(255) DEFAULT NULL, + `Script_Msg_Accepted` varchar(255) DEFAULT NULL, + `Specialized_Msg_Accepted` varchar(255) DEFAULT NULL, + `Connectivity_Status` varchar(255) DEFAULT NULL, + `Accept_TSO` varchar(255) DEFAULT NULL, + `DEA_Audit_Exp` varchar(255) DEFAULT NULL, + `Test_Pharmacy` varchar(5) DEFAULT NULL, + `State_Wide_Mail_Order` varchar(6) NOT NULL, + `Created` datetime DEFAULT NULL, + `Modified` datetime DEFAULT NULL, + `Deleted` datetime DEFAULT NULL, + `24HR` varchar(3) DEFAULT NULL, + `on_weno` tinytext, + PRIMARY KEY (`id`), + UNIQUE KEY `ncpdp` (`NCPDP`) +) ENGINE=InnoDB; +#EndIf + +#IfNotTable weno_assigned_pharmacy +CREATE TABLE `weno_assigned_pharmacy` ( + `id` INT(10) NOT NULL AUTO_INCREMENT, + `pid` BIGINT(20) NOT NULL, + `primary_ncpdp` VARCHAR(8) NOT NULL, + `alternate_ncpdp` VARCHAR(8) NOT NULL, + KEY (`pid`), + PRIMARY KEY(`id`) +) ENGINE=InnoDB; +#EndIf + +#IfNotTable weno_download_log +CREATE TABLE `weno_download_log` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `value` VARCHAR(12) NOT NULL, + `status` VARCHAR(10) NOT NULL, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `value` (`value`) +) ENGINE=InnoDB; +#EndIf + +#IfNotRow background_services name WenoExchangePharmacies +INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) +VALUES ('WenoExchangePharmacies', 'Weno Exchange Pharmacy', '0', '0', current_timestamp(), '1440', 'downloadWenoPharmacy', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); +#EndIf + +#IfNotRow background_services name WenoExchange +INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) +VALUES ('WenoExchange', 'Weno Log Sync', '0', '0', current_timestamp(), '1440', 'downloadWenoPrescriptionLog', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); +#EndIf + +-- For early adopters of weno, incase they need to upgrade to the next/latest release of openEMR +#IfRow background_services name WenoExchange +UPDATE `background_services` SET title="Weno Log Sync", `function`="downloadWenoPrescriptionLog", `require_once`="/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php" WHERE `name`="WenoExchange"; +#EndIf + +#IfRow globals gl_name weno_provider_password +UPDATE `globals` SET gl_name="weno_admin_password" WHERE gl_name="weno_provider_password"; +#EndIf + +#IfRow globals gl_name weno_provider_username +UPDATE `globals` SET gl_name="weno_admin_username" WHERE gl_name="weno_provider_username"; +#EndIf + diff --git a/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php b/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php new file mode 100644 index 00000000000..6d83a544aca --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php @@ -0,0 +1,281 @@ +addGlobalSettings(); + $this->registerMenuItems(); + $this->registerDemographicsEvents(); + $this->demographicsSelectorEvents(); + $this->demographicsDisplaySelectedEvents(); + $this->patientSaveEvents(); + $this->patientUpdateEvents(); + } + + public function __construct(EventDispatcher $dispatcher, ?Kernel $kernel = null) + { + if (empty($kernel)) { + $kernel = new Kernel(); + } + $this->eventDispatcher = $dispatcher; + + $this->globalsConfig = new WenoGlobalConfig($GLOBALS); + $this->moduleDirectoryName = basename(dirname(__DIR__)); + $this->modulePath = dirname(__DIR__); + $this->logger = new SystemLogger(); + $this->selectedPatientPharmacy = new SelectedPatientPharmacy(); + } + + /** + * @return \Twig\Environment + */ + public function getTwig() + { + return $this->twig; + } + + public function addGlobalWenoSettings(GlobalsInitializedEvent $event) + { + $settings = $this->globalsConfig->getGlobalSettingSectionConfiguration(); + + $userMode = (array_key_exists('mode', $_GET) && $_GET['mode'] == 'user'); + + $service = $event->getGlobalsService(); + $service->addUserSpecificTab(self::MODULE_MENU_NAME); + + foreach ($settings as $key => $config) { + $value = $GLOBALS[$key] ?? $config['default']; + if ($userMode) { + $service->appendToSection( + self::MODULE_MENU_NAME, + $key, + new GlobalSetting( + xlt($config['title']), + $config['type'], + $value, + xlt($config['description']), + $config['user_setting'] + ) + ); + } else { + if ($config['user_setting']) { + continue; + } + $service->appendToSection( + self::MODULE_MENU_NAME, + $key, + new GlobalSetting( + xlt($config['title']), + $config['type'], + $value, + xlt($config['description']), + $config['user_setting'] + ) + ); + } + } + } + + public function registerDemographicsEvents() + { + $this->eventDispatcher->addListener(pRenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, [$this, 'renderWenoSection']); + } + + public function renderWenoSection(pRenderEvent $event) + { + $path = __DIR__; + $path = str_replace("src", "templates", $path); + + $pid = $event->getPid(); + ?> +
+ + +
+
+ eventDispatcher->addListener(GlobalsInitializedEvent::EVENT_HANDLE, [$this, 'addGlobalWenoSettings']); + } + + public function registerMenuItems() + { + $this->eventDispatcher->addListener(MenuEvent::MENU_UPDATE, [$this, 'addCustomMenuItem']); + } + + public function addCustomMenuItem(MenuEvent $event) + { + $menu = $event->getMenu(); + //Prescription Log + $menuItem = new \stdClass(); + $menuItem->requirement = 0; + $menuItem->target = 'rep'; + $menuItem->menu_id = 'rep0'; + $menuItem->label = xlt("Prescription Log"); + $menuItem->url = self::MODULE_INSTALLATION_PATH . "/templates/rxlogmanager.php"; + $menuItem->children = []; + $menuItem->acl_req = ["patients", "rx"]; + $menuItem->global_req = ["weno_rx_enable"]; + + //Weno Management + $mgtMenu = new \stdClass(); + $mgtMenu->requirement = 0; + $mgtMenu->target = 'adm0'; + $mgtMenu->menu_id = 'adm'; + $mgtMenu->label = xlt("Weno Management"); + $mgtMenu->url = self::MODULE_INSTALLATION_PATH . "/templates/facilities.php"; + $mgtMenu->children = []; + $mgtMenu->acl_req = ["admin", "super"]; + $mgtMenu->global_req = ["weno_rx_enable"]; + + foreach ($menu as $item) { + if ($item->menu_id == 'admimg') { + foreach ($item->children as $other) { + if ($other->label == 'Other') { + $other->children[] = $mgtMenu; + break; + } + } + } + + if ($item->menu_id == 'repimg') { + foreach ($item->children as $clientReport) { + if ($clientReport->label == 'Clients') { + $clientReport->children[] = $menuItem; + break; + } + } + } + } + + $event->setMenu($menu); + + return $event; + } + + public function demographicsSelectorEvents() + { + $this->eventDispatcher->addListener(RenderPharmacySectionEvent::RENDER_AFTER_PHARMACY_SECTION, [$this, 'renderWenoPharmacySelector']); + } + + public function renderWenoPharmacySelector() + { + include_once($this->modulePath) . "/templates/pharmacy_list_form.php"; + } + + public function demographicsDisplaySelectedEvents() + { + $this->eventDispatcher->addListener(RenderPharmacySectionEvent::RENDER_AFTER_SELECTED_PHARMACY_SECTION, [$this, 'renderSelectedWenoPharmacies']); + } + + public function renderSelectedWenoPharmacies() + { + echo "
"; + include_once($this->modulePath) . "/templates/pharmacy_list_display.php"; + } + + public function patientSaveEvents() + { + $this->eventDispatcher->addListener(PatientBeforeCreatedAuxEvent::EVENT_HANDLE, [$this, 'persistPatientWenoPharmacies']); + } + + public function persistPatientWenoPharmacies(PatientBeforeCreatedAuxEvent $event) + { + $patientData = $event->getPatientData(); + $this->selectedPatientPharmacy->prepSelectedPharmacy($patientData); + } + + public function patientUpdateEvents() + { + $this->eventDispatcher->addListener(PatientUpdatedEventAux::EVENT_HANDLE, [$this, 'updatePatientWenoPharmacies']); + } + + public function updatePatientWenoPharmacies(PatientUpdatedEventAux $event) + { + $updatedPatientData = $event->getUpdatedPatientData(); + $this->selectedPatientPharmacy->prepForUpdatePharmacy($updatedPatientData); + } +} + +?> diff --git a/src/Rx/Weno/Container.php b/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php similarity index 96% rename from src/Rx/Weno/Container.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/Container.php index bbab89000c5..0367820a5a9 100644 --- a/src/Rx/Weno/Container.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php @@ -8,7 +8,7 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; /** * Class Container diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php new file mode 100644 index 00000000000..bf494940d6c --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php @@ -0,0 +1,98 @@ + + * @copyright Copyright (c) 2023 Sherwin Gaddis + * + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use OpenEMR\Common\Logging\EventAuditLogger; +use OpenEMR\Modules\WenoModule\Services\WenoLogService; +use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesImport; + +class DownloadWenoPharmacies +{ + public function retrieveDataFile($url, $storelocation) + { + $path_to_extract = $storelocation; + $storelocation .= "weno_pharmacy.zip"; + if (!is_dir($path_to_extract)) { + mkdir($path_to_extract, 0775, true); + } + $fp = fopen($storelocation, 'w+'); + + $ch = curl_init($url); + + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 1000); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); + curl_exec($ch); + + curl_close($ch); + fclose($fp); + + $result = $this->extractFile($path_to_extract, $storelocation); + if ($result == "Imported") { + return "complete"; + } else { + return "failed"; + } + } + + public function extractFile($path_to_extract, $storelocation) + { + $zip = new \ZipArchive(); + $wenolog = new WenoLogService(); + $import = new WenoPharmaciesImport(); + + if ($zip->open($storelocation) === true) { + $zip->extractTo($path_to_extract); + + $files = glob($path_to_extract . "/*.csv"); + if ($files) { + $csvFile = $files[1]; + $filename = basename($csvFile); + $csvFilename = $filename; + + EventAuditLogger::instance()->newEvent( + "prescriptions_log", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "File extracted successfully." + ); + echo 'File extracted successfully.'; + echo 'CSV filename: ' . $csvFilename; + + $zip->close(); + unlink($storelocation); + $result = $import->importPharmacy($csvFile, $files); + if ($result == "Imported") { + $wenolog->insertWenoLog("pharmacy", "Success"); + } + + return "Imported"; + } else { + EventAuditLogger::instance()->newEvent( + "prescriptions_log", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "No CSV file found in the zip archive." + ); + $wenolog->insertWenoLog("pharmacy", "Failed"); + return "Failed"; + } + } else { + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Failed to extract the file."); + echo 'Failed to extract the file.'; + error_log("Failed to extract the file."); + $wenolog->insertWenoLog("pharmacy", "Failed"); + } + } +} diff --git a/src/Rx/Weno/FacilityProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php similarity index 95% rename from src/Rx/Weno/FacilityProperties.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php index a1d4be889a8..8f837f343f2 100644 --- a/src/Rx/Weno/FacilityProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php @@ -8,7 +8,7 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; class FacilityProperties { diff --git a/src/Rx/Weno/LogDataInsert.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php similarity index 55% rename from src/Rx/Weno/LogDataInsert.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php index ce544e8996d..912a659c7ef 100644 --- a/src/Rx/Weno/LogDataInsert.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php @@ -4,11 +4,15 @@ * @package OpenEMR * @link http://www.open-emr.org * @author Sherwin Gaddis + * @author Kofi Appiah * @copyright Copyright (c) 2020 Sherwin Gaddis + * @copyright Copyright (c) 2023 Omega Systems Group International * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; + +use Exception; class LogDataInsert { @@ -17,40 +21,34 @@ public function __construct() } public function insertPrescriptions($insertdata) { - $sql = "INSERT INTO prescriptions SET " - . "id = ?, " - . "active = ?, " - . "date_added = ?, " - . "patient_id = ?, " - . "drug = ?, " - . "form = ?, " - . "quantity = ?, " - . "refills = ?, " - . "substitute = ?," - . "note = ?, " - . "rxnorm_drugcode = ?, " - . "external_id = ?, " - . "indication = ?, " - . "txDate = ? "; + $sql = "INSERT INTO prescriptions SET "; + $sql .= "active = ?, "; + $sql .= "date_added = NOW(), "; + $sql .= "patient_id = ?, "; + $sql .= "drug = ?, "; + $sql .= "encounter = ?, "; + $sql .= "quantity = ?, "; + $sql .= "refills = ?, "; + $sql .= "substitute = ?,"; + $sql .= "note = ?, "; + $sql .= "rxnorm_drugcode = ?, "; + $sql .= "external_id = ?, "; + $sql .= "indication = ? "; try { sqlInsert($sql, [ - $insertdata['id'], $insertdata['active'], - $insertdata['date_added'], $insertdata['patient_id'], $insertdata['drug'], - $insertdata['form'], + $insertdata['encounter'], $insertdata['quantity'], $insertdata['refills'], $insertdata['substitute'], $insertdata['note'], $insertdata['rxnorm_drugcode'], $insertdata['provider_id'], - $insertdata['prescriptionguid'], - $insertdata['txDate'] + $insertdata['prescriptionguid'] ]); - echo "inserted data!
"; } catch (Exception $e) { return $e->getMessage(); } diff --git a/src/Rx/Weno/LogImportBuild.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php similarity index 88% rename from src/Rx/Weno/LogImportBuild.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php index 3757d1c8613..ef194057853 100644 --- a/src/Rx/Weno/LogImportBuild.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php @@ -8,7 +8,7 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; class LogImportBuild { @@ -17,7 +17,7 @@ class LogImportBuild public function __construct() { $this->insertdata = new LogDataInsert(); - $this->rxsynclog = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/logsync.csv"; + $this->rxsynclog = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/logsync.csv"; } public function prescriptionId() @@ -59,7 +59,7 @@ public function buildInsertArray() continue; } if (isset($line[4])) { - $this->messageid = isset($line[4]) ? $line[4] : null; + $this->messageid = $line[4] ?? null; $is_saved = $this->checkMessageId(); if ($is_saved > 0) { continue; @@ -76,9 +76,11 @@ public function buildInsertArray() $month = $idate[0] ?? null; $day = $idate[1] ?? null; $idate = $year . '-' . $month . '-' . $day; - $ida = filter_var($idate, FILTER_SANITIZE_NUMBER_INT); + $ida = preg_replace('/T/', ' ', $line[0]); $p = $line[1] ?? null; - $pid = filter_var($p, FILTER_SANITIZE_NUMBER_INT); + $pid_and_encounter = explode(":", $p); + $pid = intval($pid_and_encounter[0]); + $encounter = intval($pid_and_encounter[1]); $r = $line[22] ?? null; $refills = filter_var($r, FILTER_SANITIZE_NUMBER_INT); @@ -87,12 +89,11 @@ public function buildInsertArray() $insertdata['id'] = $rec; $active = 1; $insertdata['active'] = $active; - $insertdata['date_added'] = $ida; + $insertdata['date_added'] = $ida; $insertdata['patient_id'] = $pid; + $insertdata['encounter'] = $encounter; $drug = isset($line[11]) ? str_replace('"', '', $line[11]) : null; $insertdata['drug'] = $drug; - $type = $this->drugForm($line[19]); - $insertdata['form'] = $type ?? null; $insertdata['quantity'] = $line[18] ?? null; $insertdata['refills'] = $refills; $sub = ($line[14] = 'Allowed' ? 1 : 0); diff --git a/src/Rx/Weno/LogProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php similarity index 64% rename from src/Rx/Weno/LogProperties.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php index e0e88f798b9..110a7fee76e 100644 --- a/src/Rx/Weno/LogProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php @@ -8,11 +8,12 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; use Exception; use OpenEMR\Common\Crypto\CryptoGen; use OpenEMR\Common\Logging\EventAuditLogger; +use OpenEMR\Modules\WenoModule\Services\WenoLogService; class LogProperties { @@ -36,6 +37,14 @@ class LogProperties * @var false|string */ private $enc_key; + /** + * @var false|string + */ + private $weno_admin_email; + /** + * @var false|string + */ + private $weno_admin_password; /** * @var CryptoGen */ @@ -58,14 +67,14 @@ class LogProperties */ public function __construct() { - $this->container = new Container(); $this->cryptoGen = new CryptoGen(); $this->method = "aes-256-cbc"; - $this->rxsynclog = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/logsync.csv"; + $this->rxsynclog = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/logsync.csv"; $this->enc_key = $this->cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); $this->key = substr(hash('sha256', $this->enc_key, true), 0, 32); $this->iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0); - $this->provider = $this->container->getTransmitproperties(); + $this->weno_admin_email = $GLOBALS['weno_admin_username']; + $this->weno_admin_password = $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); } /** @@ -73,11 +82,10 @@ public function __construct() */ public function logEpcs() { - $email = $this->provider->getProviderEmail(); - $prov_pass = $this->provider->getProviderPassword(); // gets the password stored for the + $email['email'] = $this->weno_admin_email; + $prov_pass = $this->weno_admin_password; // gets the password stored for the $md5 = md5($prov_pass); // hash the current password $workday = date("l"); - //This is to cover working on Saturday but not on Sunday. //Checking Saturday for any prescriptions that were written. if ($workday == 'Monday') { $yesterday = date("Y-m-d", strtotime("-2 day")); @@ -85,11 +93,13 @@ public function logEpcs() $yesterday = date("Y-m-d", strtotime("yesterday")); } + $today = date("Y-m-d", strtotime("today")); + $p = [ "UserEmail" => $email['email'], "MD5Password" => $md5, "FromDate" => $yesterday, - "ToDate" => $yesterday, + "ToDate" => $today, "ResponseFormat" => "CSV" ]; $plaintext = json_encode($p); //json encode email and password @@ -105,8 +115,8 @@ public function logEpcs() */ public function logReview() { - $email = $this->provider->getProviderEmail(); - $prov_pass = $this->provider->getProviderPassword(); // gets the password stored for the + $email = $this->getProviderEmail(); + $prov_pass = $this->getProviderPassword(); $md5 = md5($prov_pass); // hash the current password $p = [ @@ -126,7 +136,9 @@ public function logReview() */ public function logSync() { - $provider_info = $this->provider->getProviderEmail(); + $provider_info['email'] = $this->weno_admin_email; + + $wenolog = new WenoLogService(); $logurlparam = $this->logEpcs(); $syncLogs = "https://online.wenoexchange.com/en/EPCS/DownloadNewRxSyncDataVal?useremail="; @@ -151,13 +163,61 @@ public function logSync() file_put_contents($this->rxsynclog, $rpt); $logstring = "prescription log import initiated successfully"; EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$logstring"); + $wenolog->insertWenoLog("prescription", "Success"); } else { EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$statusCode"); + $wenolog->insertWenoLog("prescription", "Failed"); + return false; } if (file_exists($this->rxsynclog)) { $log = new LogImportBuild(); $log->buildInsertArray(); + return true; + } + } + + /** + * @return mixed + */ + public function getProviderEmail() + { + if ($_SESSION['authUser']) { + $provider_info = ['email' => $GLOBALS['weno_provider_email']]; + if (!empty($provider_info)) { + return $provider_info; + } else { + $error = "Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"; + error_log($error); + exit; + } + } else if ($GLOBALS['weno_admin_username']) { + $provider_info["email"] = $GLOBALS['weno_admin_username']; + return $provider_info; + } else { + $error = "Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"; + error_log($error); + exit; + } + } + + /** + * @return mixed + */ + public function getProviderPassword() + { + if ($_SESSION['authUser']) { + if (!empty($GLOBALS['weno_admin_password'])) { + return $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); + } else { + echo xlt('Provider Password is missing'); + die; + } + } else if ($GLOBALS['weno_admin_password']) { + return $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); + } else { + error_log("Admin password not set"); + exit; } } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php new file mode 100644 index 00000000000..c906ec55336 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php @@ -0,0 +1,237 @@ + + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use Exception; + +class PharmacyService +{ + public function __construct() + { + } + + public function createWenoPharmaciesForPatient($pid, $data) + { + $sql = "INSERT INTO weno_assigned_pharmacy SET "; + $sql .= "pid = ?,"; + $sql .= "primary_ncpdp = ?,"; + $sql .= "alternate_ncpdp = ? "; + + try { + sqlInsert($sql, [ + $pid, + $data['primary_pharmacy'], + $data['alternate_pharmacy'], + ]); + } catch (Exception $e) { + return $e->getMessage(); + } + } + + public function updatePatientWenoPharmacy($pid, $data) + { + //check if pharmacies already exist for patient + if (!$this->getWenoPharmacy($pid)) { + return $this->createWenoPharmaciesForPatient($pid, $data); + } + $sql = "UPDATE weno_assigned_pharmacy SET "; + $sql .= "primary_ncpdp = ?, "; + $sql .= "alternate_ncpdp = ? "; + $sql .= "WHERE pid = ?"; + + try { + sqlInsert($sql, [ + $data['primary_pharmacy'], + $data['alternate_pharmacy'], + $pid + ]); + } catch (Exception $e) { + return $e->getMessage(); + } + } + + public function getPatientPrimaryPharmacy($pid) + { + $sql = "SELECT pd.pharmacy_id, pd.pid, p.id, p.name, " ; + $sql .= "a.foreign_id, a.city, a.line1 FROM patient_data pd "; + $sql .= "LEFT JOIN pharmacies p ON pd.pharmacy_id = p.id "; + $sql .= "LEFT JOIN addresses a ON p.id = a.foreign_id WHERE pd.pid = ?"; + + $result = sqlQuery($sql, [$pid]); + + return json_encode($result); + } + + public function getWenoPharmacyForPatient($pid) + { + if ($pid !== 0) { + $sql = "SELECT p.pid,p.weno_pharmacy, w.state,w.ncpdp,w.business_name,"; + $sql .= "w.address_line_1 FROM patient_data p "; + $sql .= "INNER JOIN weno_pharmacy w ON p.weno_pharmacy = w.ncpdp WHERE pid = ?"; + $result = sqlQuery($sql, array($pid)); + } + $pharmacy_data = array( + "name" => $result['business_name'] ?? '', + "ncpdp" => $result['ncpdp'] ?? '', + "state" => $result['state'] ?? '', + "address" => $result['address_line_1'] ?? '' + ); + + return json_encode($pharmacy_data); + } + + public function getWenoPrimaryPharm($pid) + { + $sql = "SELECT wap.pid, wap.primary_ncpdp, wp.business_name, "; + $sql .= "wp.city, wp.address_line_1, wp.ncpdp, wp.state FROM weno_assigned_pharmacy wap "; + $sql .= "INNER JOIN weno_pharmacy wp ON wap.primary_ncpdp = wp.ncpdp "; + $sql .= "WHERE wap.pid = ?"; + $result = sqlQuery($sql, array($pid)); + + return $result; + } + + public function getWenoAlternatePharm($pid) + { + $sql = "SELECT wap.pid, wap.alternate_ncpdp, wp.business_name, "; + $sql .= "wp.city, wp.address_line_1, wp.ncpdp, wp.state FROM weno_assigned_pharmacy wap "; + $sql .= "INNER JOIN weno_pharmacy wp ON wap.alternate_ncpdp = wp.ncpdp "; + $sql .= "WHERE wap.pid = ?"; + + $result = sqlQuery($sql, array($pid)); + + return $result; + } + + public function checkWenoPharmacyLog() + { + $db_exist = sqlStatement("SELECT * FROM weno_download_log LIMIT 1"); + if (empty($db_exist)) { + return "empty"; + } else { + return true; + } + } + + public function insertPharmacies($insertdata) + { + + $sql = "INSERT INTO weno_pharmacy SET "; + $sql .= "ncpdp = ?, "; + $sql .= "npi = ?, "; + $sql .= "business_name = ?, "; + $sql .= "address_line_1 = ?, "; + $sql .= "address_line_2 = ?, "; + $sql .= "city = ?, "; + $sql .= "state = ?, "; + $sql .= "zipcode = ?,"; + $sql .= "country_code = ?, "; + $sql .= "international = ?, "; + $sql .= "pharmacy_phone = ?, "; + $sql .= "on_weno = ?, "; + $sql .= "test_pharmacy = ?, "; + $sql .= "state_wide_mail_order = ?, "; + $sql .= "24hr = ? "; + + try { + sqlInsert($sql, [ + $insertdata['ncpdp'], + $insertdata['npi'], + $insertdata['business_name'], + $insertdata['address_line_1'], + $insertdata['address_line_2'], + $insertdata['city'], + $insertdata['state'], + $insertdata['zipcode'], + $insertdata['country'], + $insertdata['international'], + $insertdata['pharmacy_phone'], + $insertdata['on_weno'], + $insertdata['test_pharmacy'], + $insertdata['state_wide_mail'], + $insertdata['fullDay'], + ]); + } catch (Exception $e) { + return $e->getMessage(); + } + } + + public function updatePharmacies($insertdata) + { + $sql = "UPDATE weno_pharmacy SET "; + $sql .= "npi = ?, "; + $sql .= "business_name = ?, "; + $sql .= "address_line_1 = ?, "; + $sql .= "address_line_2 = ?, "; + $sql .= "city = ?, "; + $sql .= "state = ?, "; + $sql .= "zipcode = ?,"; + $sql .= "country_code = ?, "; + $sql .= "international = ?, "; + $sql .= "pharmacy_phone = ?, "; + $sql .= "test_pharmacy = ?, "; + $sql .= "state_wide_mail_order = ?, "; + $sql .= "24hr = ? "; + $sql .= "WHERE ncpdp = ?"; + + try { + sqlStatement($sql, [ + $insertdata['npi'], + $insertdata['business_name'], + $insertdata['address_line_1'], + $insertdata['address_line_2'], + $insertdata['city'], + $insertdata['state'], + $insertdata['zipcode'], + $insertdata['country'], + $insertdata['international'], + $insertdata['pharmacy_phone'], + $insertdata['test_pharmacy'], + $insertdata['state_wide_mail'], + $insertdata['fullDay'], + $insertdata['ncpdp'] + ]); + } catch (Exception $e) { + return $e->getMessage(); + } + } + + public function removeWenoPharmacies() + { + $sql = "TRUNCATE TABLE weno_pharmacy"; + sqlStatement($sql); + } + + public function checkWenoDb() + { + $has_data = sqlQuery("SELECT 1 FROM weno_pharmacy LIMIT 1"); + if (!empty($has_data)) { + return true; + } else { + return false; + } + } + + public function getWenoPharmacy($pid) + { + $sql = "SELECT * FROM weno_assigned_pharmacy WHERE pid = ?"; + + $result = sqlStatement($sql, [$pid]); + + if (sqlNumRows($result) <= 0) { + return false; + } else { + return $result; + } + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/SelectedPatientPharmacy.php b/interface/modules/custom_modules/oe-module-weno/src/Services/SelectedPatientPharmacy.php new file mode 100644 index 00000000000..55209a1ed5a --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/SelectedPatientPharmacy.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (c) 2024 Omegasystems Group Intl + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +class SelectedPatientPharmacy +{ + public function __construct() + { + } + + public function prepSelectedPharmacy(array $data) + { + $newData = array( + "primary_pharmacy" => $_POST['primary_pharmacy'], + "alternate_pharmacy" => $_POST['alternate_pharmacy'] + ); + $pharmacyService = new PharmacyService(); + $pharmacyService->createWenoPharmaciesForPatient($data['pid'], $newData); + } + + public function prepForUpdatePharmacy($data) + { + $updateData = array( + "primary_pharmacy" => $data['primary_pharmacy'], + "alternate_pharmacy" => $data['alternate_pharmacy'] + ); + $pharmacyService = new PharmacyService(); + $pharmacyService->updatePatientWenoPharmacy($data['pid'], $updateData); + } +} diff --git a/src/Rx/Weno/TransmitProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php similarity index 50% rename from src/Rx/Weno/TransmitProperties.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php index 9b652b6cafc..311b8011108 100644 --- a/src/Rx/Weno/TransmitProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php @@ -3,14 +3,16 @@ /** * TransmitProperties class. * - * @package OpenEMR - * @link http://www.open-emr.org - * @author Sherwin Gaddis + * @package OpenEMR + * @link http://www.open-emr.org + * @author Sherwin Gaddis + * @author Kofi Appiah * @copyright Copyright (c) 2016-2017 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -namespace OpenEMR\Rx\Weno; +namespace OpenEMR\Modules\WenoModule\Services; use OpenEMR\Common\Crypto\CryptoGen; @@ -25,21 +27,25 @@ class TransmitProperties private $subscriber; private $ncpdp; private $cryptoGen; + private $pharmacy; + private $encounter; /** * AdminProperties constructor. */ public function __construct() { - $this->cryptoGen = new CryptoGen(); - $this->ncpdp = $this->getPharmacy(); - $this->vitals = $this->getVitals(); - $this->patient = $this->getPatientInfo(); + $this->cryptoGen = new CryptoGen(); + $this->ncpdp = $this->getPharmacy(); + $this->vitals = $this->getVitals(); + $this->patient = $this->getPatientInfo(); $this->provider_email = $this->getProviderEmail(); - $this->provider_pass = $this->getProviderPassword(); - $this->locid = $this->getFacilityInfo(); - $this->payload = $this->createJsonObject(); - $this->subscriber = $this->getSubscriber(); + $this->provider_pass = $this->getProviderPassword(); + $this->locid = $this->getFacilityInfo(); + $this->pharmacy = $this->getPharmacy(); + $this->payload = $this->createJsonObject(); + $this->subscriber = $this->getSubscriber(); + $this->encounter = $this->getEncounter(); } /** @@ -64,7 +70,7 @@ public function createJsonObject() $wenObj['LocationID'] = $this->locid['weno_id']; $wenObj['TestPatient'] = $mode; $wenObj['PatientType'] = 'Human'; - $wenObj['OrgPatientID'] = $this->patient['pid']; + $wenObj['OrgPatientID'] = $this->patient['pid'] . ":" . $this->getEncounter(); $wenObj['LastName'] = $this->patient['lname']; $wenObj['FirstName'] = $this->patient['fname']; @@ -83,6 +89,11 @@ public function createJsonObject() $wenObj['HeightWeightObservationDate'] = $heighDate[0]; $wenObj["ResponsiblePartySameAsPatient"] = 'Y'; $wenObj['PatientLocation'] = "Home"; + + $wenObj['PrimaryPharmacyNCPCP'] = $this->pharmacy['primary']; + $wenObj['AlternativePharmacyNCPCP'] = $this->pharmacy['alternate']; + + //add insurance return json_encode($wenObj); } @@ -91,9 +102,9 @@ public function createJsonObject() */ public function getProviderEmail() { - $provider_info = sqlQuery("select email from users where username=? ", [$_SESSION["authUser"]]); + $provider_info = ['email' => $GLOBALS['weno_provider_email']]; if (empty($provider_info['email'])) { - echo xlt('Provider email address is missing. Go to address book to add providers email address'); + echo xlt('Provider email address is missing. Go to [User Settings select Weno Tab] and enter your Weno Provider Password'); exit; } else { return $provider_info; @@ -109,10 +120,10 @@ public function getFacilityInfo() if (empty($locid['weno_id'])) { //if not in an encounter then get the first facility location id as default - $default_facility = sqlQuery("select name, street, city, state, postal_code, phone, fax, weno_id from facility order by id asc limit 1"); + $default_facility = sqlQuery("SELECT name, street, city, state, postal_code, phone, fax, weno_id from facility order by id asc limit 1"); if (empty($default_facility)) { - echo xlt('Facility ID is missing'); + echo xlt('Facility ID is missing. head over to Admin -> Other -> Weno Management. Enter the Weno ID of your facility'); exit; } else { return $default_facility; @@ -129,37 +140,43 @@ private function getPatientInfo() //get patient data if in an encounter //Since the transmitproperties is called in the logproperties //need to check to see if in an encounter or not. Patient data is not required to view the Weno log + // TODO sjp To do prescriptions having to hava an active encounter isn't normal. + // TODO if required by Weno then completely changes Rx workflow and WILL cause push back from users. + $log = ''; + $missing = 0; if (empty($_SESSION['encounter'])) { - die("please select an encounter"); + //die("please select an encounter"); + $log .= xlt("Please select an encounter") . "
"; + ++$missing; } - $missing = 0; $patient = sqlQuery("select title, fname, lname, mname, street, state, city, email, phone_cell, postal_code, dob, sex, pid from patient_data where pid=?", [$_SESSION['pid']]); if (empty($patient['fname'])) { - echo xlt("First Name Missing") . "
"; + $log .= xlt("First Name Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . ""; + $log .= xlt("Last Name Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['dob'])) { - echo xlt("Date of Birth Missing") . "
"; + $log .= xlt("Date of Birth Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['sex'])) { - echo xlt("Gender Missing") . "
"; + $log .= xlt("Gender Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['postal_code'])) { - echo xlt("Zip Code Missing") . "
"; + $log .= xlt("Zip Code Missing, head over to the Patient Chart select Demographics select Contact select Postal Code. Save and retry") . "
"; ++$missing; } if (empty($patient['street'])) { - echo xlt("Street Address incomplete Missing") . "
"; + $log .= xlt("Street Address incomplete Missing, head over to the Patient Chart select Demographics select Contact. Save and retry") . "
"; ++$missing; } if ($missing > 0) { - die('Pleasae add the missing data and try again'); + echo "
" . $log . "
"; + die('Please add the missing data and try again'); } return $patient; } @@ -188,9 +205,9 @@ public function cipherpayload() public function getProviderPassword() { $uid = $_SESSION['authUserID']; - $sql = "select setting_value from user_settings where setting_user = ? and setting_label = 'global:weno_provider_password'"; + $sql = "select setting_value from user_settings where setting_user = ? and setting_label = 'global:weno_admin_password'"; $prov_pass = sqlQuery($sql, [$uid]); - if (!empty($prov_pass['setting_value'])) { + if (!empty($GLOBALS['weno_admin_password'])) { return $this->cryptoGen->decryptStandard($prov_pass['setting_value']); } else { echo xlt('Provider Password is missing'); @@ -201,7 +218,7 @@ public function getProviderPassword() /** * @return mixed */ - private function getVitals() + public function getVitals() { $vitals = sqlQuery("select date, height, weight from form_vitals where pid = ? ORDER BY id DESC", [$_SESSION["pid"] ?? null]); return $vitals; @@ -218,8 +235,90 @@ private function getSubscriber() */ public function getPharmacy() { - $sql = "SELECT p.ncpdp FROM pharmacies p JOIN patient_data pd ON p.id = pd.pharmacy_id WHERE pd.pid = ? "; - $give = sqlQuery($sql, [$_SESSION['pid'] ?? null]); - return $give['ncpdp'] ?? null; + $data = sqlQuery("SELECT * FROM `weno_assigned_pharmacy` WHERE `pid` = ? ", [$_SESSION["pid"]]); + if (empty($data)) { + die("Weno Pharmacies not set. head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Pharmacies"); + } + $response = array( + "primary" => $data['primary_ncpdp'], + "alternate" => $data['alternate_ncpdp'] + ); + + if (empty($response['primary'])) { + die("Weno Primary Pharmacy not set. Head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Primary Pharmacy"); + } + + if (empty($response['alternate'])) { + die("Weno Alternate Pharmacy not set. Head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Primary Pharmacy"); + } + return $response; + } + + public function wenoChr() + { + return + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0) . + chr(0x0); + } + + public function wenoMethod(): string + { + return "aes-256-cbc"; + } + + /** + * @return mixed + */ + public function getProviderName() + { + $provider_info = sqlQuery("select fname, mname, lname from users where username=? ", [$_SESSION["authUser"]]); + + return $provider_info['fname'] . " " . $provider_info['mname'] . " " . $provider_info['lname']; + } + + /** + * @return mixed + */ + public function getPatientName() + { + $patient_info = sqlQuery("select fname, mname, lname from patient_data where pid=? ", [$_SESSION["pid"]]); + + return $patient_info['fname'] . " " . $patient_info['mname'] . " " . $patient_info['lname']; + } + + /** + * @return mixed + */ + public function getWenoAltPharmacies() + { + $data = sqlQuery("SELECT * FROM weno_assigned_pharmacy WHERE pid = ? ", [$_SESSION["pid"]]); + $response = array( + "primary" => $data['primary_ncpdp'], + "alternate" => $data['alternate_ncpdp'] + ); + return $response; + } + + private function getEncounter() + { + if (!$_SESSION['encounter']) { + die("Please select an encounter to continue"); + } + + return $_SESSION['encounter']; } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php new file mode 100644 index 00000000000..25a557b72ac --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php @@ -0,0 +1,57 @@ + + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use Exception; + +class WenoLogService +{ + public function __construct() + { + } + + public function getLastPrescriptionLogStatus() + { + $params = "prescription"; + $sql = "SELECT * FROM weno_download_log WHERE "; + $sql .= "VALUE = ? ORDER BY created_at DESC LIMIT 1"; + + $result = sqlQuery($sql, [$params]); + + return $result; + } + + public function getLastPharmacyDownloadStatus() + { + $params = "pharmacy"; + $sql = "SELECT * FROM weno_download_log WHERE "; + $sql .= "VALUE = ? ORDER BY created_at DESC LIMIT 1"; + + $result = sqlQuery($sql, [$params]); + + return $result; + } + + public function insertWenoLog($value, $status) + { + $sql = "INSERT INTO weno_download_log SET "; + $sql .= "value = ?, "; + $sql .= "status = ? "; + + try { + sqlInsert($sql, [$value, $status]); + } catch (Exception $e) { + return $e->getMessage(); + } + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php new file mode 100644 index 00000000000..d60dd09d03b --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php @@ -0,0 +1,86 @@ + + * @copyright Copyright (c) 2020 Sherwin Gaddis + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Modules\WenoModule\Services\PharmacyService; + +class WenoPharmaciesJson +{ + private CryptoGen $cryptoGen; + private string $encrypted; + + final public function __construct( + CryptoGen $cryptoGen + ) { + $this->cryptoGen = $cryptoGen; + $job_j = $this->buildJson(); + $method = "aes-256-cbc"; + $key = substr(hash('sha256', $this->wenoEncryptionKey(), true), 0, 32); + $iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);//$this->provider->wenoChr(); + $this->encrypted = base64_encode(openssl_encrypt($job_j, $method, $key, OPENSSL_RAW_DATA, $iv)); + } + + public function storePharmacyDataJson() + { + $url = $this->wenoPharmacyDirectoryLink() . "?useremail=" . urlencode($this->providerEmail()) . "&data=" . urlencode($this->encrypted); + $getWenoPharmaciesCsv = new DownloadWenoPharmacies(); + $storageLocation = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/"; + $c = $getWenoPharmaciesCsv->retrieveDataFile($url, $storageLocation); + } + + private function buildJson() + { + $checkWenoDb = new PharmacyService(); + $has_data = $checkWenoDb->checkWenoDb(); + $jobj = [ + "UserEmail" => $this->providerEmail(), + "MD5Password" => $this->providerPassword(), + "ExcludeNonWenoTest" => "N", + "Daily" => 'N' + ]; + + if (date("l") != "Monday" && $has_data) { + $jobj["Daily"] = "Y"; + } + + return json_encode($jobj); + } + private function providerEmail() + { + return $GLOBALS['weno_admin_username']; + } + + private function providerPassword(): string + { + return md5($this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password'])); + } + private function wenoEncryptionKey() + { + return $this->cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); + } + + private function wenoPharmacyDirectoryLink(): string + { + return "https://online.wenoexchange.com/en/EPCS/DownloadPharmacyDirectory"; + } + + public function checkBackgroundService(): string + { + $sql = "SELECT active FROM background_services WHERE name = 'WenoExchangePharmacies'"; + $activeStatus = sqlQuery($sql); + if ($activeStatus['active'] == 0) { + sqlStatement("UPDATE background_service SET `active` = 1, WHERE name = 'WenoExchangePharmacies'"); + return "active"; + } + return "live"; + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php b/interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php new file mode 100644 index 00000000000..8a78cb55701 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php @@ -0,0 +1,123 @@ + + * @copyright Copyright (c) 2020 Sherwin Gaddis + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use OpenEMR\Modules\WenoModule\Services\PharmacyService; + +class WenoPharmaciesImport +{ + public function __construct() + { + } + + public function importPharmacy($csvFile, $files) + { + $insertPharmacy = new PharmacyService(); + $insertdata = []; + $checkWenoDb = new PharmacyService(); + $has_data = $checkWenoDb->checkWenoDb(); + + $l = 0; + if (file_exists($csvFile)) { + $records = fopen($csvFile, "r"); + + while (!feof($records)) { + $line = fgetcsv($records); + + if ($l <= 1) { + $l++; + continue; + } + if (!isset($line[1])) { + continue; + } + if (!isset($line[1])) { + continue; + } + if (!empty($line)) { + if (date("l") == 'Monday' || !$has_data) { //build for weekly file + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[5]); + $business_name = $line[6]; + $address_line_1 = $line[7]; + $address_line_2 = $line[8]; + $city = $line[9]; + $state = $line[10]; + $zipcode = str_replace(['[', ']'], '', $line[11]); + $country = $line[12]; + $international = $line[13]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); + $on_weno = $line[21]; + $test_pharmacy = $line[17]; + $state_wide_mail = $line[18]; + $fullDay = $line[22]; + } else { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[7]); + $business_name = $line[8]; + $city = $line[11]; + $state = $line[12]; + $zipcode = str_replace(['[', ']'], '', $line[14]); + $country = $line[15]; + $address_line_1 = $line[9]; + $address_line_2 = $line[10]; + $international = $line[16]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); + $county = $line[33]; + $on_weno = $line[37]; + $compounding = $line[41]; + $medicaid_id = $line[45]; + $dea = $line[44]; + $test_pharmacy = $line[29]; + $fullDay = $line[40]; + $state_wide_mail = $line[47]; + } + + $insertdata['ncpdp'] = $ncpdp; + $insertdata['npi'] = $npi; + $insertdata['business_name'] = $business_name; + $insertdata['address_line_1'] = $address_line_1; + $insertdata['address_line_2'] = $address_line_2; + $insertdata['city'] = $city; + $insertdata['state'] = $state; + $insertdata['zipcode'] = $zipcode; + $insertdata['country'] = $country; + $insertdata['international'] = $international; + $insertdata['pharmacy_phone'] = $pharmacy_phone; + $insertdata['on_weno'] = $on_weno; + $insertdata['test_pharmacy'] = $test_pharmacy; + $insertdata['state_wide_mail'] = $state_wide_mail; + $insertdata['fullDay'] = $fullDay; + if ($has_data && date("l") == 'Monday') { + $insertPharmacy->updatePharmacies($insertdata); + } + if ($has_data && date("l") != 'Monday') { + $insertPharmacy->updatePharmacies($insertdata); + } + if (!$has_data) { + $insertPharmacy->insertPharmacies($insertdata); + } + + ++$l; + } + } + fclose($records); + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } + } + return "Imported"; + } else { + error_log("file missing"); + } + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php b/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php new file mode 100644 index 00000000000..cfb5398dedc --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php @@ -0,0 +1,122 @@ + + * @copyright Copyright (c) 2023 Omega Systems Group + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + + namespace OpenEMR\Modules\WenoModule; + +use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Services\Globals\GlobalSetting; +use OpenEMR\Services\Globals\GlobalsService; + +class WenoGlobalConfig +{ + //globals variable + const WENO_ENCRYPTION_KEY = 'weno_encryption_key'; + const WENO_ADMIN_USERNAME = 'weno_admin_username'; + const WENO_ADMIN_PASSWORD = 'weno_admin_password'; + const WENO_SETUP_INSTRUCTION_LINK = 'weno_setup_instructions_link'; + const WENO_RX_ENABLE_TEST = 'weno_rx_enable_test'; + const WENO_RX_ENABLE = 'weno_rx_enable'; + const WENO_PROVIDER_PASSWORD = 'weno_provider_password'; + const WENO_PROVIDER_EMAIL = 'weno_provider_email'; + + const GLOBAL_SECTION_NAME = 'Weno'; + + /** + * @var CryptoGen + */ + private $cryptoGen; + + public function __construct() + { + $this->cryptoGen = new CryptoGen(); + } + + /** + * Returns true if all the weno settings have been configured. Otherwise, it returns false. + * @return bool + */ + public function isWenoConfigured() + { + $config = $this->getGlobalSettingSectionConfiguration(); + $keys = array_keys($config); + foreach ($keys as $key) { + $value = $this->getGlobalSetting($key); + + if (empty($value)) { + return false; + } + } + return true; + } + + public function getGlobalSetting($settingKey) + { + // don't like this as php 8.1 requires this but OpenEMR works with globals and this is annoying. + return $GLOBALS[$settingKey] ?? null; + } + + public function getGlobalSettingSectionConfiguration() + { + $settings = [ + self::WENO_RX_ENABLE => [ + 'title' => 'Enable Weno eRx Service' + ,'description' => xl('Enable Weno eRx Service') . ' ' . xl('Contact https://online.wenoexchange.com to sign up for Weno Free eRx service.') + ,'type' => GlobalSetting::DATA_TYPE_BOOL + ,'default' => '' + ,'user_setting' => false + ] + ,self::WENO_RX_ENABLE_TEST => [ + 'title' => xl('Enable Weno eRx Service Test mode') + ,'description' => xl('Enable Weno eRx Service Test mode. This option will automatically include test pharmacies in your pharmacy download') + ,'type' => GlobalSetting::DATA_TYPE_BOOL + ,'default' => '' + ,'user_setting' => false + ] + ,self::WENO_ENCRYPTION_KEY => [ + 'title' => xl('Weno Encryption Key') + ,'description' => xl('Encryption key issued by Weno eRx service on the Weno Developer Page') + ,'type' => GlobalSetting::DATA_TYPE_ENCRYPTED + ,'default' => '' + ,'user_setting' => false + ] + ,self::WENO_ADMIN_USERNAME => [ + 'title' => xl('Weno Admin Username') + ,'description' => xl('This is required for Weno Pharmacy Directory Download in Background Services. Same as email for logging in into Weno') + ,'type' => GlobalSetting::DATA_TYPE_TEXT + ,'default' => '' + ,'user_setting' => false + ] + ,self::WENO_ADMIN_PASSWORD => [ + 'title' => xl('Weno Admin Password') + ,'description' => xl('') + ,'type' => GlobalSetting::DATA_TYPE_ENCRYPTED + ,'default' => '' + ,'user_setting' => false + ] + ,self::WENO_PROVIDER_EMAIL => [ + 'title' => xl('Weno Provider Email') + ,'description' => xl('') + ,'type' => GlobalSetting::DATA_TYPE_TEXT + ,'default' => '' + ,'user_setting' => true + ] + ,self::WENO_PROVIDER_PASSWORD => [ + 'title' => xl('Weno Provider Password') + ,'description' => xl('') + ,'type' => GlobalSetting::DATA_TYPE_ENCRYPTED + ,'default' => '' + ,'user_setting' => true + ] + ]; + return $settings; + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/templates/facilities.php b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php new file mode 100644 index 00000000000..a8937c4a70e --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php @@ -0,0 +1,202 @@ + + * @author Kofi Appiah + * @copyright Copyright (c) 2020 Sherwin Gaddis + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +require_once(dirname(__DIR__, 4) . "/globals.php"); + +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Csrf\CsrfUtils; +use OpenEMR\Common\Twig\TwigContainer; +use OpenEMR\Core\Header; + +use OpenEMR\Modules\WenoModule\Services\FacilityProperties; +use OpenEMR\Modules\WenoModule\Services\WenoLogService; + +//ensure user has proper access +if (!AclMain::aclCheckCore('admin', 'super')) { + echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Weno Admin")]); + exit; +} + +$data = new FacilityProperties(); +$logService = new WenoLogService(); + +if ($_POST) { + if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token"])) { + CsrfUtils::csrfNotVerified(); + } + $data->facilityupdates = $_POST; + $data->updateFacilityNumber(); +} + +$facilities = $data->getFacilities(); +$pres_log = $logService->getLastPrescriptionLogStatus(); +$pharm_log = $logService->getLastPharmacyDownloadStatus(); + + +?> + + + <?php echo xlt('Weno Admin'); ?> + + + + + + +
+ + +
+
+


+

+ +
+ + + + + + + + + + "; + print ""; + print ""; + print ""; + ++$i; + } + ?> +
" . text($facility["name"]) . "" . text($facility['street']) + . "" . text($facility['city']) . "
+ +
+
+
+

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
#
1 + +
2 + +
+
+
+ + diff --git a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php new file mode 100644 index 00000000000..d690f23689b --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php @@ -0,0 +1,137 @@ + + * @author Kofi Appiah + * @copyright Copyright (c) 2020 Sherwin Gaddis + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +require_once("../../../../globals.php"); +require_once("$srcdir/patient.inc"); + +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Twig\TwigContainer; + +use OpenEMR\Modules\WenoModule\Services\PharmacyService; +use OpenEMR\Modules\WenoModule\Services\Container; + + +//ensure user has proper access +if (!AclMain::aclCheckCore('patients', 'rx')) { + echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Weno eRx")]); + exit; +} + +$pharmacyService = new PharmacyService(); +$prim_pharmacy = $pharmacyService->getWenoPrimaryPharm($_SESSION['pid']) ?? []; +$alt_pharmacy = $pharmacyService->getWenoAlternatePharm($_SESSION['pid']) ?? []; + + +$container = new Container(); + +$wenoProperties = $container->getTransmitproperties(); +$provider_info = $wenoProperties->getProviderEmail(); +$urlParam = $wenoProperties->cipherpayload(); //lets encrypt the data +//$logsync = $container->getLogproperties(); +//$logsync->logSync(); + +$vitals = $wenoProperties->getVitals(); +$provider_name = $wenoProperties->getProviderName(); +$patient_name = $wenoProperties->getPatientName(); +$facility_name = $wenoProperties->getFacilityInfo(); + +$newRxUrl = "https://online.wenoexchange.com/en/NewRx/ComposeRx?useremail="; +if ($urlParam == 'error') { //check to make sure there were no errors + echo xlt("Cipher failure check encryption key"); + exit; +} +?> + + + + + + + + <?php echo xlt('Weno eRx') ?> + + + + + +
+
+

+
+
+
+
+
+
:
+
+
+
:
+
+
+
+ : +
+
+
+
+ + + + + + + + + + + + + +
:
+
+
+
:
+
:
+
+
+
+
+ +
+
+ + + diff --git a/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_display.php b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_display.php new file mode 100644 index 00000000000..3352548b9df --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_display.php @@ -0,0 +1,40 @@ + + * @copyright Copyright (c) 2023 Omega Systems Group International. + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Modules\WenoModule\Services\PharmacyService; +use OpenEMR\Common\Twig\TwigContainer; + +if (!AclMain::aclCheckCore('patients', 'med')) { + echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Pharmacy Selector")]); + exit; +} + +$pharmacyService = new PharmacyService(); +$prim_pharmacy = $pharmacyService->getWenoPrimaryPharm($_SESSION['pid']) ?? []; +$alt_pharmacy = $pharmacyService->getWenoAlternatePharm($_SESSION['pid']) ?? []; + +$primary_pharmacy = $prim_pharmacy['business_name'] ?? '' . ' - ' . $prim_pharmacy['address_line_1'] ?? ''; +$alternate_pharmacy = $alt_pharmacy['business_name'] ?? '' . ' - ' . $alt_pharmacy['address_line_1'] ?? ''; +?> + +
+
+ + +
+
+ + +
+
diff --git a/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php new file mode 100644 index 00000000000..9857c3de3c6 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php @@ -0,0 +1,437 @@ + + * @copyright Copyright (c) 2023 Omega Systems Group International. + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +require_once $GLOBALS['srcdir'] . '/options.inc.php'; + +use OpenEMR\Modules\WenoModule\Services\PharmacyService; +use OpenEMR\Common\Csrf\CsrfUtils; +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Twig\TwigContainer; + +if (!AclMain::aclCheckCore('patients', 'med')) { + echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Pharmacy Selector")]); + exit; +} + +$widgetConstants = [ + 'listWithAddButton' => 26 + ,'textDate' => 4 + ,'textbox' => 2 +]; + +global $pid; // we need to grab our pid from our global settings. +$pid = ($frow['blank_form'] ?? null) ? 0 : $pid; + +// should always be set, but just in case we will set it to 0 so we can grab it +$field_id_esc = $field_id_esc ?? '0'; +$name_field_id = "form_" . $field_id_esc; +$smallform = $smallform ?? ''; + +$pharmacyService = new PharmacyService(); +$prev_prim_pharmacy = $pharmacyService->getWenoPrimaryPharm($_SESSION['pid']) ?? []; +$prev_alt_pharmacy = $pharmacyService->getWenoAlternatePharm($_SESSION['pid']) ?? []; +$prev_prim_pharmacy = json_encode($prev_prim_pharmacy); +$prev_alt_pharmacy = json_encode($prev_alt_pharmacy); + +$sql = "SELECT list_id, option_id, title FROM list_options WHERE list_id = 'state'"; +$res = sqlStatement($sql); + +?> + + + +
+ + + + diff --git a/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php new file mode 100644 index 00000000000..a145c2efdf2 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php @@ -0,0 +1,51 @@ + + * @copyright Copyright (c) 2021 Sherwin Gaddis + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + + require_once(dirname(__DIR__, 4) . "/globals.php"); + +use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Modules\WenoModule\Services\LogProperties; + +/* + * access control is on Weno side based on the user login + */ +if (!AclMain::aclCheckCore('patient', 'med')) { + echo xlt('Prescriptions Review Not Authorized'); + exit; +} + +$log_properties = new LogProperties(); +$logurlparam = $log_properties->logReview(); +$provider_info = $log_properties->getProviderEmail(); + +if ($logurlparam == 'error') { + echo xlt("Cipher failure check encryption key"); + exit; +} + +$url = "https://online.wenoexchange.com/en/EPCS/RxLog?useremail="; + +// I don't understand why you wouldn't escape email +// Let me know if there is a good reason not to. +//**warning** do not add urlencode to $provider_info['email']. +$urlOut = $url . urlencode($provider_info['email']) . "&data=" . urlencode($logurlparam); +// Setting a location header here overrides tab html and iFrame. +//header("Location: " . $urlOut); + +?> +<?php echo xlt("Weno RxLog") ?> +
+ +
diff --git a/interface/modules/custom_modules/oe-module-weno/templates/synch.php b/interface/modules/custom_modules/oe-module-weno/templates/synch.php new file mode 100644 index 00000000000..3b8fce90d55 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/synch.php @@ -0,0 +1,31 @@ + + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ +require_once(dirname(__DIR__, 4) . "/globals.php"); + +use OpenEMR\Modules\WenoModule\Services\LogProperties; +use OpenEMR\Common\Acl\AclMain; + +/* + * access control is on Weno side based on the user login + */ +if (!AclMain::aclCheckCore('patient', 'med')) { + echo xlt('Prescriptions Review Not Authorized'); + exit; +} + +$logproperties = new LogProperties(); +$result = $logproperties->logSync(); + + +if ($result == true) { + http_response_code(200); +} else { + http_response_code(500); +} diff --git a/interface/modules/custom_modules/oe-module-weno/templates/weno_fragment.php b/interface/modules/custom_modules/oe-module-weno/templates/weno_fragment.php new file mode 100644 index 00000000000..7cf6bd9080c --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/templates/weno_fragment.php @@ -0,0 +1,67 @@ + + * @copyright Copyright (c) 2023 omega systems group international + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +require_once(dirname(__DIR__, 4) . "/globals.php"); + +use OpenEMR\Common\Csrf\CsrfUtils; +use OpenEMR\Common\Acl\AclMain; + +if (!AclMain::aclCheckCore('patients', 'med')) { + exit; +} +$sql = "SELECT * FROM prescriptions WHERE patient_id = ? " . + "AND indication IS NOT NULL"; +$res = sqlStatement($sql, array($pid)); + +function getProviderByWenoId($external_id) +{ + $provider = sqlQuery("SELECT fname, mname, lname FROM users WHERE weno_prov_id = ? ", array($external_id)); + if ($provider) { + return $provider['fname'] . " " . $provider['mname'] . " " . $provider['lname']; + } else { + return ""; + } +} +?> + + + +
+
+ +
+ + + +
+ +
+ +
+ + + + + + + + + + + + + + + +
+
diff --git a/interface/modules/custom_modules/oe-module-weno/version.php b/interface/modules/custom_modules/oe-module-weno/version.php new file mode 100644 index 00000000000..9ae3836ec8c --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/version.php @@ -0,0 +1,11 @@ +getEventDispatcher()->dispatch(new PatientBeforeCreatedAuxEvent($pid, $_POST), PatientBeforeCreatedAuxEvent::EVENT_HANDLE, 10); + + $i1dob = DateToYYYYMMDD(filter_input(INPUT_POST, "i1subscriber_DOB")); $i1date = DateToYYYYMMDD(filter_input(INPUT_POST, "i1effective_date")); diff --git a/interface/patient_file/summary/demographics.php b/interface/patient_file/summary/demographics.php index 341b69c684c..1ef1417e1cf 100644 --- a/interface/patient_file/summary/demographics.php +++ b/interface/patient_file/summary/demographics.php @@ -397,11 +397,6 @@ function newEvt() { return false; } - function getWeno() { - top.restoreSession(); - location.href = '../../weno/indexrx.php' - } - function toggleIndicator(target, div) { // $mode = $(target).find(".indicator").text(); @@ -880,7 +875,7 @@ function setMyPatient() { } else { echo js_escape(" " . xl('DOB') . ": " . oeFormatShortDate($result['DOB_YMD']) . " " . xl('Age at death') . ": " . oeFormatAge($result['DOB_YMD'], $date_of_death)); } ?>); - var EncounterDateArray = new Array; + var EncounterDateArray = []; var CalendarCategoryArray = new Array; var EncounterIdArray = new Array; var Count = 0; @@ -1171,15 +1166,6 @@ function filterActiveIssues(array $i): array $viewArgs['title'] = 'Prescription History'; $viewArgs['btnLabel'] = 'Add'; $viewArgs['btnLink'] = "{$GLOBALS['webroot']}/interface/eRx.php?page=compose"; - } elseif ($GLOBALS['weno_rx_enable']) { - // weno plus button which opens their iframe - $viewArgs['weno'] = true; - $viewArgs['title'] = "WENO ComposeRx"; - $viewArgs['btnLabel'] = 'Add'; - $viewArgs['btnLink'] = "{$GLOBALS['webroot']}/interface/weno/indexrx.php"; - $viewArgs['btnClass'] = "iframe"; - $viewArgs['linkMethod'] = "javascript"; - $viewArgs['btnLink'] = "editScripts('{$GLOBALS['webroot']}/controller.php?prescription&list&id=" . attr_url($pid) . "')"; } else { $viewArgs['btnLink'] = "editScripts('{$GLOBALS['webroot']}/controller.php?prescription&list&id=" . attr_url($pid) . "')"; $viewArgs['linkMethod'] = "javascript"; @@ -1203,7 +1189,6 @@ function filterActiveIssues(array $i): array endif; ?> -
render($card->getTemplateFile(), array_merge($viewArgs, $card->getTemplateVariables())); } + // if anyone wants to render anything before the patient demographic list + $GLOBALS["kernel"]->getEventDispatcher()->dispatch(new RenderEvent($pid), RenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, 10); + if (!$GLOBALS['hide_billing_widget']) : $forceBillingExpandAlways = ($GLOBALS['force_billing_widget_open']) ? true : false; $patientbalance = get_patient_balance($pid, false); @@ -1282,9 +1270,6 @@ function filterActiveIssues(array $i): array echo $twig->getTwig()->render('patient/card/billing.html.twig', $viewArgs); endif; // End the hide_billing_widget - // if anyone wants to render anything before the patient demographic list - $GLOBALS["kernel"]->getEventDispatcher()->dispatch(new RenderEvent($pid), RenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, 10); - if (AclMain::aclCheckCore('patients', 'demo')) : $dispatchResult = $ed->dispatch(new CardRenderEvent('demographic'), CardRenderEvent::EVENT_HANDLE); // Render the Demographics box diff --git a/interface/patient_file/summary/demographics_save.php b/interface/patient_file/summary/demographics_save.php index 7c0414422e8..0848a942402 100644 --- a/interface/patient_file/summary/demographics_save.php +++ b/interface/patient_file/summary/demographics_save.php @@ -17,6 +17,8 @@ use OpenEMR\Common\Acl\AclMain; use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Services\ContactService; +use OpenEMR\Events\Patient\PatientUpdatedEventAux; + if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) { CsrfUtils::csrfNotVerified(); @@ -96,6 +98,13 @@ } } +/** + * trigger events to listeners who want data that is not directly available in + * the patient_data table on update + */ +$GLOBALS["kernel"]->getEventDispatcher()->dispatch(new PatientUpdatedEventAux($pid, $_POST), PatientUpdatedEventAux::EVENT_HANDLE, 10); + + $i1dob = DateToYYYYMMDD(filter_input(INPUT_POST, "i1subscriber_DOB")); $i1date = DateToYYYYMMDD(filter_input(INPUT_POST, "i1effective_date")); $i1date_end = DateToYYYYMMDD(filter_input(INPUT_POST, "i1effective_date_end")); diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index e0a80a861fc..585acb24890 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -143,7 +143,8 @@ function checkBackgroundServices() * this is to sync the prescription logs */ $wenoservices = $GLOBALS['weno_rx_enable'] == 1 ? '1' : '0'; - updateBackgroundService('WenoExchange', $wenoservices, 1); + updateBackgroundService('WenoExchange', $wenoservices, 60); + updateBackgroundService('WenoExchangePharmacies', $wenoservices, 1440); } ?> diff --git a/interface/weno/facilities.php b/interface/weno/facilities.php deleted file mode 100644 index 8463828ce33..00000000000 --- a/interface/weno/facilities.php +++ /dev/null @@ -1,80 +0,0 @@ - - * @copyright Copyright (c) 2020 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -require_once("../globals.php"); - -use OpenEMR\Common\Acl\AclMain; -use OpenEMR\Common\Csrf\CsrfUtils; -use OpenEMR\Common\Twig\TwigContainer; -use OpenEMR\Core\Header; -use OpenEMR\Rx\Weno\FacilityProperties; - -//ensure user has proper access -if (!AclMain::aclCheckCore('admin', 'super')) { - echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Weno Admin")]); - exit; -} - -$data = new FacilityProperties(); - -if ($_POST) { - if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token"])) { - CsrfUtils::csrfNotVerified(); - } - $data->facilityupdates = $_POST; - $data->updateFacilityNumber(); -} - -$facilities = $data->getFacilities(); - -?> - - - <?php echo xlt('Weno Admin'); ?> - - - - -


-

- -
- - - - - - - - - - "; - print ""; - print ""; - print ""; - ++$i; - } - ?> -
" . text($facility["name"]) . "" . text($facility['street']) - . "" . text($facility['city']) . "
- -
-
- - - diff --git a/interface/weno/indexrx.php b/interface/weno/indexrx.php deleted file mode 100644 index 7248f078598..00000000000 --- a/interface/weno/indexrx.php +++ /dev/null @@ -1,52 +0,0 @@ - - * @copyright Copyright (c) 2020 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -require_once("../globals.php"); - -use OpenEMR\Common\Acl\AclMain; -use OpenEMR\Common\Twig\TwigContainer; -use OpenEMR\Rx\Weno\Container; - -//ensure user has proper access -if (!AclMain::aclCheckCore('patients', 'rx')) { - echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Weno eRx")]); - exit; -} - -$container = new Container(); - -$wenoProperties = $container->getTransmitproperties(); -$provider_info = $wenoProperties->getProviderEmail(); -$urlParam = $wenoProperties->cipherpayload(); //lets encrypt the data -$logsync = $container->getLogproperties(); -$logsync->logSync(); -$newRxUrl = "https://online.wenoexchange.com/en/NewRx/ComposeRx?useremail="; -if ($urlParam == 'error') { //check to make sure there were no errors - echo xlt("Cipher failure check encryption key"); - exit; -} -?> - - - - - <?php echo xlt('Weno eRx') ?> - - - - - - diff --git a/interface/weno/rxlogmanager.php b/interface/weno/rxlogmanager.php deleted file mode 100644 index aa6681a4263..00000000000 --- a/interface/weno/rxlogmanager.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (c) 2021 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -require_once("../globals.php"); - -use OpenEMR\Common\Acl\AclMain; -use OpenEMR\Rx\Weno\Container; - -/* - * access control is on Weno side based on the user login - */ -if (!AclMain::aclCheckCore('patient', 'med')) { - echo xlt('Prescriptions Review Not Authorized'); - exit; -} - -$container = new Container(); -$log_review = $container->getLogproperties(); -$wenoProperties = $container->getTransmitproperties(); -$logurlparam = $log_review->logReview(); -$provider_info = $wenoProperties->getProviderEmail(); - -if ($logurlparam == 'error') { - echo xlt("Cipher failure check encryption key"); - exit; -} - -$url = "https://online.wenoexchange.com/en/EPCS/RxLog?useremail="; - -//**warning** do not add urlencode to $provider_info['email'] -$urlOut = $url . $provider_info['email'] . "&data=" . urlencode($logurlparam); -header("Location: " . $urlOut); diff --git a/interface/weno/weno.js b/interface/weno/weno.js deleted file mode 100644 index 7a984f9e9e2..00000000000 --- a/interface/weno/weno.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * @package OpenEMR - * @link http://www.open-emr.org - * @author Sherwin Gaddis - * @copyright Copyright (c) 2020 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -document.getElementById('connected').addEventListener('click', runScript); - -function runScript() -{ - let xhr = new XMLHttpRequest(); - xhr.open('GET', 'wenoconnected.php', true); - xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xhr.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - console.log(this.responseText); - if (this.responseText === 'imported') { - alert('Update Complete'); - $('#loading').hide(); - } - } - } - - xhr.send() -} \ No newline at end of file diff --git a/interface/weno/wenoconnected.php b/interface/weno/wenoconnected.php deleted file mode 100644 index c4e4013c5ae..00000000000 --- a/interface/weno/wenoconnected.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @copyright Copyright (c) 2020 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -require_once("../globals.php"); - -use OpenEMR\Common\Acl\AclMain; -use OpenEMR\Rx\Weno\wenoPharmaciesImport; - -//ensure user has proper access -if (!AclMain::aclCheckCore('patient', 'med')) { - echo xlt('Pharmacy Import not authorized'); - exit; -} -//Weno has decided to not force the import of pharmacies since they are using the iframe -//and the pharmacy can be selected at the time of creating the prescription. -$phIN = new wenoPharmaciesImport(); - -$status = $phIN->importPharmacy(); - -echo $status; diff --git a/library/globals.inc.php b/library/globals.inc.php index 9ec4d304e9b..276c80ad0ac 100644 --- a/library/globals.inc.php +++ b/library/globals.inc.php @@ -155,8 +155,8 @@ function getDefaultRenderListOptions() 'checkout_roll_off', 'patient_birthday_alert', 'patient_birthday_alert_manual_off', - 'erx_import_status_message', - 'weno_provider_password'); + 'erx_import_status_message' +); // Gets array of time zones supported by PHP. // @@ -3495,34 +3495,6 @@ function gblTimeZones() xl('Log all NewCrop eRx Requests and / or Responses.'), ), - 'weno_rx_enable' => array( - xl('Enable Weno eRx Service'), - 'bool', - '0', - xl('Enable Weno eRx Service') . ' ' . xl('Contact https://online.wenoexchange.com to sign up for Weno Free eRx service.') - ), - - 'weno_rx_enable_test' => array( - xl('Enable Weno eRx Service Test mode'), - 'bool', - '1', - xl('Enable Weno eRx Service Test mode') - ), - - 'weno_encryption_key' => array( - xl('Weno Encryption Key'), - 'encrypted', // data type - '', - xl('Encryption key issued by Weno eRx service.') - ), - - 'weno_provider_password' => array( - xl('Weno Provider Account Password'), - 'encrypted', // data type - '', - xl('Each provider needs to set this under user settings. This should be blank') - ), - 'ccda_alt_service_enable' => array( xl('Enable C-CDA Service'), array( diff --git a/library/options.inc.php b/library/options.inc.php index dfe3bb1da8a..3953c0d8e0e 100644 --- a/library/options.inc.php +++ b/library/options.inc.php @@ -60,6 +60,7 @@ use OpenEMR\Services\EncounterService; use OpenEMR\Services\FacilityService; use OpenEMR\Services\PatientService; +use OpenEMR\Events\PatientDemographics\RenderPharmacySectionEvent; $facilityService = new FacilityService(); @@ -853,6 +854,12 @@ class='form-control{$smallform}' } else { echo ""; } + + /** + * if anyone wants to render something after the pharmacy section on the demographics form, + * they would have to listen to this event. + */ + $GLOBALS["kernel"]->getEventDispatcher()->dispatch(new RenderPharmacySectionEvent(), RenderPharmacySectionEvent::RENDER_AFTER_PHARMACY_SECTION, 10); } elseif ($data_type == 13) { // squads echo "