From de7bca356fbeb7dd82508c539154f9a6a38513dc Mon Sep 17 00:00:00 2001 From: Ritesh Ghiya Date: Tue, 28 Nov 2023 13:12:01 +0530 Subject: [PATCH 01/75] [Ritesh] | BAH-3148 | Create and fetch medication task (#1) * [Ritesh] | 1. Repo set up. 2. Created Slot and Schedule entity 3.Saving IPD Medication Schedule without creating slots. * [Ritesh] | 1. Update package name 2. Added Dao and Service layer for reference 3. Minor fixes * [Ritesh] | 1.Rename Schedule Strategy to MedicationFrequency * [Ritesh] | 1. Migration for slot. 2. Slot creation from schedule * [Ritesh] | 1. Refactor SlotTimeCreationService * [Ritesh] | 1. Handle time zone issue while creating slots and schedule. * [Ritesh] | 1. Changing the url of saving medication * [Ritesh] | 1. Returning slots * [Ritesh] | Get schedule for Drug chart * [Ritesh] | Fix date time issue in slots response * [Ritesh] | Refactoring and Added test * [Ritesh] | 1. Change for reference id to subject reference id and by reference id to actor reference id. 2. Also added pre-condition before adding medication concept for ipd. * [Ritesh] | 1. Refactoring ServiceType * [Ritesh] | 1. Bug Fix return empty list if now slots are not present for a patient on specific day. * [Ritesh] | 1. Updated README file * [Ritesh] | 1. Fixed time zone issue in test * add. endpoint to get list of IPD medications scheduled for a patient * refactor. endpoint and updated tests in DAO and service classes * refactor. namings for schedule DAO methods * fix. test failures in ScheduleImpl --------- Co-authored-by: Arjun-Go Co-authored-by: Arjun G <91885483+Arjun-Go@users.noreply.github.com> --- .github/workflows/build_publish.yaml | 24 + .github/workflows/validate_pr.yml | 22 + .gitignore | 22 + LICENSE | 661 ++++++++++++++++++ README.md | 14 + api/pom.xml | 181 +++++ .../openmrs/module/ipd/api/IPDActivator.java | 22 + .../module/ipd/api/dao/ReferenceDAO.java | 15 + .../module/ipd/api/dao/ScheduleDAO.java | 20 + .../openmrs/module/ipd/api/dao/SlotDAO.java | 20 + .../api/dao/impl/HibernateReferenceDAO.java | 44 ++ .../api/dao/impl/HibernateScheduleDAO.java | 60 ++ .../ipd/api/dao/impl/HibernateSlotDAO.java | 54 ++ .../module/ipd/api/model/Reference.java | 40 ++ .../module/ipd/api/model/Schedule.java | 71 ++ .../module/ipd/api/model/ServiceType.java | 15 + .../openmrs/module/ipd/api/model/Slot.java | 106 +++ .../ipd/api/service/ReferenceService.java | 20 + .../ipd/api/service/ScheduleService.java | 23 + .../module/ipd/api/service/SlotService.java | 23 + .../service/impl/ReferenceServiceImpl.java | 39 ++ .../api/service/impl/ScheduleServiceImpl.java | 51 ++ .../ipd/api/service/impl/SlotServiceImpl.java | 48 ++ .../module/ipd/api/util/DateTimeUtil.java | 18 + .../ipd/api/util/PrivilegeConstants.java | 13 + api/src/main/resources/liquibase.xml | 192 +++++ .../resources/moduleApplicationContext.xml | 13 + .../module/ipd/api/BaseIntegrationTest.java | 6 + .../HibernateReferenceDAOIntegrationTest.java | 36 + .../HibernateScheduleDAOIntegrationTest.java | 150 ++++ .../impl/HibernateSlotDAOIntegrationTest.java | 143 ++++ .../impl/ReferenceServiceImplTest.java | 50 ++ .../service/impl/ScheduleServiceImplTest.java | 101 +++ .../api/service/impl/SlotServiceImplTest.java | 76 ++ .../module/ipd/api/util/DateTimeUtilTest.java | 58 ++ .../resources/TestingApplicationContext.xml | 12 + mvnw | 287 ++++++++ mvnw.cmd | 187 +++++ omod/pom.xml | 138 ++++ .../openmrs/module/ipd/ModuleDescriptor.java | 3 + .../contract/MedicationScheduleResponse.java | 68 ++ .../contract/ScheduleMedicationRequest.java | 46 ++ .../contract/ScheduleMedicationResponse.java | 37 + .../ipd/controller/IPDScheduleController.java | 93 +++ .../module/ipd/factory/ScheduleFactory.java | 59 ++ .../module/ipd/factory/SlotFactory.java | 56 ++ .../ipd/service/IPDScheduleService.java | 16 + .../service/impl/IPDScheduleServiceImpl.java | 87 +++ .../service/impl/SlotTimeCreationService.java | 87 +++ omod/src/main/resources/config.xml | 20 + .../resources/webModuleApplicationContext.xml | 11 + .../module/ipd/BaseIntegrationTest.java | 7 + .../module/ipd/BaseWebControllerTest.java | 176 +++++ .../IPDScheduleControllerIntegrationTest.java | 57 ++ omod/src/test/resources/config.xml | 21 + .../resources/webModuleApplicationContext.xml | 11 + pom.xml | 377 ++++++++++ 57 files changed, 4307 insertions(+) create mode 100644 .github/workflows/build_publish.yaml create mode 100644 .github/workflows/validate_pr.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 api/pom.xml create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/IPDActivator.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/ReferenceDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/Reference.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/ReferenceService.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImpl.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java create mode 100644 api/src/main/resources/liquibase.xml create mode 100644 api/src/main/resources/moduleApplicationContext.xml create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/BaseIntegrationTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAOIntegrationTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImplTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/util/DateTimeUtilTest.java create mode 100644 api/src/test/resources/TestingApplicationContext.xml create mode 100755 mvnw create mode 100644 mvnw.cmd create mode 100644 omod/pom.xml create mode 100644 omod/src/main/java/org/openmrs/module/ipd/ModuleDescriptor.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java create mode 100644 omod/src/main/resources/config.xml create mode 100644 omod/src/main/resources/webModuleApplicationContext.xml create mode 100644 omod/src/test/java/org/openmrs/module/ipd/BaseIntegrationTest.java create mode 100644 omod/src/test/java/org/openmrs/module/ipd/BaseWebControllerTest.java create mode 100644 omod/src/test/java/org/openmrs/module/ipd/controller/IPDScheduleControllerIntegrationTest.java create mode 100644 omod/src/test/resources/config.xml create mode 100644 omod/src/test/resources/webModuleApplicationContext.xml create mode 100644 pom.xml diff --git a/.github/workflows/build_publish.yaml b/.github/workflows/build_publish.yaml new file mode 100644 index 0000000..0a569fe --- /dev/null +++ b/.github/workflows/build_publish.yaml @@ -0,0 +1,24 @@ +name: Build and Publish package +on: + push: + branches: [ main ] + workflow_dispatch: + +jobs: + build-publish-package: + name: Build and Publish package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: nexus-sonatype + server-username: NEXUS_USERNAME + server-password: NEXUS_PASSWORD + - name: Build and deploy with Maven + run: ./mvnw --no-transfer-progress clean -U deploy + env: + NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} + NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} diff --git a/.github/workflows/validate_pr.yml b/.github/workflows/validate_pr.yml new file mode 100644 index 0000000..2c20d1c --- /dev/null +++ b/.github/workflows/validate_pr.yml @@ -0,0 +1,22 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + pull_request: + branches: [ Bahmni-IPD-master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn clean package diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef96046 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +*.class +.settings +.project +.classpath +.talismanrc +target + +# Package Files # +*.jar +*.marker +*.war +*.ear +.idea +.DS_Store + +/omod/target/* +/api/target/* +*.iml +*/logs/* +logs/* +classes/ +.mvn/wrapper/*.jar diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/README.md b/README.md index 7833d3f..aa72fd3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ # openmrs-module-ipd Openmrs module for Bahmni IPD Care and Monitoring + +OpenMRS Module Bahmni-events Backend +================================= +This repository handles Bahmni IPD Care and Monitoring. + +## Packaging +```mvn clean package``` + +### Prerequisite + JDK 1.8 + +## Deploy + +Copy ```openmrs-module-ipd/omod/target/bahmni-ipd-1.0.0-SNAPSHOT.omod``` into OpenMRS modules directory and restart OpenMRS \ No newline at end of file diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 0000000..b28f5db --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,181 @@ + + + 4.0.0 + + org.bahmni.module + bahmni-ipd + 1.0.0-SNAPSHOT + + + bahmni-ipd-api + jar + Bahmni IPD API + Bahmni IPD API contains all backend APIs for IPD + + + + + src/main/resources + true + + + + + + src/test/resources + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + test-jar + + + + + + + + + + + org.openmrs.api + openmrs-api + + + org.projectlombok + lombok + + + org.openmrs.web + openmrs-web + + + org.openmrs.module + webservices.rest-omod-common + provided + + + + org.openmrs.module + webservices.rest-omod-2.0 + provided + + + + org.openmrs.module + webservices.rest-omod-common + test-jar + test + + + org.openmrs.test + openmrs-test + pom + + + org.openmrs.web + openmrs-web + test-jar + test + + + org.openmrs.api + openmrs-api + test-jar + test + + + org.powermock + powermock-api-mockito2 + test + + + org.mockito + mockito-core + test + + + org.powermock + powermock-module-junit4 + test + + + junit + junit + + + org.hamcrest + hamcrest-core + + + test + + + + + + diff --git a/api/src/main/java/org/openmrs/module/ipd/api/IPDActivator.java b/api/src/main/java/org/openmrs/module/ipd/api/IPDActivator.java new file mode 100644 index 0000000..730babb --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/IPDActivator.java @@ -0,0 +1,22 @@ +package org.openmrs.module.ipd.api; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openmrs.module.BaseModuleActivator; + +/** + * This class contains the logic that is run every time this module is either started or shutdown + */ +public class IPDActivator extends BaseModuleActivator { + + private final Log log = LogFactory.getLog(this.getClass()); + + public void startup() { + log.info("Starting Basic Module"); + } + + public void shutdown() { + log.info("Shutting down Basic Module"); + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/ReferenceDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/ReferenceDAO.java new file mode 100644 index 0000000..983d639 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/ReferenceDAO.java @@ -0,0 +1,15 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.model.Reference; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ReferenceDAO { + + Optional getReferenceByTypeAndTargetUUID(String type, String targetUUID) throws DAOException; + + Reference saveReference(Reference reference) throws DAOException; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java new file mode 100644 index 0000000..d8aa917 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java @@ -0,0 +1,20 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.api.db.DAOException; +import org.springframework.stereotype.Repository; +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.model.Reference; + +import java.util.List; + +@Repository +public interface ScheduleDAO { + + Schedule getSchedule(Integer scheduleId) throws DAOException; + + Schedule saveSchedule(Schedule schedule) throws DAOException; + + List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws DAOException; + List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws DAOException; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java new file mode 100644 index 0000000..9d99330 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -0,0 +1,20 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.api.db.DAOException; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; + +@Repository +public interface SlotDAO { + + Slot getSlot(Integer slotId) throws DAOException; + + Slot saveSlot(Slot slot) throws DAOException; + + List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAO.java new file mode 100644 index 0000000..9557690 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAO.java @@ -0,0 +1,44 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.hibernate.query.Query; +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.dao.ReferenceDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public class HibernateReferenceDAO implements ReferenceDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateReferenceDAO.class); + + private final SessionFactory sessionFactory; + + @Autowired + public HibernateReferenceDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public Optional getReferenceByTypeAndTargetUUID(String type, String targetUuid) throws DAOException { + + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Reference ref WHERE ref.type=:type and ref.targetUuid=:targetUuid"); + + query.setParameter("type", type); + query.setParameter("targetUuid", targetUuid); + + return query.uniqueResultOptional(); + } + + @Override + public Reference saveReference(Reference reference) throws DAOException { + sessionFactory.getCurrentSession().saveOrUpdate(reference); + return reference; + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java new file mode 100644 index 0000000..1dc8e29 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java @@ -0,0 +1,60 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.hibernate.query.Query; +import org.openmrs.Concept; +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public class HibernateScheduleDAO implements ScheduleDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateScheduleDAO.class); + private final SessionFactory sessionFactory; + + @Autowired + public HibernateScheduleDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public Schedule getSchedule(Integer scheduleId) throws DAOException { + return sessionFactory.getCurrentSession().get(Schedule.class, scheduleId); + } + + @Override + public Schedule saveSchedule(Schedule schedule) throws DAOException { + sessionFactory.getCurrentSession().saveOrUpdate(schedule); + return schedule; + } + + public List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws DAOException { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Schedule schedule WHERE schedule.subject = :subject AND schedule.serviceType = :serviceType"); + + + query.setParameter("subject", subject); + query.setParameter("serviceType", serviceType); + return query.getResultList(); + } + + @Override + public List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws DAOException { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Schedule schedule WHERE schedule.subject = :subject AND schedule.serviceType = :serviceType AND schedule.order.uuid IN :orderUuids"); + + query.setParameter("subject", subject); + query.setParameter("serviceType", serviceType); + query.setParameter("orderUuids", orderUuids); + + return query.getResultList(); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java new file mode 100644 index 0000000..1184496 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -0,0 +1,54 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.query.Query; +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.dao.SlotDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; +import org.hibernate.SessionFactory; +import org.openmrs.api.db.DAOException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; + +@Repository +public class HibernateSlotDAO implements SlotDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateSlotDAO.class); + + private final SessionFactory sessionFactory; + + @Autowired + public HibernateSlotDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public Slot getSlot(Integer slotId) throws DAOException { + return sessionFactory.getCurrentSession().get(Slot.class, slotId); + } + + @Override + public Slot saveSlot(Slot slot) throws DAOException { + sessionFactory.getCurrentSession().saveOrUpdate(slot); + return slot; + } + + @Override + public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType) { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and YEAR(slot.startDateTime)=:forYear and MONTH(slot.startDateTime)=:forMonth and DAY(slot.startDateTime)=:forDay and slot.serviceType=:serviceType"); + + query.setParameter("subject", subject); + query.setParameter("forYear", forDate.getYear()); + query.setParameter("forMonth", forDate.getMonthValue()); + query.setParameter("forDay", forDate.getDayOfMonth()); + query.setParameter("serviceType", serviceType); + + return query.getResultList(); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Reference.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Reference.java new file mode 100644 index 0000000..2889cac --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Reference.java @@ -0,0 +1,40 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.BaseOpenmrsMetadata; +import org.openmrs.OpenmrsObject; + +import javax.persistence.*; + +@Getter +@Setter +@Entity +@Table(name = "ipd_reference") +public class Reference extends BaseOpenmrsMetadata { + + private static final long serialVersionUID = 1L; + + public Reference() { + setName(""); + } + + public Reference(String type, String targetUuid) { + this.type = type; + this.targetUuid = targetUuid; + this.setName(type + "/" + targetUuid); + } + + @EqualsAndHashCode.Include + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "reference_id") + private Integer id; + + @Column(name = "target_type", nullable = false) + private String type; + + @Column(name = "target_uuid", nullable = false) + private String targetUuid; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java new file mode 100644 index 0000000..63e495f --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java @@ -0,0 +1,71 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.openmrs.BaseChangeableOpenmrsData; +import org.openmrs.Concept; +import org.openmrs.Order; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) +@Entity +@Table(name = "ipd_schedule") +public class Schedule extends BaseChangeableOpenmrsData { + + private static final long serialVersionUID = 1L; + + @EqualsAndHashCode.Include + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "schedule_id") + private Integer id; + + /** + * Should we rename it to "subject" + * This can have reference for which the schedule is being created + */ + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "subject_reference_id", referencedColumnName = "reference_id", nullable = false) + private Reference subject; + + /** + * Should we rename it to "carer/executor/ actor" + * This can have reference which execute the schedule is being created + */ + @ManyToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "actor_reference_id", referencedColumnName = "reference_id", nullable = false) + private Reference actor; + + @Column(name = "active", nullable = false) + private boolean active = Boolean.TRUE; + + @OneToOne + @JoinColumn(name = "service_category_id", referencedColumnName = "concept_id") + private Concept serviceCategory; // null not in use + + @OneToOne + @JoinColumn(name = "service_type_id", referencedColumnName = "concept_id", nullable = false) + private Concept serviceType; + + @OneToOne + @JoinColumn(name = "speciality_id", referencedColumnName = "concept_id") + private Concept speciality; // null not in use + + @OneToOne + @JoinColumn(name = "order_id", referencedColumnName = "order_id") + private Order order; + + @Column(name = "start_date", nullable = false) + private LocalDateTime startDate; + + @Column(name = "end_date", nullable = false) + private LocalDateTime endDate; + + @Column(name = "comments") + private String comments; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java new file mode 100644 index 0000000..48af776 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java @@ -0,0 +1,15 @@ +package org.openmrs.module.ipd.api.model; + +public enum ServiceType { + MEDICATION_REQUEST("MedicationRequest"); + + private final String conceptName; + + ServiceType(String medicationRequest) { + this.conceptName = medicationRequest; + } + + public String conceptName() { + return conceptName; + } +} \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java new file mode 100644 index 0000000..d5ce4dd --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -0,0 +1,106 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.openmrs.BaseChangeableOpenmrsData; +import org.openmrs.Concept; +import org.openmrs.Location; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) +@Entity +@Table(name = "ipd_slot") +public class Slot extends BaseChangeableOpenmrsData { + + private static final long serialVersionUID = 1L; + + public enum SlotStatus { + SCHEDULED, + MISSED, + COMPLETED, + CANCELLED + } + + @EqualsAndHashCode.Include + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "slot_id") + private Integer id; + + /** + * The location Where schedule occurs + */ + @ManyToOne + @JoinColumn(name = "location_id", referencedColumnName = "location_id") + private Location location; // bed location for patient + + /** + * The Service Category of the Schedule + */ + @OneToOne + @JoinColumn(name = "service_category_id", referencedColumnName = "concept_id") + private Concept serviceCategory; // null not in use + + /** + * The Service Type of the Schedule + */ + @OneToOne + @JoinColumn(name = "service_type_id", referencedColumnName = "concept_id", nullable = false) + private Concept serviceType; // as per schedule service type + + /** + * The Speciality of the Schedule + */ + @OneToOne + @JoinColumn(name = "speciality_id", referencedColumnName = "concept_id") + private Concept speciality; // null not in sue + + /** + * The Appointment Type of the Schedule + */ + @OneToOne + @JoinColumn(name = "appointment_type_id", referencedColumnName = "concept_id") + private Concept appointmentType; // null not in use + + /** + * The entity that belongs to a Schedule + */ + @ManyToOne + @JoinColumn(name = "schedule_id", referencedColumnName = "schedule_id", nullable = false) + private Schedule schedule; + + /** + * The Start Date the Slot + */ + @Column(name = "start_date_time", nullable = false) + private LocalDateTime startDateTime; // slot start time + + /** + * The End Date the Slot + */ + @Column(name = "end_date_time") + private LocalDateTime endDateTime; // can be null for now + + /** + * Any Comment for the Slot + */ + @Column(name = "comments") + private String comments; // null not is use + + /** + * The current status of the slot. + */ + @Column(name = "status", nullable = false) + @Enumerated(EnumType.STRING) + private SlotStatus status = SlotStatus.SCHEDULED; + + @Column(name = "overbooked", nullable = false) + private Boolean overbooked = Boolean.FALSE; // not is use +} + + diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/ReferenceService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/ReferenceService.java new file mode 100644 index 0000000..a006d08 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/ReferenceService.java @@ -0,0 +1,20 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.api.APIException; +import org.openmrs.api.OpenmrsService; +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public interface ReferenceService extends OpenmrsService { + + // @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) + Optional getReferenceByTypeAndTargetUUID(String type, String targetUuid) throws APIException; + + // @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) + Reference saveReference(Reference reference) throws APIException; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java new file mode 100644 index 0000000..97b4e04 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java @@ -0,0 +1,23 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.api.APIException; +import org.openmrs.api.OpenmrsService; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public interface ScheduleService extends OpenmrsService { + +// @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) + Schedule getSchedule(Integer scheduleId) throws APIException; + +// @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) + Schedule saveSchedule(Schedule schedule) throws APIException; + + List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws APIException; + List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws APIException; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java new file mode 100644 index 0000000..60eb1ed --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -0,0 +1,23 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.api.APIException; +import org.openmrs.api.OpenmrsService; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.List; + +@Service +public interface SlotService extends OpenmrsService { + +// @Authorized({ PrivilegeConstants.EDIT_IPD_SLOTS }) + Slot getSlot(Integer slotId) throws APIException; + +// @Authorized({ PrivilegeConstants.EDIT_IPD_SLOTS }) + Slot saveSlot(Slot slot) throws APIException; + + List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImpl.java new file mode 100644 index 0000000..9895276 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImpl.java @@ -0,0 +1,39 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.openmrs.api.APIException; +import org.openmrs.api.impl.BaseOpenmrsService; +import org.openmrs.module.ipd.api.dao.ReferenceDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.service.ReferenceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +@Transactional +public class ReferenceServiceImpl extends BaseOpenmrsService implements ReferenceService { + + private static final Logger log = LoggerFactory.getLogger(ReferenceServiceImpl.class); + + private final ReferenceDAO referenceDAO; + + @Autowired + public ReferenceServiceImpl(ReferenceDAO referenceDAO) { + this.referenceDAO = referenceDAO; + } + + @Override + @Transactional(readOnly = true) + public Optional getReferenceByTypeAndTargetUUID(String type, String targetUuid) throws APIException { + return referenceDAO.getReferenceByTypeAndTargetUUID(type, targetUuid); + } + + @Override + public Reference saveReference(Reference reference) throws APIException { + return referenceDAO.saveReference(reference); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java new file mode 100644 index 0000000..a1cdb07 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java @@ -0,0 +1,51 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.service.ScheduleService; +import org.openmrs.api.APIException; +import org.openmrs.api.impl.BaseOpenmrsService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +public class ScheduleServiceImpl extends BaseOpenmrsService implements ScheduleService { + + private static final Logger log = LoggerFactory.getLogger(ScheduleServiceImpl.class); + + private final ScheduleDAO scheduleDAO; + + @Autowired + public ScheduleServiceImpl(ScheduleDAO scheduleDAO) { + this.scheduleDAO = scheduleDAO; + } + + @Override + @Transactional(readOnly = true) + public Schedule getSchedule(Integer scheduleId) throws APIException { + return scheduleDAO.getSchedule(scheduleId); + } + + @Override + public Schedule saveSchedule(Schedule schedule) throws APIException { + return scheduleDAO.saveSchedule(schedule); + } + + @Override + public List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws APIException { + return scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(subject, serviceType); + } + + @Override + public List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws APIException { + return scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(subject, serviceType, orderUuids); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java new file mode 100644 index 0000000..9306a81 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -0,0 +1,48 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.openmrs.Concept; +import org.openmrs.module.ipd.api.dao.SlotDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.api.APIException; +import org.openmrs.api.impl.BaseOpenmrsService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.util.List; + +@Service +@Transactional +public class SlotServiceImpl extends BaseOpenmrsService implements SlotService { + + private static final Logger log = LoggerFactory.getLogger(SlotServiceImpl.class); + + private final SlotDAO slotDAO; + + @Autowired + public SlotServiceImpl(SlotDAO slotDAO) { + this.slotDAO = slotDAO; + } + + @Override + @Transactional(readOnly = true) + public Slot getSlot(Integer slotId) throws APIException { + return slotDAO.getSlot(slotId); + } + + @Override + public Slot saveSlot(Slot slot) throws APIException { + return slotDAO.saveSlot(slot); + } + + @Override + @Transactional(readOnly = true) + public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType) { + return slotDAO.getSlotsBySubjectReferenceIdAndForDateAndServiceType(subject, forDate, serviceType); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java new file mode 100644 index 0000000..45c6cc3 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java @@ -0,0 +1,18 @@ +package org.openmrs.module.ipd.api.util; + +import java.time.*; +import java.util.Date; + +public class DateTimeUtil { + public static LocalDateTime convertEpocUTCToLocalTimeZone(long utcTime) { + return Instant.ofEpochSecond(utcTime).atZone(ZoneOffset.systemDefault()).toLocalDateTime(); + } + + public static long convertLocalDateTimeToUTCEpoc(LocalDateTime localDateTime) { + return localDateTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toEpochSecond(); + } + + public static LocalDateTime convertDateToLocalDateTime(Date date) { + return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + } +} \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java b/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java new file mode 100644 index 0000000..ede0449 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java @@ -0,0 +1,13 @@ +package org.openmrs.module.ipd.api.util; + +import org.openmrs.annotation.AddOnStartup; + +public class PrivilegeConstants { + + @AddOnStartup(description = "Able to save ipd schedules") + public static final String EDIT_IPD_SCHEDULES = "Edit IPD Schedules"; + + @AddOnStartup(description = "Able to save ipd slots") + public static final String EDIT_IPD_SLOTS = "Edit IPD Slots"; + +} diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml new file mode 100644 index 0000000..9b708b8 --- /dev/null +++ b/api/src/main/resources/liquibase.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT COUNT(*) FROM concept where short_name='MedicationRequest' and description='MedicationRequest'; + + + Add concept Medication Request + + insert into concept (retired, short_name, description, datatype_id, class_id, is_set, creator, date_created, + changed_by, date_changed, uuid) + values (0, 'MedicationRequest', 'MedicationRequest', + (select concept_datatype_id from concept_datatype where name = 'Text'), + (select concept_class_id from concept_class where name = 'Misc'), + 0, 1, now(), 1, now(), uuid()); + + + + + + + SELECT COUNT(*) FROM concept_name where name ='MedicationRequest'; + + + Add concept-name Medication Request + + insert into concept_name (concept_id, name, locale, locale_preferred, creator, date_created, + concept_name_type, voided, uuid) + values ((select concept_id from concept where short_name='MedicationRequest'), + 'MedicationRequest', 'en', 1, 1, now(), 'FULLY_SPECIFIED', 0, uuid()); + + + diff --git a/api/src/main/resources/moduleApplicationContext.xml b/api/src/main/resources/moduleApplicationContext.xml new file mode 100644 index 0000000..a91ef45 --- /dev/null +++ b/api/src/main/resources/moduleApplicationContext.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/BaseIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/BaseIntegrationTest.java new file mode 100644 index 0000000..1e6033b --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/BaseIntegrationTest.java @@ -0,0 +1,6 @@ +package org.openmrs.module.ipd.api; +import org.openmrs.web.test.BaseModuleWebContextSensitiveTest; + +@org.springframework.test.context.ContextConfiguration(locations = {"classpath:TestingApplicationContext.xml"}) +public abstract class BaseIntegrationTest extends BaseModuleWebContextSensitiveTest { +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAOIntegrationTest.java new file mode 100644 index 0000000..46aa98d --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateReferenceDAOIntegrationTest.java @@ -0,0 +1,36 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openmrs.Patient; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.ReferenceDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Optional; + +public class HibernateReferenceDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private ReferenceDAO referenceDAO; + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void shouldSaveAndGetThePatientReference() { + Reference openmrsReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference reference = referenceDAO.saveReference(openmrsReference); + + Optional savedReference = referenceDAO.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + + Assertions.assertTrue(savedReference.isPresent()); + Assertions.assertEquals("2c33920f-7aa6-0000-998a-60412d8ff7d5", savedReference.get().getTargetUuid()); + Assertions.assertEquals("org.openmrs.Patient", savedReference.get().getType()); + Assertions.assertEquals("org.openmrs.Patient/2c33920f-7aa6-0000-998a-60412d8ff7d5", savedReference.get().getName()); + + sessionFactory.getCurrentSession().delete(reference); + } +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java new file mode 100644 index 0000000..7d2484e --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java @@ -0,0 +1,150 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openmrs.Concept; +import org.openmrs.DrugOrder; +import org.openmrs.Patient; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +public class HibernateScheduleDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private ScheduleDAO scheduleDAO; + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void shouldSaveTheScheduledCreatedForPatientGivenPatientSchedule() { + + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + Assertions.assertEquals(drugOrder, schedule.getOrder()); + Assertions.assertEquals(patientReference, schedule.getSubject()); + Assertions.assertEquals(providerReference, schedule.getActor()); + Assertions.assertEquals(startDate, schedule.getStartDate()); + Assertions.assertEquals(endDate, schedule.getEndDate()); + Assertions.assertEquals(testConcept, schedule.getServiceType()); + + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedScheduledCreatedForPatientGivenPatientSchedule() { + + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + Schedule scheduleById = scheduleDAO.getSchedule(savedSchedule.getId()); + + Assertions.assertEquals(drugOrder, scheduleById.getOrder()); + Assertions.assertEquals(patientReference, scheduleById.getSubject()); + Assertions.assertEquals(providerReference, scheduleById.getActor()); + Assertions.assertEquals(startDate, scheduleById.getStartDate()); + Assertions.assertEquals(endDate, scheduleById.getEndDate()); + Assertions.assertEquals(testConcept, scheduleById.getServiceType()); + + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedSchedulesForPatientByForReferenceIdAndServiceTypeAndOrderUuid() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + List orderUuidList = new ArrayList<>(); + orderUuidList.add(orderUuid); + + List schedulesBySubjectReferenceIdAndServiceType = scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, testConcept, orderUuidList); + + Assertions.assertEquals(1, schedulesBySubjectReferenceIdAndServiceType.size()); + + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedSchedulesForPatientByForReferenceIdAndServiceType() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + List orderUuidList = new ArrayList<>(); + orderUuidList.add(orderUuid); + + List schedulesBySubjectReferenceIdAndServiceType = scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, testConcept); + + Assertions.assertEquals(1, schedulesBySubjectReferenceIdAndServiceType.size()); + + sessionFactory.getCurrentSession().delete(savedSchedule); + } +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java new file mode 100644 index 0000000..cee6719 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -0,0 +1,143 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openmrs.Concept; +import org.openmrs.DrugOrder; +import org.openmrs.Patient; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.dao.SlotDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.List; + +public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private ScheduleDAO scheduleDAO; + + @Autowired + private SlotDAO slotDAO; + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void shouldSaveTheSlotForPatientGivenPatientSchedule() { + + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime slotStartTime = LocalDateTime.now(); + + Slot slot = new Slot(); + slot.setSchedule(savedSchedule); + slot.setServiceType(testConcept); + slot.setStartDateTime(slotStartTime); + + Slot savedSlot = slotDAO.saveSlot(slot); + + sessionFactory.getCurrentSession().delete(savedSlot); + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedSlotForPatientGivenPatientSchedule() { + + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime slotStartTime = LocalDateTime.now(); + + Slot slot = new Slot(); + slot.setSchedule(savedSchedule); + slot.setServiceType(testConcept); + slot.setStartDateTime(slotStartTime); + + Slot savedSlot = slotDAO.saveSlot(slot); + Slot getSlotById = slotDAO.getSlot(savedSlot.getId()); + + sessionFactory.getCurrentSession().delete(savedSlot); + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndForDateAndServiceTypeGivenPatientSchedule() { + + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setOrder(drugOrder); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime slotStartTime = LocalDateTime.now(); + + Slot slot1 = new Slot(); + slot1.setSchedule(savedSchedule); + slot1.setServiceType(testConcept); + slot1.setStartDateTime(slotStartTime); + + Slot slot2 = new Slot(); + slot2.setSchedule(savedSchedule); + slot2.setServiceType(testConcept); + slot2.setStartDateTime(slotStartTime.plusDays(1)); + + Slot savedSlot1 = slotDAO.saveSlot(slot1); + Slot savedSlot2 = slotDAO.saveSlot(slot2); + + List slotsAgainstSchedule = slotDAO.getSlotsBySubjectReferenceIdAndForDateAndServiceType(patientReference, slotStartTime.toLocalDate(), testConcept); + + Assertions.assertEquals(1, slotsAgainstSchedule.size()); + + sessionFactory.getCurrentSession().delete(savedSlot1); + sessionFactory.getCurrentSession().delete(savedSlot2); + sessionFactory.getCurrentSession().delete(savedSchedule); + } +} diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImplTest.java new file mode 100644 index 0000000..26332a8 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ReferenceServiceImplTest.java @@ -0,0 +1,50 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.openmrs.Patient; +import org.openmrs.module.ipd.api.dao.ReferenceDAO; +import org.openmrs.module.ipd.api.model.Reference; + +import java.util.Optional; + +@RunWith(MockitoJUnitRunner.class) +public class ReferenceServiceImplTest { + + @InjectMocks + private ReferenceServiceImpl referenceService; + + @Mock + private ReferenceDAO referenceDAO; + + @Test + public void shouldInvokeSaveReferenceWithGivenReference() { + Reference openmrsReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference expectedOpenmrsReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + expectedOpenmrsReference.setId(1); + + Mockito.when(referenceDAO.saveReference(openmrsReference)).thenReturn(expectedOpenmrsReference); + + referenceService.saveReference(openmrsReference); + + Mockito.verify(referenceDAO, Mockito.times(1)).saveReference(openmrsReference); + } + + @Test + public void shouldInvokeGetReferenceByTargetUUIDAndTypeWithGivenTargetUUIDAndType() { + String typeName = Patient.class.getTypeName(); + String targetUuid = "2c33920f-7aa6-0000-998a-60412d8ff7d5"; + Reference expectedOpenmrsReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + expectedOpenmrsReference.setId(1); + + Mockito.when(referenceDAO.getReferenceByTypeAndTargetUUID(typeName, targetUuid)).thenReturn(Optional.of(expectedOpenmrsReference)); + + referenceService.getReferenceByTypeAndTargetUUID(typeName, targetUuid); + + Mockito.verify(referenceDAO, Mockito.times(1)).getReferenceByTypeAndTargetUUID(typeName, targetUuid); + } +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java new file mode 100644 index 0000000..0c6ea86 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java @@ -0,0 +1,101 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.openmrs.Concept; +import org.openmrs.ConceptName; +import org.openmrs.Patient; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +@RunWith(MockitoJUnitRunner.class) +public class ScheduleServiceImplTest { + + @InjectMocks + private ScheduleServiceImpl scheduleService; + + @Mock + private ScheduleDAO scheduleDAO; + + @Test + public void shouldInvokeSaveScheduleWithGivenSchedule() { + Schedule schedule = new Schedule(); + Schedule expectedSchedule = new Schedule(); + expectedSchedule.setId(1); + + Mockito.when(scheduleDAO.saveSchedule(schedule)).thenReturn(expectedSchedule); + + scheduleService.saveSchedule(schedule); + + Mockito.verify(scheduleDAO, Mockito.times(1)).saveSchedule(schedule); + } + + @Test + public void shouldInvokeGetScheduleWithGivenScheduleId() { + Schedule expectedSchedule = new Schedule(); + expectedSchedule.setId(1); + + Mockito.when(scheduleDAO.getSchedule(1)).thenReturn(expectedSchedule); + + scheduleService.getSchedule(1); + + Mockito.verify(scheduleDAO, Mockito.times(1)).getSchedule(1); + } + + @Test + public void shouldInvokeGetSchedulesByForReferenceAndServiceTypeWithGivenScheduleId() { + Schedule expectedSchedule = new Schedule(); + expectedSchedule.setId(1); + List schedules = new ArrayList<>(); + + LocalDate today = LocalDate.now(); + Concept medicationRequestConcept = new Concept(); + ConceptName conceptName = new ConceptName(); + conceptName.setName("MedicationRequest"); + conceptName.setLocale(Locale.US); + medicationRequestConcept.setFullySpecifiedName(conceptName); + + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept)).thenReturn(schedules); + + scheduleService.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); + + Mockito.verify(scheduleDAO, Mockito.times(1)).getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); + } + + @Test + public void shouldInvokeGetSchedulesByForReferenceAndServiceTypeAndOrderUuidsWithGivenScheduleId() { + Schedule expectedSchedule = new Schedule(); + expectedSchedule.setId(1); + List schedules = new ArrayList<>(); + + LocalDate today = LocalDate.now(); + Concept medicationRequestConcept = new Concept(); + ConceptName conceptName = new ConceptName(); + conceptName.setName("MedicationRequest"); + conceptName.setLocale(Locale.US); + medicationRequestConcept.setFullySpecifiedName(conceptName); + + List orderUuids = new ArrayList<>(); + orderUuids.add("orderUuid"); + + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids)).thenReturn(schedules); + + scheduleService.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); + + Mockito.verify(scheduleDAO, Mockito.times(1)).getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); + } +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java new file mode 100644 index 0000000..a9e58b4 --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -0,0 +1,76 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.openmrs.Concept; +import org.openmrs.ConceptName; +import org.openmrs.Patient; +import org.openmrs.module.ipd.api.dao.SlotDAO; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Slot; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +@RunWith(MockitoJUnitRunner.class) +public class SlotServiceImplTest { + + @InjectMocks + private SlotServiceImpl slotService; + + @Mock + private SlotDAO slotDAO; + + @Test + public void shouldInvokeSaveSlotWithGivenSlot() { + Slot slot = new Slot(); + Slot expectedSlot = new Slot(); + expectedSlot.setId(1); + + Mockito.when(slotDAO.saveSlot(slot)).thenReturn(expectedSlot); + + slotService.saveSlot(slot); + + Mockito.verify(slotDAO, Mockito.times(1)).saveSlot(slot); + } + + @Test + public void shouldInvokeGetSlotWithGivenSlotId() { + Slot expectedSlot = new Slot(); + expectedSlot.setId(1); + + Mockito.when(slotDAO.getSlot(1)).thenReturn(expectedSlot); + + slotService.getSlot(1); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlot(1); + } + + @Test + public void shouldInvokeGetSlotsByForReferenceAndForDateAndServiceTypeWithGivenScheduleId() { + Slot expectedSlot = new Slot(); + expectedSlot.setId(1); + List slots = new ArrayList<>(); + + LocalDate today = LocalDate.now(); + Concept medicationRequestConcept = new Concept(); + ConceptName conceptName = new ConceptName(); + conceptName.setName("MedicationRequest"); + conceptName.setLocale(Locale.US); + medicationRequestConcept.setFullySpecifiedName(conceptName); + + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(slotDAO.getSlotsBySubjectReferenceIdAndForDateAndServiceType(patientReference, today, medicationRequestConcept)).thenReturn(slots); + + slotService.getSlotsBySubjectReferenceIdAndForDateAndServiceType(patientReference, today, medicationRequestConcept); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndForDateAndServiceType(patientReference, today, medicationRequestConcept); + } +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/util/DateTimeUtilTest.java b/api/src/test/java/org/openmrs/module/ipd/api/util/DateTimeUtilTest.java new file mode 100644 index 0000000..88b2a7e --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/util/DateTimeUtilTest.java @@ -0,0 +1,58 @@ +package org.openmrs.module.ipd.api.util; + +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.TimeZone; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DateTimeUtilTest { + + @Test + public void shouldConvertEPOCUTCToLocalTimeZone() { + ZoneId defaultZoneId = TimeZone.getDefault().toZoneId(); + TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata"))); + + LocalDateTime localDateTime = DateTimeUtil.convertEpocUTCToLocalTimeZone(1690906304); + + assertEquals(2023,localDateTime.getYear()); + assertEquals(8, localDateTime.getMonthValue()); + assertEquals(1, localDateTime.getDayOfMonth()); + assertEquals(21, localDateTime.getHour()); + assertEquals(41, localDateTime.getMinute()); + assertEquals(44, localDateTime.getSecond()); + + TimeZone.setDefault(TimeZone.getTimeZone(defaultZoneId)); + } + + @Test + public void shouldConvertLocalTimeZoneToEPOCUTC() { + ZoneId defaultZoneId = TimeZone.getDefault().toZoneId(); + TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata"))); + + LocalDateTime localDateTime = LocalDateTime.of(2023, 8, 1, 21, 41, 44); + long epocUTCTime = DateTimeUtil.convertLocalDateTimeToUTCEpoc(localDateTime); + + assertEquals(1690906304,epocUTCTime); + + TimeZone.setDefault(TimeZone.getTimeZone(defaultZoneId)); + } + + @Test + public void shouldConvertDateToLocalDateTime() { + ZoneId defaultZoneId = TimeZone.getDefault().toZoneId(); + TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata"))); + + Date date = Date.from(Instant.ofEpochSecond(1690906304)); + LocalDateTime localDateTime = DateTimeUtil.convertDateToLocalDateTime(date); + + assertEquals(1690906304, localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond()); + + TimeZone.setDefault(TimeZone.getTimeZone(defaultZoneId)); + } +} \ No newline at end of file diff --git a/api/src/test/resources/TestingApplicationContext.xml b/api/src/test/resources/TestingApplicationContext.xml new file mode 100644 index 0000000..bf8a8fc --- /dev/null +++ b/api/src/test/resources/TestingApplicationContext.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..b7f0646 --- /dev/null +++ b/mvnw @@ -0,0 +1,287 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.1.1 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + printf '%s' "$(cd "$basedir"; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname $0)") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $wrapperUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + QUIET="--quiet" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + elif command -v curl > /dev/null; then + QUIET="--silent" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=`cygpath --path --windows "$javaSource"` + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..474c9d6 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,187 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/omod/pom.xml b/omod/pom.xml new file mode 100644 index 0000000..ff83e3b --- /dev/null +++ b/omod/pom.xml @@ -0,0 +1,138 @@ + + + + 4.0.0 + + bahmni-ipd + org.bahmni.module + 1.0.0-SNAPSHOT + + + bahmni-ipd-omod + jar + Bahmni IPD omod + Bahmni IPD module contains all backend APIs for IPD + + + bahmni-ipd + ${project.name} + ${project.version} + ${project.groupId}.${MODULE_ID} + + + + ${project.parent.artifactId}-${project.parent.version} + + + + maven-resources-plugin + + true + + + + + + + + org.openmrs.maven.plugins + maven-openmrs-plugin + true + + + init + initialize + + initialize-module + + + + pack + package + + package-module + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + Expand moduleApplicationContext and messages + + unpack-dependencies + + generate-resources + + ${project.parent.groupId} + ${project.parent.artifactId}-api + true + **/* + ${project.build.directory}/classes + + + + + + + + + ${project.parent.groupId} + ${project.parent.artifactId}-api + ${project.parent.version} + + + org.projectlombok + lombok + + + org.openmrs.web + openmrs-web + provided + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + org.openmrs.module + webservices.rest-omod-common + provided + + + org.openmrs.module + bedmanagement-api + provided + + + + org.openmrs.test + openmrs-test + pom + + + org.openmrs.web + openmrs-web + test-jar + test + + + org.openmrs.api + openmrs-api + test-jar + test + + + javax.servlet + servlet-api + test + + + + \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/ModuleDescriptor.java b/omod/src/main/java/org/openmrs/module/ipd/ModuleDescriptor.java new file mode 100644 index 0000000..7b43171 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/ModuleDescriptor.java @@ -0,0 +1,3 @@ +package org.openmrs.module.ipd; + +public class ModuleDescriptor {} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java new file mode 100644 index 0000000..94f501d --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java @@ -0,0 +1,68 @@ +package org.openmrs.module.ipd.contract; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertLocalDateTimeToUTCEpoc; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MedicationScheduleResponse { + + private Integer id; + private String uuid; + private String serviceType; + private String comments; + private long startDate; + private long endDate; + private Object order; + private List slots; + public static MedicationScheduleResponse createFrom(Schedule schedule, List slots) { + + return MedicationScheduleResponse.builder() + .id(schedule.getId()) + .uuid(schedule.getUuid()) + .serviceType(schedule.getServiceType().getName().getName()) + .comments(schedule.getComments()) + .startDate(convertLocalDateTimeToUTCEpoc(schedule.getStartDate())) + .endDate(convertLocalDateTimeToUTCEpoc(schedule.getEndDate())) + .order(ConversionUtil.convertToRepresentation(schedule.getOrder(), Representation.FULL)) + .slots(slots.stream().map(MedicationSlot::createFrom).collect(Collectors.toList())) + .build(); + + } + + @Builder + @Getter + @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) + @AllArgsConstructor + @NoArgsConstructor + static class MedicationSlot { + private Integer id; + private String uuid; + private String serviceType; + private String status; + private long startTime; + public static MedicationSlot createFrom(Slot slot) { + return MedicationSlot.builder() + .id(slot.getId()) + .uuid(slot.getUuid()) + .serviceType(slot.getServiceType().getName().getName()) + .status(slot.getStatus().name()) + .startTime(convertLocalDateTimeToUTCEpoc(slot.getStartDateTime())) + .build(); + } + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java new file mode 100644 index 0000000..c41eced --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java @@ -0,0 +1,46 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.api.util.DateTimeUtil; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertEpocUTCToLocalTimeZone; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScheduleMedicationRequest { + + private String patientUuid; + private String orderUuid; + private String providerUuid; + private String comments; + private Long slotStartTime; + private List firstDaySlotsStartTime; + private List dayWiseSlotsStartTime; + private MedicationFrequency medicationFrequency; + + public enum MedicationFrequency { + START_TIME_DURATION_FREQUENCY, + FIXED_SCHEDULE_FREQUENCY + } + + public LocalDateTime getSlotStartTimeAsLocaltime() { + return slotStartTime != null ? convertEpocUTCToLocalTimeZone(slotStartTime): null; + } + + public List getFirstDaySlotsStartTimeAsLocalTime() { + return firstDaySlotsStartTime != null ? firstDaySlotsStartTime.stream().map(DateTimeUtil::convertEpocUTCToLocalTimeZone).collect(Collectors.toList()) : null; + } + + public List getDayWiseSlotsStartTimeAsLocalTime() { + return dayWiseSlotsStartTime != null ? dayWiseSlotsStartTime.stream().map(DateTimeUtil::convertEpocUTCToLocalTimeZone).collect(Collectors.toList()) : null; + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java new file mode 100644 index 0000000..a5acd23 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java @@ -0,0 +1,37 @@ +package org.openmrs.module.ipd.contract; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertLocalDateTimeToUTCEpoc; + +@Builder +@Getter +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@AllArgsConstructor +@NoArgsConstructor +public class ScheduleMedicationResponse { + private Integer id; + private String patientUuid; + private String comments; + private long startDate; + private long endDate; + private Object order; + + public static ScheduleMedicationResponse constructFrom(Schedule schedule) { + return ScheduleMedicationResponse.builder() + .id(schedule.getId()) + .patientUuid(schedule.getSubject().getUuid()) + .comments(schedule.getComments()) + .order(ConversionUtil.convertToRepresentation(schedule.getOrder(), Representation.REF)) // TODO. Clarify why we need to use REF here with product team + .startDate(convertLocalDateTimeToUTCEpoc(schedule.getStartDate())) + .endDate(convertLocalDateTimeToUTCEpoc(schedule.getEndDate())) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java new file mode 100644 index 0000000..215d13c --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -0,0 +1,93 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.contract.MedicationScheduleResponse; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; +import org.openmrs.module.ipd.service.IPDScheduleService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.openmrs.module.ipd.api.model.ServiceType.MEDICATION_REQUEST; +import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertEpocUTCToLocalTimeZone; +import static org.openmrs.module.ipd.contract.MedicationScheduleResponse.createFrom; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd/schedule") +@Slf4j +public class IPDScheduleController extends BaseRestController { + + private final IPDScheduleService ipdScheduleService; + + @Autowired + public IPDScheduleController(IPDScheduleService ipdScheduleService) { + this.ipdScheduleService = ipdScheduleService; + } + + @RequestMapping(value = "type/medication", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity createMedicationSchedule(@RequestBody ScheduleMedicationRequest scheduleMedicationRequest) { + try { + Schedule schedule = ipdScheduleService.saveMedicationSchedule(scheduleMedicationRequest); + return new ResponseEntity<>(ScheduleMedicationResponse.constructFrom(schedule), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + + @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "forDate"}) + @ResponseBody + public ResponseEntity getMedicationScheduleByDate(@RequestParam(value = "patientUuid") String patientUuid, + @RequestParam(value = "forDate") long forDate) { + try { + LocalDate localDate = convertEpocUTCToLocalTimeZone(forDate).toLocalDate(); + List slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, localDate); + return new ResponseEntity<>(constructResponse(slots), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + + @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid"}) + @ResponseBody + public ResponseEntity getMedicationScheduleByOrderUuids(@RequestParam(value = "patientUuid") String patientUuid, + @RequestParam(value = "orderUuids", required = false) List orderUuids) { + try { + List schedules; + if (orderUuids == null || orderUuids.isEmpty()) { + schedules = ipdScheduleService.getMedicationSchedules(patientUuid, MEDICATION_REQUEST); + } else { + schedules = ipdScheduleService.getMedicationSchedules(patientUuid, MEDICATION_REQUEST, orderUuids); + } + List medicationResponses = schedules.stream() + .map(ScheduleMedicationResponse::constructFrom) + .collect(Collectors.toList()); + return new ResponseEntity<>(medicationResponses, OK); + } catch (Exception e) { + log.error("Runtime error while trying to retrieve schedules created by patient", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + + + private List constructResponse(List slots) { + Map> slotsBySchedule = slots.stream().collect(Collectors.groupingBy(Slot::getSchedule)); + return slotsBySchedule.entrySet().stream().map(entry -> createFrom(entry.getKey(), entry.getValue())).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java new file mode 100644 index 0000000..3c11a81 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java @@ -0,0 +1,59 @@ +package org.openmrs.module.ipd.factory; + +import org.openmrs.Concept; +import org.openmrs.DrugOrder; +import org.openmrs.Patient; +import org.openmrs.Provider; +import org.openmrs.api.ConceptService; +import org.openmrs.api.OrderService; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.service.ReferenceService; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +import static org.openmrs.module.ipd.api.model.ServiceType.MEDICATION_REQUEST; +import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertDateToLocalDateTime; + +@Component +public class ScheduleFactory { + + private final OrderService orderService; + private final ConceptService conceptService; + private final ReferenceService referenceService; + + @Autowired + public ScheduleFactory(OrderService orderService, ConceptService conceptService, ReferenceService referenceService) { + this.orderService = orderService; + this.conceptService = conceptService; + this.referenceService = referenceService; + } + + public Schedule createScheduleForMedicationFrom(ScheduleMedicationRequest request) { + Schedule schedule = new Schedule(); + + DrugOrder drugOrder = (DrugOrder) orderService.getOrderByUuid(request.getOrderUuid()); + Concept medicationRequestServiceType = conceptService.getConceptByName(MEDICATION_REQUEST.conceptName()); + + Reference subject = getReference(Patient.class.getTypeName(), request.getPatientUuid()); + Reference actor = getReference(Provider.class.getTypeName(), request.getProviderUuid()); + + schedule.setSubject(subject); + schedule.setActor(actor); + schedule.setStartDate(convertDateToLocalDateTime(drugOrder.getEffectiveStartDate())); + schedule.setEndDate(convertDateToLocalDateTime(drugOrder.getEffectiveStopDate())); + schedule.setServiceType(medicationRequestServiceType); + schedule.setOrder(drugOrder); + schedule.setActive(true); + + return schedule; + } + + private Reference getReference(String type, String targetUuid) { + Optional reference = referenceService.getReferenceByTypeAndTargetUUID(type, targetUuid); + return reference.orElseGet(() -> new Reference(type, targetUuid)); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java new file mode 100644 index 0000000..c07c6fe --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java @@ -0,0 +1,56 @@ +package org.openmrs.module.ipd.factory; + +import org.openmrs.Concept; +import org.openmrs.Patient; +import org.openmrs.api.ConceptService; +import org.openmrs.api.PatientService; +import org.openmrs.module.bedmanagement.BedDetails; +import org.openmrs.module.bedmanagement.service.BedManagementService; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.Slot; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +import static org.openmrs.module.ipd.api.model.ServiceType.MEDICATION_REQUEST; +import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; + +@Component +public class SlotFactory { + + private final BedManagementService bedManagementService; + private final ConceptService conceptService; + private final PatientService patientService; + + @Autowired + public SlotFactory(BedManagementService bedManagementService, ConceptService conceptService, PatientService patientService) { + this.bedManagementService = bedManagementService; + this.conceptService = conceptService; + this.patientService = patientService; + } + + public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime) { + + return slotsStartTime.stream().map(slotStartTime -> { + Slot slot = new Slot(); + + String patientUuid = savedSchedule.getSubject().getTargetUuid(); + Patient patient = patientService.getPatientByUuid(patientUuid); + BedDetails bedAssignmentDetailsByPatient = bedManagementService.getBedAssignmentDetailsByPatient(patient); + if(bedAssignmentDetailsByPatient != null){ + slot.setLocation(bedAssignmentDetailsByPatient.getPhysicalLocation()); + } + + Concept medicationRequestServiceType = conceptService.getConceptByName(MEDICATION_REQUEST.conceptName()); + slot.setServiceType(medicationRequestServiceType); + + slot.setSchedule(savedSchedule); + slot.setStartDateTime(slotStartTime); + slot.setStatus(SCHEDULED); + return slot; + }).collect(Collectors.toList()); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java new file mode 100644 index 0000000..21e2ccd --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -0,0 +1,16 @@ +package org.openmrs.module.ipd.service; + +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.ServiceType; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; + +import java.time.LocalDate; +import java.util.List; + +public interface IPDScheduleService { + Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); + List getMedicationSlots(String patientUuid, ServiceType serviceType, LocalDate forDate); + List getMedicationSchedules(String patientUuid, ServiceType serviceType); + List getMedicationSchedules(String patientUuid, ServiceType serviceType, List orderUuids); +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java new file mode 100644 index 0000000..e93bf57 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -0,0 +1,87 @@ +package org.openmrs.module.ipd.service.impl; + +import org.openmrs.Concept; +import org.openmrs.Patient; +import org.openmrs.api.ConceptService; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.ServiceType; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.service.ReferenceService; +import org.openmrs.module.ipd.api.service.ScheduleService; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.openmrs.module.ipd.factory.ScheduleFactory; +import org.openmrs.module.ipd.factory.SlotFactory; +import org.openmrs.module.ipd.service.IPDScheduleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@Service +@Transactional +public class IPDScheduleServiceImpl implements IPDScheduleService { + + private final ScheduleService scheduleService; + private final ScheduleFactory scheduleFactory; + private final SlotFactory slotFactory; + private final SlotService slotService; + private final SlotTimeCreationService slotTimeCreationService; + private final ConceptService conceptService; + private final ReferenceService referenceService; + + @Autowired + public IPDScheduleServiceImpl(ScheduleService scheduleService, ScheduleFactory scheduleFactory, SlotFactory slotFactory, SlotService slotService, SlotTimeCreationService slotTimeCreationService, ConceptService conceptService, ReferenceService referenceService) { + this.scheduleService = scheduleService; + this.scheduleFactory = scheduleFactory; + this.slotFactory = slotFactory; + this.slotService = slotService; + this.slotTimeCreationService = slotTimeCreationService; + this.conceptService = conceptService; + this.referenceService = referenceService; + } + + @Override + public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest) { + Schedule schedule = scheduleFactory.createScheduleForMedicationFrom(scheduleMedicationRequest); + Schedule savedSchedule = scheduleService.saveSchedule(schedule); + List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, savedSchedule); + slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime) + .forEach(slotService::saveSlot); + + return savedSchedule; + } + + @Override + public List getMedicationSlots(String patientUuid, ServiceType serviceType, LocalDate forDate) { + Concept concept = conceptService.getConceptByName(serviceType.conceptName()); + Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); + if(!subjectReference.isPresent()) + return Collections.emptyList(); + return slotService.getSlotsBySubjectReferenceIdAndForDateAndServiceType(subjectReference.get(), forDate, concept); + } + + @Override + public List getMedicationSchedules(String patientUuid, ServiceType serviceType) { + Concept concept = conceptService.getConceptByName(serviceType.conceptName()); + Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); + if(!subjectReference.isPresent()) + return Collections.emptyList(); + return scheduleService.getSchedulesBySubjectReferenceIdAndServiceType(subjectReference.get(), concept); + } + + @Override + public List getMedicationSchedules(String patientUuid, ServiceType serviceType, List orderUuids) { + Concept concept = conceptService.getConceptByName(serviceType.conceptName()); + Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); + if(!subjectReference.isPresent()) + return Collections.emptyList(); + return scheduleService.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(subjectReference.get(), concept, orderUuids); + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java new file mode 100644 index 0000000..489435c --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -0,0 +1,87 @@ +package org.openmrs.module.ipd.service.impl; + +import org.openmrs.DrugOrder; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static org.openmrs.module.ipd.contract.ScheduleMedicationRequest.MedicationFrequency.FIXED_SCHEDULE_FREQUENCY; +import static org.openmrs.module.ipd.contract.ScheduleMedicationRequest.MedicationFrequency.START_TIME_DURATION_FREQUENCY; + +@Component +public class SlotTimeCreationService { + public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, Schedule savedSchedule) { + DrugOrder order = (DrugOrder) savedSchedule.getOrder(); + + if (request.getSlotStartTimeAsLocaltime() != null && request.getMedicationFrequency() == START_TIME_DURATION_FREQUENCY) { + return getSlotsStartTimeWithStartTimeDurationFrequency(request, order); + } else if (!CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) && request.getMedicationFrequency() == FIXED_SCHEDULE_FREQUENCY) { + return getSlotsStartTimeWithFixedScheduleFrequency(request, order); + } + + return Collections.emptyList(); + } + + private List getSlotsStartTimeWithFixedScheduleFrequency(ScheduleMedicationRequest request, DrugOrder order) { + int numberOfSlotsStartTimeToBeCreated = (int) (Math.ceil(order.getQuantity() / order.getDose())); + List slotsStartTime = new ArrayList<>(); + + if (!CollectionUtils.isEmpty(request.getFirstDaySlotsStartTimeAsLocalTime())) { + List slotsToBeAddedForFirstDay = numberOfSlotsStartTimeToBeCreated < request.getFirstDaySlotsStartTimeAsLocalTime().size() + ? request.getFirstDaySlotsStartTimeAsLocalTime().subList(0, numberOfSlotsStartTimeToBeCreated) + : request.getFirstDaySlotsStartTimeAsLocalTime(); + + slotsStartTime.addAll(slotsToBeAddedForFirstDay); + numberOfSlotsStartTimeToBeCreated -= slotsToBeAddedForFirstDay.size(); + } + + if (!CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) && numberOfSlotsStartTimeToBeCreated > 0) { + + List initialSlotsToBeAddedForSecondDay = numberOfSlotsStartTimeToBeCreated < request.getDayWiseSlotsStartTimeAsLocalTime().size() + ? request.getDayWiseSlotsStartTimeAsLocalTime().subList(0, numberOfSlotsStartTimeToBeCreated) + : request.getDayWiseSlotsStartTimeAsLocalTime(); + slotsStartTime.addAll(initialSlotsToBeAddedForSecondDay); + numberOfSlotsStartTimeToBeCreated -= initialSlotsToBeAddedForSecondDay.size(); + + List nextSlotsStartTime = request.getDayWiseSlotsStartTimeAsLocalTime(); + while (numberOfSlotsStartTimeToBeCreated > 0) { + nextSlotsStartTime = nextSlotsStartTime.stream().map(slotStartTime -> slotStartTime.plusHours(24)).collect(Collectors.toList()); + if (numberOfSlotsStartTimeToBeCreated >= nextSlotsStartTime.size()) { + slotsStartTime.addAll(nextSlotsStartTime); + numberOfSlotsStartTimeToBeCreated -= nextSlotsStartTime.size(); + } else { + slotsStartTime.addAll(nextSlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated)); + numberOfSlotsStartTimeToBeCreated -= nextSlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated).size(); + } + } + } + + return slotsStartTime; + } + + private List getSlotsStartTimeWithStartTimeDurationFrequency(ScheduleMedicationRequest request, DrugOrder order) { + int numberOfSlotsStartTimeToBeCreated = (int) (Math.ceil(order.getQuantity() / order.getDose())); + List slotsStartTime = new ArrayList<>(); + Double slotDurationInHours = 24 / order.getFrequency().getFrequencyPerDay(); + LocalDateTime slotStartTime = request.getSlotStartTimeAsLocaltime(); + while (numberOfSlotsStartTimeToBeCreated-- > 0) { + slotsStartTime.add(slotStartTime); + if(slotDurationInHours.compareTo(1.0) >= 0) + { + slotStartTime = slotStartTime.plusHours(slotDurationInHours.longValue()); + } + else { + Double minutesToBeAdded = 60 * slotDurationInHours; + slotStartTime = slotStartTime.plusMinutes(minutesToBeAdded.longValue()); + } + } + return slotsStartTime; + } +} diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml new file mode 100644 index 0000000..067eda0 --- /dev/null +++ b/omod/src/main/resources/config.xml @@ -0,0 +1,20 @@ + + + + + bahmni-ipd + Bahmni IPD + 1.0.0-SNAPSHOT + ${MODULE_PACKAGE} + Bahmni + ${project.parent.description} + + + org.openmrs.module.webservices.rest + org.bahmni.module.bahmnicore + org.openmrs.module.bedmanagement + + + org.openmrs.module.ipd.api.IPDActivator + + diff --git a/omod/src/main/resources/webModuleApplicationContext.xml b/omod/src/main/resources/webModuleApplicationContext.xml new file mode 100644 index 0000000..82e84de --- /dev/null +++ b/omod/src/main/resources/webModuleApplicationContext.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/omod/src/test/java/org/openmrs/module/ipd/BaseIntegrationTest.java b/omod/src/test/java/org/openmrs/module/ipd/BaseIntegrationTest.java new file mode 100644 index 0000000..642bc1f --- /dev/null +++ b/omod/src/test/java/org/openmrs/module/ipd/BaseIntegrationTest.java @@ -0,0 +1,7 @@ +package org.openmrs.module.ipd; + +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(locations = {"classpath:TestingApplicationContext.xml"}) +public abstract class BaseIntegrationTest extends BaseWebControllerTest { +} diff --git a/omod/src/test/java/org/openmrs/module/ipd/BaseWebControllerTest.java b/omod/src/test/java/org/openmrs/module/ipd/BaseWebControllerTest.java new file mode 100644 index 0000000..169b6e5 --- /dev/null +++ b/omod/src/test/java/org/openmrs/module/ipd/BaseWebControllerTest.java @@ -0,0 +1,176 @@ +package org.openmrs.module.ipd; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import junit.framework.Assert; +import org.junit.Ignore; +import org.openmrs.web.test.BaseModuleWebContextSensitiveTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.HandlerExecutionChain; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.Map; + +@Ignore +@ContextConfiguration(locations = {"classpath:TestingApplicationContext.xml"}) +public class BaseWebControllerTest extends BaseModuleWebContextSensitiveTest { + + @Autowired + private RequestMappingHandlerAdapter handlerAdapter; + + @Autowired + private List handlerMappings; + + private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); + + /** + * Creates a request from the given parameters. + *

+ * The requestURI is automatically preceded with "/rest/" + RestConstants.VERSION_1. + * + * @param method + * @param requestURI + * @return + */ + public MockHttpServletRequest request(RequestMethod method, String requestURI) { + MockHttpServletRequest request = new MockHttpServletRequest(method.toString(), requestURI); + request.addHeader("content-type", "application/json"); + request.addHeader("accept", "application/json"); + return request; + } + + public static class Parameter { + + public String name; + + public String value; + + public Parameter(String name, String value) { + this.name = name; + this.value = value; + } + } + + public MockHttpServletRequest newRequest(RequestMethod method, String requestURI, Parameter... parameters) { + MockHttpServletRequest request = request(method, requestURI); + for (Parameter parameter : parameters) { + request.addParameter(parameter.name, parameter.value); + } + return request; + } + + public MockHttpServletRequest newRequest(RequestMethod method, String requestURI, Map headers, Parameter... parameters) { + MockHttpServletRequest request = newRequest(method, requestURI, parameters); + for (String key : headers.keySet()) { + request.addHeader(key, headers.get(key)); + } + return request; + } + + public MockHttpServletRequest newDeleteRequest(String requestURI, Parameter... parameters) { + return newRequest(RequestMethod.DELETE, requestURI, parameters); + } + + public MockHttpServletRequest newGetRequest(String requestURI, Parameter... parameters) { + return newRequest(RequestMethod.GET, requestURI, parameters); + } + + public MockHttpServletRequest newGetRequest(String requestURI, Map headers, Parameter... parameters) { + return newRequest(RequestMethod.GET, requestURI, headers, parameters); + } + + public MockHttpServletRequest newPostRequest(String requestURI, Object content) { + return newWriteRequest(requestURI, content, RequestMethod.POST); + } + + public MockHttpServletRequest newPutRequest(String requestURI, Object content) { + return newWriteRequest(requestURI, content, RequestMethod.PUT); + } + + private MockHttpServletRequest newWriteRequest(String requestURI, Object content, RequestMethod requestMethod) { + MockHttpServletRequest request = request(requestMethod, requestURI); + try { + String json = new ObjectMapper().writeValueAsString(content); + request.setContent(json.getBytes("UTF-8")); + } catch (Exception e) { + throw new RuntimeException(e); + } + return request; + } + + public MockHttpServletRequest newPostRequest(String requestURI, String content) { + MockHttpServletRequest request = request(RequestMethod.POST, requestURI); + try { + request.setContent(content.getBytes("UTF-8")); + } catch (Exception e) { + throw new RuntimeException(e); + } + return request; + } + + public MockHttpServletRequest newPutRequest(String requestURI, String content) { + MockHttpServletRequest request = request(RequestMethod.PUT, requestURI); + try { + request.setContent(content.getBytes("UTF-8")); + } catch (Exception e) { + throw new RuntimeException(e); + } + return request; + } + + /** + * Passes the given request to a proper controller. + * + * @param request + * @return + * @throws Exception + */ + public MockHttpServletResponse handle(HttpServletRequest request) throws Exception { + MockHttpServletResponse response = new MockHttpServletResponse(); + + HandlerExecutionChain handlerExecutionChain = null; + for (RequestMappingHandlerMapping handlerMapping : handlerMappings) { + handlerExecutionChain = handlerMapping.getHandler(request); + if (handlerExecutionChain != null) { + break; + } + } + Assert.assertNotNull("The request URI does not exist", handlerExecutionChain); + + handlerAdapter.handle(request, response, handlerExecutionChain.getHandler()); + + return response; + } + + /** + * Deserializes the JSON response. + * + * @param response + * @param type + * @return + * @throws Exception + */ + public T deserialize(MockHttpServletResponse response, Class type) throws Exception { + return objectMapper.readValue(response.getContentAsString(), type); + } + + /** + * Deserializes the JSON response. + * + * @param response + * @param typeReference + * @return + * @throws Exception + */ + public T deserialize(MockHttpServletResponse response, final TypeReference typeReference) throws Exception { + return objectMapper.readValue(response.getContentAsString(), typeReference); + } +} \ No newline at end of file diff --git a/omod/src/test/java/org/openmrs/module/ipd/controller/IPDScheduleControllerIntegrationTest.java b/omod/src/test/java/org/openmrs/module/ipd/controller/IPDScheduleControllerIntegrationTest.java new file mode 100644 index 0000000..e135b58 --- /dev/null +++ b/omod/src/test/java/org/openmrs/module/ipd/controller/IPDScheduleControllerIntegrationTest.java @@ -0,0 +1,57 @@ +package org.openmrs.module.ipd.controller; + +import com.fasterxml.jackson.core.type.TypeReference; +import org.hibernate.SessionFactory; +import org.hibernate.query.Query; +import org.junit.Test; +import org.openmrs.DrugOrder; +import org.openmrs.module.bedmanagement.entity.BedPatientAssignment; +import org.openmrs.module.ipd.BaseIntegrationTest; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.service.ScheduleService; +import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletResponse; + +import java.util.List; + +/*public class IPDScheduleControllerIntegrationTest extends BaseIntegrationTest { + + @Autowired + private ScheduleService scheduleService; + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void shouldSaveMedicationSchedule() throws Exception { + + List allDrugOrders = getAllDrudOrders(); + + String content = "{ \"providerUuid\": \"823fdcd7-3f10-11e4-adec-0800271c1b75\", " + + "\"patientUuid\": \"2c33920f-7aa6-48d6-998a-60412d8ff7d5\", " + + "\"orderUuid\": \""+allDrugOrders.get(0).getUuid()+"\", " + + "\"slotStartTime\": \"2107-07-15T17:30:00.0\"," + + "\"firstDaySlotsStartTime\": [\"2107-07-15T17:30:00.0\"]," + + "\"dayWiseSlotsStartTime\": [\"2107-07-15T17:30:00.0\"]," + + "\"comments\":\"changes the schedule\"," + + "\"medicationFrequency\":\"START_TIME_DURATION_FREQUENCY\"" + + "}"; + + MockHttpServletResponse response = handle(newPostRequest("/rest/" + RestConstants.VERSION_1 + "/ipd/schedule/type/medication", content)); + ScheduleMedicationResponse scheduleMedicationResponse = deserialize(response, new TypeReference() {}); + Schedule savedSchedule = scheduleService.getSchedule(scheduleMedicationResponse.getId()); + scheduleService.purgeSchedule(savedSchedule); + } + + private List getAllDrudOrders() { + Query query = sessionFactory.getCurrentSession().createQuery("FROM org.openmrs.DrugOrder"); + return (List) query.getResultList(); + } + + private List getAllBedsAssignedToPatient() { + Query query = sessionFactory.getCurrentSession().createQuery("FROM org.openmrs.module.bedmanagement.entity.BedPatientAssignment"); + return (List) query.getResultList(); + } +}*/ diff --git a/omod/src/test/resources/config.xml b/omod/src/test/resources/config.xml new file mode 100644 index 0000000..040350d --- /dev/null +++ b/omod/src/test/resources/config.xml @@ -0,0 +1,21 @@ + + + + + + bahmni-ipd + Bahmni IPD + 1.0.0-SNAPSHOT + Provides bahmni ipd services + ${MODULE_PACKAGE} + Bahmni + + + org.openmrs.module.webservices.rest + org.bahmni.module.bahmnicore + + + org.openmrs.module.ipd.api.IPDActivator + + 1.11.6 + \ No newline at end of file diff --git a/omod/src/test/resources/webModuleApplicationContext.xml b/omod/src/test/resources/webModuleApplicationContext.xml new file mode 100644 index 0000000..1a906f3 --- /dev/null +++ b/omod/src/test/resources/webModuleApplicationContext.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d5873b0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,377 @@ + + + 4.0.0 + + org.bahmni.module + bahmni-ipd + 1.0.0-SNAPSHOT + pom + Bahmni IPD + Bahmni IPD module contains all backend APIs for IPD + https://demo.mybahmni.org/bahmni/home/index.html + + + + GNU AFFERO GENERAL PUBLIC LICENSE + https://www.gnu.org/licenses/agpl-3.0.txt + + + + + Bahmnitw + bahmnicommunity@gmail.com + Bahmni + https://github.com/Bahmni + + + + scm:git:git@github.com:Bahmni/openmrs-module-ipd.git + scm:git:https://github.com/Bahmni/openmrs-module-ipd.git + https://github.com/Bahmni/openmrs-module-ipd + + + + api + omod + + + + 2.5.10 + 2.39.0 + 5.13.0 + 5.2.14.RELEASE + 4.13 + 2.0.7 + 1.3 + 3.5.11 + -Xmx1024m + 0.7.9 + 1.18.26 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.openmrs.maven.plugins + maven-openmrs-plugin + 1.0.1 + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.10 + + + **/*Test.java + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.5.1 + true + + + default-deploy + deploy + + deploy + + + + + nexus-sonatype + https://oss.sonatype.org + + + + + + + + + + org.projectlombok + lombok + ${lombokVersion} + provided + + + + org.openmrs.api + openmrs-api + ${openmrsPlatformVersion} + jar + provided + + + javax.servlet + servlet-api + + + + + org.openmrs.module + webservices.rest-omod-common + ${openMRSWebServicesVersion} + jar + provided + + + org.openmrs.module + webservices.rest-omod-2.0 + ${openMRSWebServicesVersion} + provided + + + org.openmrs.web + openmrs-web + ${openmrsPlatformVersion} + provided + + + org.openmrs.module + bedmanagement-api + ${bedManagementVersion} + provided + + + + + org.openmrs.module + webservices.rest-omod-common + ${openMRSWebServicesVersion} + test-jar + test + + + org.openmrs.web + openmrs-web + ${openmrsPlatformVersion} + test-jar + test + + + org.openmrs.api + openmrs-api + ${openmrsPlatformVersion} + test-jar + test + + + javax.servlet + servlet-api + + + + + org.openmrs.test + openmrs-test + ${openmrsPlatformVersion} + pom + test + + + javax.servlet + servlet-api + 2.5 + test + + + + + junit + junit + ${junitVersion} + + + org.hamcrest + hamcrest-core + + + test + + + + + org.powermock + powermock-api-mockito2 + ${powerMockVersion} + test + + + mockito-all + org.mockito + + + + + org.powermock + powermock-module-junit4 + ${powerMockVersion} + test + + + + + org.mockito + mockito-core + ${mockitoVersion} + + + org.hamcrest + hamcrest-core + + + test + + + + + + + openmrs-repo + OpenMRS Nexus Repository + https://mavenrepo.openmrs.org/public + + + central + Maven Repository Switchboard + default + https://repo1.maven.org/maven2 + + + sonatype-nexus-releases + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/releases + + false + + + true + + + + + + + openmrs-repo + OpenMRS Nexus Repository + https://mavenrepo.openmrs.org/public + + false + + + + + + + nexus-sonatype + https://oss.sonatype.org/content/repositories/snapshots + + + nexus-sonatype + https://oss.sonatype.org/service/local/staging/deploy/maven2 + + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.17 + + + + integration-test + verify + + + -Xmx512m + + **/*IT.java + + + + + + + + + + From b81a4111aa803c9b1677626d1a6e4f9dd78b925a Mon Sep 17 00:00:00 2001 From: Arjun G <91885483+Arjun-Go@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:55:03 +0530 Subject: [PATCH 02/75] A-1205974389432443 | Feedbacks on Medication Schedule (#3) * [Ritesh] | 1. Repo set up. 2. Created Slot and Schedule entity 3.Saving IPD Medication Schedule without creating slots. * [Ritesh] | 1. Update package name 2. Added Dao and Service layer for reference 3. Minor fixes * [Ritesh] | 1.Rename Schedule Strategy to MedicationFrequency * [Ritesh] | 1. Migration for slot. 2. Slot creation from schedule * [Ritesh] | 1. Refactor SlotTimeCreationService * [Ritesh] | 1. Handle time zone issue while creating slots and schedule. * [Ritesh] | 1. Changing the url of saving medication * [Ritesh] | 1. Returning slots * [Ritesh] | Get schedule for Drug chart * [Ritesh] | Fix date time issue in slots response * [Ritesh] | Refactoring and Added test * [Ritesh] | 1. Change for reference id to subject reference id and by reference id to actor reference id. 2. Also added pre-condition before adding medication concept for ipd. * [Ritesh] | 1. Refactoring ServiceType * [Ritesh] | 1. Bug Fix return empty list if now slots are not present for a patient on specific day. * [Ritesh] | 1. Updated README file * [Ritesh] | 1. Fixed time zone issue in test * add. endpoint to get list of IPD medications scheduled for a patient * refactor. endpoint and updated tests in DAO and service classes * refactor. namings for schedule DAO methods * fix. test failures in ScheduleImpl * add. changes to create one schedule for a patient * update. columns in Schedule and Slot table * update. set end date as null * fix tests for Slot and Schedule Hiberate and DAOs. Updated responses for GET calls * fix tests Schedule DAO * remove unnecessary fields * API Change to accomodate Editable Remaining day slot start time for medication --------- Co-authored-by: Ritesh Ghiya Co-authored-by: Kalaiyarasan Raja --- .../module/ipd/api/dao/ScheduleDAO.java | 4 +- .../openmrs/module/ipd/api/dao/SlotDAO.java | 4 + .../api/dao/impl/HibernateScheduleDAO.java | 31 ++---- .../ipd/api/dao/impl/HibernateSlotDAO.java | 26 +++++ .../module/ipd/api/model/Schedule.java | 16 +-- .../openmrs/module/ipd/api/model/Slot.java | 44 ++------ .../ipd/api/service/ScheduleService.java | 4 +- .../module/ipd/api/service/SlotService.java | 5 + .../api/service/impl/ScheduleServiceImpl.java | 14 +-- .../ipd/api/service/impl/SlotServiceImpl.java | 10 ++ api/src/main/resources/liquibase.xml | 29 +++++ .../HibernateScheduleDAOIntegrationTest.java | 92 +++++++--------- .../impl/HibernateSlotDAOIntegrationTest.java | 104 +++++++++++++++++- .../service/impl/ScheduleServiceImplTest.java | 44 +------- .../api/service/impl/SlotServiceImplTest.java | 46 ++++++++ .../contract/MedicationScheduleResponse.java | 37 +------ .../ipd/contract/MedicationSlotResponse.java | 37 +++++++ .../contract/ScheduleMedicationRequest.java | 5 + .../contract/ScheduleMedicationResponse.java | 18 ++- .../ipd/controller/IPDScheduleController.java | 19 ++-- .../module/ipd/factory/ScheduleFactory.java | 18 ++- .../module/ipd/factory/SlotFactory.java | 4 +- .../ipd/service/IPDScheduleService.java | 4 +- .../service/impl/IPDScheduleServiceImpl.java | 35 ++++-- .../service/impl/SlotTimeCreationService.java | 14 ++- 25 files changed, 414 insertions(+), 250 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java index d8aa917..196a23b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java @@ -1,5 +1,6 @@ package org.openmrs.module.ipd.api.dao; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.api.db.DAOException; import org.springframework.stereotype.Repository; @@ -15,6 +16,5 @@ public interface ScheduleDAO { Schedule saveSchedule(Schedule schedule) throws DAOException; - List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws DAOException; - List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws DAOException; + Schedule getScheduleByVisit(Visit visit) throws DAOException; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 9d99330..df03ade 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -17,4 +17,8 @@ public interface SlotDAO { Slot saveSlot(Slot slot) throws DAOException; List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java index 1dc8e29..5a15768 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAO.java @@ -2,18 +2,15 @@ import org.hibernate.SessionFactory; import org.hibernate.query.Query; -import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.api.db.DAOException; import org.openmrs.module.ipd.api.dao.ScheduleDAO; -import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public class HibernateScheduleDAO implements ScheduleDAO { @@ -36,25 +33,15 @@ public Schedule saveSchedule(Schedule schedule) throws DAOException { return schedule; } - public List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws DAOException { - Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Schedule schedule WHERE schedule.subject = :subject AND schedule.serviceType = :serviceType"); - - - query.setParameter("subject", subject); - query.setParameter("serviceType", serviceType); - return query.getResultList(); - } - - @Override - public List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws DAOException { + @Override + public Schedule getScheduleByVisit(Visit visit) throws DAOException { Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Schedule schedule WHERE schedule.subject = :subject AND schedule.serviceType = :serviceType AND schedule.order.uuid IN :orderUuids"); + .createQuery("FROM Schedule schedule " + + "WHERE schedule.visit = :visit " + + "and active = 1"); - query.setParameter("subject", subject); - query.setParameter("serviceType", serviceType); - query.setParameter("orderUuids", orderUuids); + query.setParameter("visit", visit); - return query.getResultList(); - } + return (Schedule) query.uniqueResult(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 1184496..d58259b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -51,4 +51,30 @@ public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference return query.getResultList(); } + + @Override + public List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and slot.serviceType=:serviceType"); + + query.setParameter("subject", subject); + query.setParameter("serviceType", serviceType); + + return query.getResultList(); + } + + @Override + public List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Slot slot " + + "WHERE slot.schedule.subject=:subject and " + + "slot.serviceType=:serviceType and" + + " slot.order.uuid IN :orderUuids"); + + query.setParameter("subject", subject); + query.setParameter("serviceType", serviceType); + query.setParameter("orderUuids", orderUuids); + + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java index 63e495f..691c24d 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Schedule.java @@ -5,7 +5,7 @@ import lombok.NoArgsConstructor; import org.openmrs.BaseChangeableOpenmrsData; import org.openmrs.Concept; -import org.openmrs.Order; +import org.openmrs.Visit; import javax.persistence.*; import java.time.LocalDateTime; @@ -44,26 +44,18 @@ public class Schedule extends BaseChangeableOpenmrsData { @Column(name = "active", nullable = false) private boolean active = Boolean.TRUE; - @OneToOne - @JoinColumn(name = "service_category_id", referencedColumnName = "concept_id") - private Concept serviceCategory; // null not in use - @OneToOne @JoinColumn(name = "service_type_id", referencedColumnName = "concept_id", nullable = false) private Concept serviceType; @OneToOne - @JoinColumn(name = "speciality_id", referencedColumnName = "concept_id") - private Concept speciality; // null not in use - - @OneToOne - @JoinColumn(name = "order_id", referencedColumnName = "order_id") - private Order order; + @JoinColumn(name = "visit_id", referencedColumnName = "visit_id") + private Visit visit; @Column(name = "start_date", nullable = false) private LocalDateTime startDate; - @Column(name = "end_date", nullable = false) + @Column(name = "end_date") private LocalDateTime endDate; @Column(name = "comments") diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index d5ce4dd..937de6b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -4,8 +4,9 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.openmrs.BaseChangeableOpenmrsData; -import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Location; +import org.openmrs.Concept; import javax.persistence.*; import java.time.LocalDateTime; @@ -39,13 +40,6 @@ public enum SlotStatus { @JoinColumn(name = "location_id", referencedColumnName = "location_id") private Location location; // bed location for patient - /** - * The Service Category of the Schedule - */ - @OneToOne - @JoinColumn(name = "service_category_id", referencedColumnName = "concept_id") - private Concept serviceCategory; // null not in use - /** * The Service Type of the Schedule */ @@ -53,54 +47,38 @@ public enum SlotStatus { @JoinColumn(name = "service_type_id", referencedColumnName = "concept_id", nullable = false) private Concept serviceType; // as per schedule service type - /** - * The Speciality of the Schedule - */ - @OneToOne - @JoinColumn(name = "speciality_id", referencedColumnName = "concept_id") - private Concept speciality; // null not in sue - - /** - * The Appointment Type of the Schedule - */ - @OneToOne - @JoinColumn(name = "appointment_type_id", referencedColumnName = "concept_id") - private Concept appointmentType; // null not in use - /** * The entity that belongs to a Schedule */ @ManyToOne @JoinColumn(name = "schedule_id", referencedColumnName = "schedule_id", nullable = false) private Schedule schedule; + + /** + * Order with respect to the Slot + */ + @OneToOne + @JoinColumn(name = "order_id", referencedColumnName = "order_id") + private Order order; /** * The Start Date the Slot */ @Column(name = "start_date_time", nullable = false) private LocalDateTime startDateTime; // slot start time - + /** * The End Date the Slot */ @Column(name = "end_date_time") private LocalDateTime endDateTime; // can be null for now - - /** - * Any Comment for the Slot - */ - @Column(name = "comments") - private String comments; // null not is use - + /** * The current status of the slot. */ @Column(name = "status", nullable = false) @Enumerated(EnumType.STRING) private SlotStatus status = SlotStatus.SCHEDULED; - - @Column(name = "overbooked", nullable = false) - private Boolean overbooked = Boolean.FALSE; // not is use } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java index 97b4e04..3df1903 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service; import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.api.APIException; @@ -18,6 +19,5 @@ public interface ScheduleService extends OpenmrsService { // @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) Schedule saveSchedule(Schedule schedule) throws APIException; - List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws APIException; - List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws APIException; + Schedule getScheduleByVisit(Visit visit); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 60eb1ed..dc3fb56 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -2,6 +2,7 @@ import org.openmrs.Concept; import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.api.APIException; import org.openmrs.api.OpenmrsService; @@ -20,4 +21,8 @@ public interface SlotService extends OpenmrsService { Slot saveSlot(Slot slot) throws APIException; List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java index a1cdb07..f331151 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.ScheduleDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; @@ -39,13 +40,8 @@ public Schedule saveSchedule(Schedule schedule) throws APIException { return scheduleDAO.saveSchedule(schedule); } - @Override - public List getSchedulesBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) throws APIException { - return scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(subject, serviceType); - } - - @Override - public List getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) throws APIException { - return scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(subject, serviceType, orderUuids); - } + @Override + public Schedule getScheduleByVisit(Visit visit) { + return scheduleDAO.getScheduleByVisit(visit); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 9306a81..25a33cd 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -45,4 +45,14 @@ public Slot saveSlot(Slot slot) throws APIException { public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType) { return slotDAO.getSlotsBySubjectReferenceIdAndForDateAndServiceType(subject, forDate, serviceType); } + + @Override + public List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) { + return slotDAO.getSlotsBySubjectReferenceIdAndServiceType(subject, serviceType); + } + + @Override + public List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) { + return slotDAO.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(subject, serviceType, orderUuids); + } } diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 9b708b8..1740908 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -189,4 +189,33 @@ 'MedicationRequest', 'en', 1, 1, now(), 'FULLY_SPECIFIED', 0, uuid()); + + + + + + + + + + + + + + + + + + + + + + + ALTER TABLE ipd_schedule MODIFY COLUMN end_date datetime NULL; + + diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java index 7d2484e..a6806e5 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateScheduleDAOIntegrationTest.java @@ -6,7 +6,9 @@ import org.openmrs.Concept; import org.openmrs.DrugOrder; import org.openmrs.Patient; +import org.openmrs.Visit; import org.openmrs.api.context.Context; +import org.openmrs.api.db.VisitDAO; import org.openmrs.module.ipd.api.BaseIntegrationTest; import org.openmrs.module.ipd.api.dao.ScheduleDAO; import org.openmrs.module.ipd.api.model.Reference; @@ -15,8 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; +import java.util.Date; public class HibernateScheduleDAOIntegrationTest extends BaseIntegrationTest { @@ -26,32 +27,37 @@ public class HibernateScheduleDAOIntegrationTest extends BaseIntegrationTest { @Autowired private SessionFactory sessionFactory; + @Autowired + private VisitDAO visitDAO; + @Test public void shouldSaveTheScheduledCreatedForPatientGivenPatientSchedule() { - DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); - LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Patient patient = Context.getPatientService().getPatientByUuid("2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Visit visit = new Visit(); + visit.setPatient(patient); + visit.setStartDatetime(new Date()); + visit.setVisitType(Context.getVisitService().getVisitType(1)); Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); - schedule.setEndDate(endDate); schedule.setServiceType(testConcept); + schedule.setVisit(visit); Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); - Assertions.assertEquals(drugOrder, schedule.getOrder()); Assertions.assertEquals(patientReference, schedule.getSubject()); Assertions.assertEquals(providerReference, schedule.getActor()); Assertions.assertEquals(startDate, schedule.getStartDate()); - Assertions.assertEquals(endDate, schedule.getEndDate()); Assertions.assertEquals(testConcept, schedule.getServiceType()); + Assertions.assertEquals(visit, schedule.getVisit()); sessionFactory.getCurrentSession().delete(savedSchedule); } @@ -64,87 +70,69 @@ public void shouldGetTheSavedScheduledCreatedForPatientGivenPatientSchedule() { Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); - LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Patient patient = Context.getPatientService().getPatientByUuid("2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Visit visit = new Visit(); + visit.setPatient(patient); + visit.setStartDatetime(new Date()); + visit.setVisitType(Context.getVisitService().getVisitType(1)); + Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); - schedule.setEndDate(endDate); schedule.setServiceType(testConcept); + schedule.setVisit(visit); Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); Schedule scheduleById = scheduleDAO.getSchedule(savedSchedule.getId()); - Assertions.assertEquals(drugOrder, scheduleById.getOrder()); Assertions.assertEquals(patientReference, scheduleById.getSubject()); Assertions.assertEquals(providerReference, scheduleById.getActor()); Assertions.assertEquals(startDate, scheduleById.getStartDate()); - Assertions.assertEquals(endDate, scheduleById.getEndDate()); Assertions.assertEquals(testConcept, scheduleById.getServiceType()); + Assertions.assertEquals(visit, scheduleById.getVisit()); sessionFactory.getCurrentSession().delete(savedSchedule); } @Test - public void shouldGetTheSavedSchedulesForPatientByForReferenceIdAndServiceTypeAndOrderUuid() { + public void shouldGetTheSavedScheduleCreatedForPatientGivenVisit() { - String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; - DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9142"); Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); - LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); - - Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); - schedule.setSubject(patientReference); - schedule.setActor(providerReference); - schedule.setStartDate(startDate); - schedule.setEndDate(endDate); - schedule.setServiceType(testConcept); - Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); - List orderUuidList = new ArrayList<>(); - orderUuidList.add(orderUuid); - - List schedulesBySubjectReferenceIdAndServiceType = scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, testConcept, orderUuidList); - - Assertions.assertEquals(1, schedulesBySubjectReferenceIdAndServiceType.size()); - - sessionFactory.getCurrentSession().delete(savedSchedule); - } - - @Test - public void shouldGetTheSavedSchedulesForPatientByForReferenceIdAndServiceType() { - - String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; - DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); - Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); - Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); - Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); - LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); - LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + Visit visit = new Visit(); + visit.setPatient(new Patient(2)); + visit.setStartDatetime(new Date()); + visit.setVisitType(Context.getVisitService().getVisitType(1)); + Visit savedVisit = visitDAO.saveVisit(visit); Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); + schedule.setDateCreated(new Date()); + schedule.setActive(true); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); - schedule.setEndDate(endDate); schedule.setServiceType(testConcept); + schedule.setVisit(savedVisit); Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); - List orderUuidList = new ArrayList<>(); - orderUuidList.add(orderUuid); - List schedulesBySubjectReferenceIdAndServiceType = scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, testConcept); + Schedule scheduleByVisit = scheduleDAO.getScheduleByVisit(visit); - Assertions.assertEquals(1, schedulesBySubjectReferenceIdAndServiceType.size()); + Assertions.assertEquals(patientReference, scheduleByVisit.getSubject()); + Assertions.assertEquals(providerReference, scheduleByVisit.getActor()); + Assertions.assertEquals(startDate, scheduleByVisit.getStartDate()); + Assertions.assertEquals(testConcept, scheduleByVisit.getServiceType()); + Assertions.assertEquals(visit, scheduleByVisit.getVisit()); sessionFactory.getCurrentSession().delete(savedSchedule); + sessionFactory.getCurrentSession().delete(savedVisit); } } \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index cee6719..2d26ef5 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest { @@ -41,7 +42,7 @@ public void shouldSaveTheSlotForPatientGivenPatientSchedule() { LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); +// schedule.setOrder(drugOrder); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); @@ -74,7 +75,7 @@ public void shouldGetTheSavedSlotForPatientGivenPatientSchedule() { LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); +// schedule.setOrder(drugOrder); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); @@ -108,7 +109,7 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndForDateAndService LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); Schedule schedule = new Schedule(); - schedule.setOrder(drugOrder); +// schedule.setOrder(drugOrder); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); @@ -140,4 +141,101 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndForDateAndService sessionFactory.getCurrentSession().delete(savedSlot2); sessionFactory.getCurrentSession().delete(savedSchedule); } + + @Test + public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceTypeAndOrderUuid() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime slotStartTime = LocalDateTime.now(); + + Slot slot1 = new Slot(); + slot1.setSchedule(savedSchedule); + slot1.setServiceType(testConcept); + slot1.setStartDateTime(slotStartTime); + slot1.setOrder(drugOrder); + + Slot slot2 = new Slot(); + slot2.setSchedule(savedSchedule); + slot2.setServiceType(testConcept); + slot2.setStartDateTime(slotStartTime.plusDays(1)); + slot2.setOrder(drugOrder2); + + Slot savedSlot1 = slotDAO.saveSlot(slot1); + Slot savedSlot2 = slotDAO.saveSlot(slot2); + + List orderUuidList = new ArrayList<>(); + orderUuidList.add(orderUuid); + + List slotsBySubjectReferenceIdAndServiceTypeAndOrderUuids = slotDAO.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, testConcept, orderUuidList); + + Assertions.assertEquals(1, slotsBySubjectReferenceIdAndServiceTypeAndOrderUuids.size()); + + sessionFactory.getCurrentSession().delete(savedSlot1); + sessionFactory.getCurrentSession().delete(savedSlot2); + sessionFactory.getCurrentSession().delete(savedSchedule); + } + + @Test + public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceType() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime slotStartTime = LocalDateTime.now(); + + Slot slot1 = new Slot(); + slot1.setSchedule(savedSchedule); + slot1.setServiceType(testConcept); + slot1.setStartDateTime(slotStartTime); + slot1.setOrder(drugOrder); + + Slot slot2 = new Slot(); + slot2.setSchedule(savedSchedule); + slot2.setServiceType(testConcept); + slot2.setStartDateTime(slotStartTime.plusDays(1)); + slot2.setOrder(drugOrder2); + + Slot savedSlot1 = slotDAO.saveSlot(slot1); + Slot savedSlot2 = slotDAO.saveSlot(slot2); + + List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectReferenceIdAndServiceType(patientReference, testConcept); + + Assertions.assertEquals(2, slotsBySubjectReferenceIdAndServiceType.size()); + + sessionFactory.getCurrentSession().delete(savedSlot1); + sessionFactory.getCurrentSession().delete(savedSlot2); + sessionFactory.getCurrentSession().delete(savedSchedule); + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java index 0c6ea86..ee897c3 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImplTest.java @@ -9,6 +9,7 @@ import org.openmrs.Concept; import org.openmrs.ConceptName; import org.openmrs.Patient; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.ScheduleDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; @@ -53,49 +54,16 @@ public void shouldInvokeGetScheduleWithGivenScheduleId() { } @Test - public void shouldInvokeGetSchedulesByForReferenceAndServiceTypeWithGivenScheduleId() { + public void shouldInvokeGetScheduleWithGivenVisit() { Schedule expectedSchedule = new Schedule(); + Visit visit = new Visit(); expectedSchedule.setId(1); - List schedules = new ArrayList<>(); - LocalDate today = LocalDate.now(); - Concept medicationRequestConcept = new Concept(); - ConceptName conceptName = new ConceptName(); - conceptName.setName("MedicationRequest"); - conceptName.setLocale(Locale.US); - medicationRequestConcept.setFullySpecifiedName(conceptName); + Mockito.when(scheduleDAO.getScheduleByVisit(visit)).thenReturn(expectedSchedule); - Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + scheduleService.getScheduleByVisit(visit); - Mockito.when(scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept)).thenReturn(schedules); - - scheduleService.getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); - - Mockito.verify(scheduleDAO, Mockito.times(1)).getSchedulesBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); + Mockito.verify(scheduleDAO, Mockito.times(1)).getScheduleByVisit(visit); } - @Test - public void shouldInvokeGetSchedulesByForReferenceAndServiceTypeAndOrderUuidsWithGivenScheduleId() { - Schedule expectedSchedule = new Schedule(); - expectedSchedule.setId(1); - List schedules = new ArrayList<>(); - - LocalDate today = LocalDate.now(); - Concept medicationRequestConcept = new Concept(); - ConceptName conceptName = new ConceptName(); - conceptName.setName("MedicationRequest"); - conceptName.setLocale(Locale.US); - medicationRequestConcept.setFullySpecifiedName(conceptName); - - List orderUuids = new ArrayList<>(); - orderUuids.add("orderUuid"); - - Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); - - Mockito.when(scheduleDAO.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids)).thenReturn(schedules); - - scheduleService.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); - - Mockito.verify(scheduleDAO, Mockito.times(1)).getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); - } } \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index a9e58b4..6e9cdde 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -11,6 +11,7 @@ import org.openmrs.Patient; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; import java.time.LocalDate; @@ -73,4 +74,49 @@ public void shouldInvokeGetSlotsByForReferenceAndForDateAndServiceTypeWithGivenS Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndForDateAndServiceType(patientReference, today, medicationRequestConcept); } + + @Test + public void shouldInvokeGetSlotsByForReferenceAndServiceTypeWithGivenScheduleId() { + List slots = new ArrayList<>(); + + LocalDate today = LocalDate.now(); + Concept medicationRequestConcept = new Concept(); + ConceptName conceptName = new ConceptName(); + conceptName.setName("MedicationRequest"); + conceptName.setLocale(Locale.US); + medicationRequestConcept.setFullySpecifiedName(conceptName); + + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(slotDAO.getSlotsBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept)).thenReturn(slots); + + slotService.getSlotsBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndServiceType(patientReference, medicationRequestConcept); + } + + @Test + public void shouldInvokeGetSlotsByForReferenceAndServiceTypeAndOrderUuidsWithGivenScheduleId() { + Schedule expectedSchedule = new Schedule(); + expectedSchedule.setId(1); + List slots = new ArrayList<>(); + + LocalDate today = LocalDate.now(); + Concept medicationRequestConcept = new Concept(); + ConceptName conceptName = new ConceptName(); + conceptName.setName("MedicationRequest"); + conceptName.setLocale(Locale.US); + medicationRequestConcept.setFullySpecifiedName(conceptName); + + List orderUuids = new ArrayList<>(); + orderUuids.add("orderUuid"); + + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(slotDAO.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids)).thenReturn(slots); + + slotService.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); + } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java index 94f501d..80ba08e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationScheduleResponse.java @@ -1,14 +1,11 @@ package org.openmrs.module.ipd.contract; -import com.fasterxml.jackson.annotation.JsonAutoDetect; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; -import org.openmrs.module.webservices.rest.web.ConversionUtil; -import org.openmrs.module.webservices.rest.web.representation.Representation; import java.util.List; import java.util.stream.Collectors; @@ -26,9 +23,8 @@ public class MedicationScheduleResponse { private String serviceType; private String comments; private long startDate; - private long endDate; - private Object order; - private List slots; + private Object endDate; + private List slots; public static MedicationScheduleResponse createFrom(Schedule schedule, List slots) { return MedicationScheduleResponse.builder() @@ -37,32 +33,11 @@ public static MedicationScheduleResponse createFrom(Schedule schedule, List firstDaySlotsStartTime; private List dayWiseSlotsStartTime; + private List remainingDaySlotsStartTime; private MedicationFrequency medicationFrequency; public enum MedicationFrequency { @@ -43,4 +44,8 @@ public List getFirstDaySlotsStartTimeAsLocalTime() { public List getDayWiseSlotsStartTimeAsLocalTime() { return dayWiseSlotsStartTime != null ? dayWiseSlotsStartTime.stream().map(DateTimeUtil::convertEpocUTCToLocalTimeZone).collect(Collectors.toList()) : null; } + + public List getRemainingDaySlotsStartTimeAsLocalTime() { + return remainingDaySlotsStartTime != null ? remainingDaySlotsStartTime.stream().map(DateTimeUtil::convertEpocUTCToLocalTimeZone).collect(Collectors.toList()) : null; + } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java index a5acd23..5478ead 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationResponse.java @@ -6,8 +6,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.openmrs.module.ipd.api.model.Schedule; -import org.openmrs.module.webservices.rest.web.ConversionUtil; -import org.openmrs.module.webservices.rest.web.representation.Representation; import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertLocalDateTimeToUTCEpoc; @@ -21,17 +19,17 @@ public class ScheduleMedicationResponse { private String patientUuid; private String comments; private long startDate; - private long endDate; + private Object endDate; private Object order; public static ScheduleMedicationResponse constructFrom(Schedule schedule) { return ScheduleMedicationResponse.builder() - .id(schedule.getId()) - .patientUuid(schedule.getSubject().getUuid()) - .comments(schedule.getComments()) - .order(ConversionUtil.convertToRepresentation(schedule.getOrder(), Representation.REF)) // TODO. Clarify why we need to use REF here with product team - .startDate(convertLocalDateTimeToUTCEpoc(schedule.getStartDate())) - .endDate(convertLocalDateTimeToUTCEpoc(schedule.getEndDate())) - .build(); + .id(schedule.getId()) + .patientUuid(schedule.getSubject().getUuid()) + .comments(schedule.getComments()) +// .order(ConversionUtil.convertToRepresentation(schedule.getOrder(), Representation.REF)) // TODO. Clarify why we need to use REF here with product team + .startDate(convertLocalDateTimeToUTCEpoc(schedule.getStartDate())) + .endDate(schedule.getEndDate() != null ? convertLocalDateTimeToUTCEpoc(schedule.getEndDate()) : null) + .build(); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 215d13c..f6bb85a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -4,6 +4,7 @@ import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.contract.MedicationScheduleResponse; +import org.openmrs.module.ipd.contract.MedicationSlotResponse; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; import org.openmrs.module.ipd.service.IPDScheduleService; @@ -52,8 +53,8 @@ public ResponseEntity createMedicationSchedule(@RequestBody ScheduleMedi @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "forDate"}) @ResponseBody - public ResponseEntity getMedicationScheduleByDate(@RequestParam(value = "patientUuid") String patientUuid, - @RequestParam(value = "forDate") long forDate) { + public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, + @RequestParam(value = "forDate") long forDate) { try { LocalDate localDate = convertEpocUTCToLocalTimeZone(forDate).toLocalDate(); List slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, localDate); @@ -66,17 +67,17 @@ public ResponseEntity getMedicationScheduleByDate(@RequestParam(value = @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid"}) @ResponseBody - public ResponseEntity getMedicationScheduleByOrderUuids(@RequestParam(value = "patientUuid") String patientUuid, - @RequestParam(value = "orderUuids", required = false) List orderUuids) { + public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value = "patientUuid") String patientUuid, + @RequestParam(value = "orderUuids", required = false) List orderUuids) { try { - List schedules; + List slots; if (orderUuids == null || orderUuids.isEmpty()) { - schedules = ipdScheduleService.getMedicationSchedules(patientUuid, MEDICATION_REQUEST); + slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST); } else { - schedules = ipdScheduleService.getMedicationSchedules(patientUuid, MEDICATION_REQUEST, orderUuids); + slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, orderUuids); } - List medicationResponses = schedules.stream() - .map(ScheduleMedicationResponse::constructFrom) + List medicationResponses = slots.stream() + .map(MedicationSlotResponse::createFrom) .collect(Collectors.toList()); return new ResponseEntity<>(medicationResponses, OK); } catch (Exception e) { diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java index 3c11a81..8daeb75 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/ScheduleFactory.java @@ -1,11 +1,10 @@ package org.openmrs.module.ipd.factory; import org.openmrs.Concept; -import org.openmrs.DrugOrder; import org.openmrs.Patient; import org.openmrs.Provider; +import org.openmrs.Visit; import org.openmrs.api.ConceptService; -import org.openmrs.api.OrderService; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.service.ReferenceService; @@ -21,21 +20,17 @@ @Component public class ScheduleFactory { - private final OrderService orderService; private final ConceptService conceptService; private final ReferenceService referenceService; @Autowired - public ScheduleFactory(OrderService orderService, ConceptService conceptService, ReferenceService referenceService) { - this.orderService = orderService; + public ScheduleFactory(ConceptService conceptService, ReferenceService referenceService) { this.conceptService = conceptService; this.referenceService = referenceService; } - public Schedule createScheduleForMedicationFrom(ScheduleMedicationRequest request) { + public Schedule createScheduleForMedicationFrom(ScheduleMedicationRequest request, Visit visit) { Schedule schedule = new Schedule(); - - DrugOrder drugOrder = (DrugOrder) orderService.getOrderByUuid(request.getOrderUuid()); Concept medicationRequestServiceType = conceptService.getConceptByName(MEDICATION_REQUEST.conceptName()); Reference subject = getReference(Patient.class.getTypeName(), request.getPatientUuid()); @@ -43,10 +38,11 @@ public Schedule createScheduleForMedicationFrom(ScheduleMedicationRequest reques schedule.setSubject(subject); schedule.setActor(actor); - schedule.setStartDate(convertDateToLocalDateTime(drugOrder.getEffectiveStartDate())); - schedule.setEndDate(convertDateToLocalDateTime(drugOrder.getEffectiveStopDate())); + schedule.setStartDate(convertDateToLocalDateTime(visit.getStartDatetime())); +// schedule.setEndDate(convertDateToLocalDateTime(null); + schedule.setServiceType(medicationRequestServiceType); - schedule.setOrder(drugOrder); + schedule.setVisit(visit); schedule.setActive(true); return schedule; diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java index c07c6fe..9373754 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.factory; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.api.ConceptService; import org.openmrs.api.PatientService; @@ -32,7 +33,7 @@ public SlotFactory(BedManagementService bedManagementService, ConceptService con this.patientService = patientService; } - public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime) { + public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime, Order drugOrder) { return slotsStartTime.stream().map(slotStartTime -> { Slot slot = new Slot(); @@ -47,6 +48,7 @@ public List createSlotsForMedicationFrom(Schedule savedSchedule, List getMedicationSlots(String patientUuid, ServiceType serviceType, LocalDate forDate); - List getMedicationSchedules(String patientUuid, ServiceType serviceType); - List getMedicationSchedules(String patientUuid, ServiceType serviceType, List orderUuids); + List getMedicationSlots(String patientUuid, ServiceType serviceType); + List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index e93bf57..e7ddbf3 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -1,8 +1,13 @@ package org.openmrs.module.ipd.service.impl; import org.openmrs.Concept; +import org.openmrs.DrugOrder; import org.openmrs.Patient; +import org.openmrs.Visit; import org.openmrs.api.ConceptService; +import org.openmrs.api.OrderService; +import org.openmrs.api.PatientService; +import org.openmrs.api.VisitService; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.ServiceType; @@ -35,9 +40,12 @@ public class IPDScheduleServiceImpl implements IPDScheduleService { private final SlotTimeCreationService slotTimeCreationService; private final ConceptService conceptService; private final ReferenceService referenceService; + private final VisitService visitService; + private final PatientService patientService; + private final OrderService orderService; @Autowired - public IPDScheduleServiceImpl(ScheduleService scheduleService, ScheduleFactory scheduleFactory, SlotFactory slotFactory, SlotService slotService, SlotTimeCreationService slotTimeCreationService, ConceptService conceptService, ReferenceService referenceService) { + public IPDScheduleServiceImpl(ScheduleService scheduleService, ScheduleFactory scheduleFactory, SlotFactory slotFactory, SlotService slotService, SlotTimeCreationService slotTimeCreationService, ConceptService conceptService, ReferenceService referenceService, VisitService visitService, PatientService patientService, OrderService orderService) { this.scheduleService = scheduleService; this.scheduleFactory = scheduleFactory; this.slotFactory = slotFactory; @@ -45,14 +53,23 @@ public IPDScheduleServiceImpl(ScheduleService scheduleService, ScheduleFactory s this.slotTimeCreationService = slotTimeCreationService; this.conceptService = conceptService; this.referenceService = referenceService; + this.visitService = visitService; + this.patientService = patientService; + this.orderService = orderService; } @Override public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest) { - Schedule schedule = scheduleFactory.createScheduleForMedicationFrom(scheduleMedicationRequest); - Schedule savedSchedule = scheduleService.saveSchedule(schedule); - List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, savedSchedule); - slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime) + Patient patient = patientService.getPatientByUuid(scheduleMedicationRequest.getPatientUuid()); + Visit visit = visitService.getActiveVisitsByPatient(patient).get(0); + Schedule savedSchedule = scheduleService.getScheduleByVisit(visit); + if(savedSchedule == null || savedSchedule.getId() == null) { + Schedule schedule = scheduleFactory.createScheduleForMedicationFrom(scheduleMedicationRequest, visit); + savedSchedule = scheduleService.saveSchedule(schedule); + } + DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); + List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); + slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order) .forEach(slotService::saveSlot); return savedSchedule; @@ -68,20 +85,20 @@ public List getMedicationSlots(String patientUuid, ServiceType serviceType } @Override - public List getMedicationSchedules(String patientUuid, ServiceType serviceType) { + public List getMedicationSlots(String patientUuid, ServiceType serviceType) { Concept concept = conceptService.getConceptByName(serviceType.conceptName()); Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); - return scheduleService.getSchedulesBySubjectReferenceIdAndServiceType(subjectReference.get(), concept); + return slotService.getSlotsBySubjectReferenceIdAndServiceType(subjectReference.get(), concept); } @Override - public List getMedicationSchedules(String patientUuid, ServiceType serviceType, List orderUuids) { + public List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids) { Concept concept = conceptService.getConceptByName(serviceType.conceptName()); Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); - return scheduleService.getSchedulesBySubjectReferenceIdAndServiceTypeAndOrderUuids(subjectReference.get(), concept, orderUuids); + return slotService.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(subjectReference.get(), concept, orderUuids); } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index 489435c..e1f4fc4 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -17,9 +17,7 @@ @Component public class SlotTimeCreationService { - public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, Schedule savedSchedule) { - DrugOrder order = (DrugOrder) savedSchedule.getOrder(); - + public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, DrugOrder order) { if (request.getSlotStartTimeAsLocaltime() != null && request.getMedicationFrequency() == START_TIME_DURATION_FREQUENCY) { return getSlotsStartTimeWithStartTimeDurationFrequency(request, order); } else if (!CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) && request.getMedicationFrequency() == FIXED_SCHEDULE_FREQUENCY) { @@ -51,9 +49,17 @@ private List getSlotsStartTimeWithFixedScheduleFrequency(Schedule numberOfSlotsStartTimeToBeCreated -= initialSlotsToBeAddedForSecondDay.size(); List nextSlotsStartTime = request.getDayWiseSlotsStartTimeAsLocalTime(); + List remainingDaySlotsStartTime = request.getRemainingDaySlotsStartTimeAsLocalTime(); while (numberOfSlotsStartTimeToBeCreated > 0) { nextSlotsStartTime = nextSlotsStartTime.stream().map(slotStartTime -> slotStartTime.plusHours(24)).collect(Collectors.toList()); - if (numberOfSlotsStartTimeToBeCreated >= nextSlotsStartTime.size()) { + if (!CollectionUtils.isEmpty(remainingDaySlotsStartTime) && numberOfSlotsStartTimeToBeCreated <= remainingDaySlotsStartTime.size()){ + List slotsToBeAddedForRemainingDay = numberOfSlotsStartTimeToBeCreated < remainingDaySlotsStartTime.size() + ? remainingDaySlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated) + : remainingDaySlotsStartTime; + numberOfSlotsStartTimeToBeCreated -= slotsToBeAddedForRemainingDay.size(); + slotsStartTime.addAll(slotsToBeAddedForRemainingDay); + } + else if (numberOfSlotsStartTimeToBeCreated >= nextSlotsStartTime.size()) { slotsStartTime.addAll(nextSlotsStartTime); numberOfSlotsStartTimeToBeCreated -= nextSlotsStartTime.size(); } else { From 2084c7b711fc28f88abadebcc55ed156add895b2 Mon Sep 17 00:00:00 2001 From: Arjun G <91885483+Arjun-Go@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:04:07 +0530 Subject: [PATCH 03/75] add. changes to automate omod publish for Bahmni-IPD-master branch (#4) --- .github/workflows/build_publish.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_publish.yaml b/.github/workflows/build_publish.yaml index 0a569fe..f9beb09 100644 --- a/.github/workflows/build_publish.yaml +++ b/.github/workflows/build_publish.yaml @@ -1,7 +1,9 @@ name: Build and Publish package on: push: - branches: [ main ] + branches: + - main + - Bahmni-IPD-master workflow_dispatch: jobs: From e2bcd0a515d9cad515e916082885f9cb436a11f7 Mon Sep 17 00:00:00 2001 From: Arjun G <91885483+Arjun-Go@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:53:11 +0530 Subject: [PATCH 04/75] Arjun | Fix deployment workflow (#5) * test. ipd publish workflow * revert. testing changes in deploy workflow * test changes with maven wrapper * revert. deploy for test branch --- .mvn/wrapper/maven-wrapper.properties | 18 +++ mvnw | 177 ++++++++++++++------------ mvnw.cmd | 24 +++- 3 files changed, 138 insertions(+), 81 deletions(-) create mode 100644 .mvn/wrapper/maven-wrapper.properties diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..ac18401 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/mvnw b/mvnw index b7f0646..8d937f4 100755 --- a/mvnw +++ b/mvnw @@ -19,7 +19,7 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.1.1 +# Apache Maven Wrapper startup batch script, version 3.2.0 # # Required ENV vars: # ------------------ @@ -53,7 +53,7 @@ fi cygwin=false; darwin=false; mingw=false -case "`uname`" in +case "$(uname)" in CYGWIN*) cygwin=true ;; MINGW*) mingw=true;; Darwin*) darwin=true @@ -61,7 +61,7 @@ case "`uname`" in # See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME else JAVA_HOME="/Library/Java/Home"; export JAVA_HOME fi @@ -71,38 +71,38 @@ esac if [ -z "$JAVA_HOME" ] ; then if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + JAVA_HOME=$(java-config --jre-home) fi fi # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi @@ -118,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`\\unset -f command; \\command -v java`" + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi @@ -150,108 +150,99 @@ find_maven_basedir() { fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done - printf '%s' "$(cd "$basedir"; pwd)" + printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" fi } -BASE_DIR=$(find_maven_basedir "$(dirname $0)") +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi +log "$MAVEN_PROJECTBASEDIR" ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi + log "Couldn't find $wrapperJarPath, downloading it ..." + if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $wrapperUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then - QUIET="--quiet" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - QUIET="" - fi + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" elif command -v curl > /dev/null; then - QUIET="--silent" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - QUIET="" - fi + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - [ $? -eq 0 ] || rm -f "$wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - javaSource=`cygpath --path --windows "$javaSource"` - javaClass=`cygpath --path --windows "$javaClass"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi if [ -e "$javaSource" ]; then if [ ! -e "$javaClass" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class + log " - Compiling MavenWrapperDownloader.java ..." ("$JAVA_HOME/bin/javac" "$javaSource") fi if [ -e "$javaClass" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi @@ -260,25 +251,55 @@ fi # End of extension ########################################################################################## +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ diff --git a/mvnw.cmd b/mvnw.cmd index 474c9d6..c4586b5 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,7 +18,7 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM Apache Maven Wrapper startup batch script, version 3.2.0 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @@ -119,7 +119,7 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B @@ -133,7 +133,7 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... @@ -153,6 +153,24 @@ if exist %WRAPPER_JAR% ( ) @REM End of extension +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* From c978be753e1be16d202fc0996322d115104bdde1 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Tue, 2 Jan 2024 01:38:53 +0530 Subject: [PATCH 05/75] Medication Administration Feature (#7) * [Ritesh] | 1. Repo set up. 2. Created Slot and Schedule entity 3.Saving IPD Medication Schedule without creating slots. * [Ritesh] | 1. Update package name 2. Added Dao and Service layer for reference 3. Minor fixes * [Ritesh] | 1.Rename Schedule Strategy to MedicationFrequency * [Ritesh] | 1. Migration for slot. 2. Slot creation from schedule * [Ritesh] | 1. Refactor SlotTimeCreationService * [Ritesh] | 1. Handle time zone issue while creating slots and schedule. * [Ritesh] | 1. Changing the url of saving medication * [Ritesh] | 1. Returning slots * [Ritesh] | Get schedule for Drug chart * [Ritesh] | Fix date time issue in slots response * [Ritesh] | Refactoring and Added test * [Ritesh] | 1. Change for reference id to subject reference id and by reference id to actor reference id. 2. Also added pre-condition before adding medication concept for ipd. * [Ritesh] | 1. Refactoring ServiceType * [Ritesh] | 1. Bug Fix return empty list if now slots are not present for a patient on specific day. * [Ritesh] | 1. Updated README file * [Ritesh] | 1. Fixed time zone issue in test * add. endpoint to get list of IPD medications scheduled for a patient * refactor. endpoint and updated tests in DAO and service classes * refactor. namings for schedule DAO methods * fix. test failures in ScheduleImpl * add. changes to create one schedule for a patient * update. columns in Schedule and Slot table * update. set end date as null * fix tests for Slot and Schedule Hiberate and DAOs. Updated responses for GET calls * fix tests Schedule DAO * remove unnecessary fields * API Change to accomodate Editable Remaining day slot start time for medication * Kavitha|Kalai Add Change for Medication Administration Save * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha, Kalai | refactored patient reference param * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha, Kalai | add medication administration reference in slot db and api * Kavitha|Kalai - Medication Administration Create API Changes * Kavitha, Kalai | added provider mapper and time converter * Kavitha | add adhoc and refactored scheduled medication administration * refactored schedule from medication administration request * Kavitha | refactored medication administration request and response * Kavitha | refactored annotation to medicationAdministrationNote * Kavitha | removed unused methods --------- Co-authored-by: Ritesh Ghiya Co-authored-by: Arjun-Go Co-authored-by: Kalaiyarasan Raja --- api/pom.xml | 22 ++++ .../module/ipd/api/dao/ScheduleDAO.java | 5 +- .../openmrs/module/ipd/api/dao/SlotDAO.java | 4 +- .../ipd/api/dao/impl/HibernateSlotDAO.java | 8 +- .../module/ipd/api/model/ServiceType.java | 4 +- .../openmrs/module/ipd/api/model/Slot.java | 7 ++ .../ipd/api/service/ScheduleService.java | 5 +- .../module/ipd/api/service/SlotService.java | 3 + .../api/service/impl/ScheduleServiceImpl.java | 4 - .../ipd/api/service/impl/SlotServiceImpl.java | 7 +- api/src/main/resources/liquibase.xml | 58 ++++++++++ omod/pom.xml | 18 +++ .../MedicationAdministrationNoteRequest.java | 26 +++++ .../MedicationAdministrationNoteResponse.java | 31 ++++++ ...icationAdministrationPerformerRequest.java | 21 ++++ ...cationAdministrationPerformerResponse.java | 28 +++++ .../MedicationAdministrationRequest.java | 39 +++++++ .../MedicationAdministrationResponse.java | 78 +++++++++++++ .../ipd/contract/MedicationSlotResponse.java | 4 + ...IPDMedicationAdministrationController.java | 71 ++++++++++++ .../MedicationAdministrationFactory.java | 81 ++++++++++++++ .../module/ipd/factory/SlotFactory.java | 24 ++-- .../IPDMedicationAdministrationService.java | 12 ++ ...PDMedicationAdministrationServiceImpl.java | 105 ++++++++++++++++++ .../service/impl/IPDScheduleServiceImpl.java | 4 +- omod/src/main/resources/config.xml | 2 +- pom.xml | 24 ++++ 27 files changed, 670 insertions(+), 25 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/IPDMedicationAdministrationService.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java diff --git a/api/pom.xml b/api/pom.xml index b28f5db..7dfdbee 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -104,14 +104,17 @@ org.openmrs.api openmrs-api + provided org.projectlombok lombok + provided org.openmrs.web openmrs-web + provided org.openmrs.module @@ -125,6 +128,25 @@ provided + + org.openmrs.module + fhir2-api + provided + + + + org.openmrs.module + fhir2-omod + provided + + + + org.bahmni.module + medication-administration-api + provided + + + org.openmrs.module webservices.rest-omod-common diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java index 196a23b..7d85035 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/ScheduleDAO.java @@ -4,16 +4,13 @@ import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.api.db.DAOException; import org.springframework.stereotype.Repository; -import org.openmrs.Concept; -import org.openmrs.module.ipd.api.model.Reference; -import java.util.List; @Repository public interface ScheduleDAO { Schedule getSchedule(Integer scheduleId) throws DAOException; - + Schedule saveSchedule(Schedule schedule) throws DAOException; Schedule getScheduleByVisit(Visit visit) throws DAOException; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index df03ade..5896222 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -13,7 +13,9 @@ public interface SlotDAO { Slot getSlot(Integer slotId) throws DAOException; - + + Slot getSlotByUUID(String uuid) throws DAOException; + Slot saveSlot(Slot slot) throws DAOException; List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index d58259b..59ecb5a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -31,7 +31,13 @@ public HibernateSlotDAO(SessionFactory sessionFactory) { public Slot getSlot(Integer slotId) throws DAOException { return sessionFactory.getCurrentSession().get(Slot.class, slotId); } - + + @Override + public Slot getSlotByUUID(String uuid) throws DAOException { + Slot s = (Slot)this.sessionFactory.getCurrentSession().createQuery("from Slot s where s.uuid = :uuid").setString("uuid", uuid).uniqueResult(); + return s; + } + @Override public Slot saveSlot(Slot slot) throws DAOException { sessionFactory.getCurrentSession().saveOrUpdate(slot); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java index 48af776..651daeb 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java @@ -1,7 +1,9 @@ package org.openmrs.module.ipd.api.model; public enum ServiceType { - MEDICATION_REQUEST("MedicationRequest"); + MEDICATION_REQUEST("MedicationRequest"), + EMERGENCY_MEDICATION_REQUEST("EmergencyMedicationRequest"), + AS_NEEDED_MEDICATION_REQUEST("AsNeededMedicationRequest"); private final String conceptName; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index 937de6b..33c6e7b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -79,6 +79,13 @@ public enum SlotStatus { @Column(name = "status", nullable = false) @Enumerated(EnumType.STRING) private SlotStatus status = SlotStatus.SCHEDULED; + + /** + * The reference of medication administration if the medication is administered + */ + @OneToOne + @JoinColumn(name = "medication_administration_id", referencedColumnName = "medication_administration_id") + private MedicationAdministration medicationAdministration; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java index 3df1903..a370215 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/ScheduleService.java @@ -1,21 +1,18 @@ package org.openmrs.module.ipd.api.service; -import org.openmrs.Concept; import org.openmrs.Visit; -import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.api.APIException; import org.openmrs.api.OpenmrsService; import org.springframework.stereotype.Service; -import java.util.List; @Service public interface ScheduleService extends OpenmrsService { // @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) Schedule getSchedule(Integer scheduleId) throws APIException; - + // @Authorized({ PrivilegeConstants.EDIT_IPD_SCHEDULES }) Schedule saveSchedule(Schedule schedule) throws APIException; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index dc3fb56..468f6b1 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -17,6 +17,9 @@ public interface SlotService extends OpenmrsService { // @Authorized({ PrivilegeConstants.EDIT_IPD_SLOTS }) Slot getSlot(Integer slotId) throws APIException; + // @Authorized({ PrivilegeConstants.EDIT_IPD_SLOTS }) + Slot getSlotByUUID(String uuid) throws APIException; + // @Authorized({ PrivilegeConstants.EDIT_IPD_SLOTS }) Slot saveSlot(Slot slot) throws APIException; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java index f331151..7521211 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/ScheduleServiceImpl.java @@ -1,9 +1,7 @@ package org.openmrs.module.ipd.api.service.impl; -import org.openmrs.Concept; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.ScheduleDAO; -import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.api.APIException; @@ -14,8 +12,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - @Service @Transactional public class ScheduleServiceImpl extends BaseOpenmrsService implements ScheduleService { diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 25a33cd..318d39d 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -34,7 +34,12 @@ public SlotServiceImpl(SlotDAO slotDAO) { public Slot getSlot(Integer slotId) throws APIException { return slotDAO.getSlot(slotId); } - + + @Override + public Slot getSlotByUUID(String uuid) throws APIException { + return slotDAO.getSlotByUUID(uuid); + } + @Override public Slot saveSlot(Slot slot) throws APIException { return slotDAO.saveSlot(slot); diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 1740908..8464105 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -218,4 +218,62 @@ ALTER TABLE ipd_schedule MODIFY COLUMN end_date datetime NULL; + + + + + + + + + + + + SELECT COUNT(*) FROM concept where short_name='EmergencyMedicationRequest' and description='EmergencyMedicationRequest'; + + + SELECT COUNT(*) FROM concept_name where name ='EmergencyMedicationRequest'; + + + Add concept for Emergency Medication Request + + insert into concept (retired, short_name, description, datatype_id, class_id, is_set, creator, date_created, + changed_by, date_changed, uuid) + values (0, 'EmergencyMedicationRequest', 'EmergencyMedicationRequest', + (select concept_datatype_id from concept_datatype where name = 'Text'), + (select concept_class_id from concept_class where name = 'Misc'), + 0, 1, now(), 1, now(), uuid()); + insert into concept_name (concept_id, name, locale, locale_preferred, creator, date_created, + concept_name_type, voided, uuid) + values ((select concept_id from concept where short_name='EmergencyMedicationRequest'), + 'EmergencyMedicationRequest', 'en', 1, 1, now(), 'FULLY_SPECIFIED', 0, uuid()); + + + + + + + SELECT COUNT(*) FROM concept where short_name='AsNeededMedicationRequest' and description='AsNeededMedicationRequest'; + + + SELECT COUNT(*) FROM concept_name where name ='AsNeededMedicationRequest'; + + + Add concept for As Needed Medication Request + + insert into concept (retired, short_name, description, datatype_id, class_id, is_set, creator, date_created, + changed_by, date_changed, uuid) + values (0, 'AsNeededMedicationRequest', 'AsNeededMedicationRequest', + (select concept_datatype_id from concept_datatype where name = 'Text'), + (select concept_class_id from concept_class where name = 'Misc'), + 0, 1, now(), 1, now(), uuid()); + insert into concept_name (concept_id, name, locale, locale_preferred, creator, date_created, + concept_name_type, voided, uuid) + values ((select concept_id from concept where short_name='AsNeededMedicationRequest'), + 'AsNeededMedicationRequest', 'en', 1, 1, now(), 'FULLY_SPECIFIED', 0, uuid()); + + + diff --git a/omod/pom.xml b/omod/pom.xml index ff83e3b..234d658 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -111,6 +111,24 @@ provided + + org.openmrs.module + fhir2-api + provided + + + + org.openmrs.module + fhir2-omod + provided + + + + org.bahmni.module + medication-administration-api + provided + + org.openmrs.test openmrs-test diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteRequest.java new file mode 100644 index 0000000..87fdd58 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteRequest.java @@ -0,0 +1,26 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties +public class MedicationAdministrationNoteRequest { + private String uuid; + private String authorUuid; + private Long recordedTime; + private String text; + + public Date getRecordedTimeAsLocaltime() { + return this.recordedTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.recordedTime)): new Date(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteResponse.java new file mode 100644 index 0000000..b8e2f01 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationNoteResponse.java @@ -0,0 +1,31 @@ +package org.openmrs.module.ipd.contract; + +import lombok.*; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.openmrs.module.ipd.api.model.MedicationAdministrationNote; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +import java.util.Date; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties +public class MedicationAdministrationNoteResponse { + private String uuid; + private Object author; + private Date recordedTime; + private String text; + + public static MedicationAdministrationNoteResponse createFrom(MedicationAdministrationNote openmrsObject) { + return MedicationAdministrationNoteResponse.builder() + .uuid(openmrsObject.getUuid()) + .author(ConversionUtil.convertToRepresentation(openmrsObject.getAuthor(), Representation.REF)) + .recordedTime(openmrsObject.getRecordedTime()) + .text(openmrsObject.getText()) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerRequest.java new file mode 100644 index 0000000..c1d5a36 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerRequest.java @@ -0,0 +1,21 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties +public class MedicationAdministrationPerformerRequest { + private String uuid; + private String providerUuid; + private String function; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerResponse.java new file mode 100644 index 0000000..3b1c1cf --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationPerformerResponse.java @@ -0,0 +1,28 @@ +package org.openmrs.module.ipd.contract; + +import lombok.*; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.openmrs.module.ipd.api.model.MedicationAdministrationPerformer; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonIgnoreProperties +public class MedicationAdministrationPerformerResponse { + private String uuid; + private Object provider; + private String function; + + public static MedicationAdministrationPerformerResponse createFrom(MedicationAdministrationPerformer openmrsMedicationAdministrationPerformer) { + String function = openmrsMedicationAdministrationPerformer.getFunction() != null ? openmrsMedicationAdministrationPerformer.getFunction().getDisplayString() : null; + return MedicationAdministrationPerformerResponse.builder() + .uuid(openmrsMedicationAdministrationPerformer.getUuid()) + .provider(ConversionUtil.convertToRepresentation(openmrsMedicationAdministrationPerformer.getActor(), Representation.REF)) + .function(function) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java new file mode 100644 index 0000000..30270d6 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java @@ -0,0 +1,39 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MedicationAdministrationRequest { + + private String uuid; + private String patientUuid; + private String encounterUuid; + private String orderUuid; + private List providers; + private List notes; + private String status; + private String statusReason; + private String drugUuid; + private String dosingInstructions; + private Double dose; + private String doseUnitsUuid; + private String routeUuid; + private String siteUuid; + private Long administeredDateTime; + private String slotUuid; + + public Date getAdministeredDateTimeAsLocaltime() { + return this.administeredDateTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.administeredDateTime)): null; + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationResponse.java new file mode 100644 index 0000000..4857b4e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationResponse.java @@ -0,0 +1,78 @@ +package org.openmrs.module.ipd.contract; + +import lombok.*; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.model.MedicationAdministrationNote; +import org.openmrs.module.ipd.api.model.MedicationAdministrationPerformer; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MedicationAdministrationResponse { + + private String uuid; + private String patientUuid; + private String encounterUuid; + private String orderUuid; + private List providers; + private List notes; + private String status; + private String statusReason; + private Object drug; + private String dosingInstructions; + private Double dose; + private Object doseUnits; + private Object route; + private Object site; + private Date administeredDateTime; + + public static MedicationAdministrationResponse createFrom(org.openmrs.module.ipd.api.model.MedicationAdministration openmrsMedicationAdministration) { + if (openmrsMedicationAdministration == null) { + return null; + } + String status = openmrsMedicationAdministration.getStatus() != null ? openmrsMedicationAdministration.getStatus().getShortNameInLocale(Context.getLocale()).getName() : null; + String statusReason = openmrsMedicationAdministration.getStatusReason() != null ? openmrsMedicationAdministration.getStatusReason().getDisplayString() : null; + String patientUuid = openmrsMedicationAdministration.getPatient() != null ? openmrsMedicationAdministration.getPatient().getUuid() : null; + String encounterUuid = openmrsMedicationAdministration.getEncounter() != null ? openmrsMedicationAdministration.getEncounter().getUuid() : null; + String orderUuid = openmrsMedicationAdministration.getDrugOrder() != null ? openmrsMedicationAdministration.getDrugOrder().getUuid() : null; + + List providers = new java.util.ArrayList<>(); + if (openmrsMedicationAdministration.getPerformers() != null) { + for (MedicationAdministrationPerformer performer : openmrsMedicationAdministration.getPerformers()) { + providers.add(MedicationAdministrationPerformerResponse.createFrom(performer)); + } + } + List notes = new java.util.ArrayList<>(); + if (openmrsMedicationAdministration.getNotes() != null) { + for (MedicationAdministrationNote note : openmrsMedicationAdministration.getNotes()) { + notes.add(MedicationAdministrationNoteResponse.createFrom(note)); + } + } + return MedicationAdministrationResponse.builder() + .uuid(openmrsMedicationAdministration.getUuid()) + .administeredDateTime(openmrsMedicationAdministration.getAdministeredDateTime()) + .status(status) + .statusReason(statusReason) + .patientUuid(patientUuid) + .encounterUuid(encounterUuid) + .orderUuid(orderUuid) + .providers(providers) + .notes(notes) + .drug(ConversionUtil.convertToRepresentation(openmrsMedicationAdministration.getDrug(), Representation.REF)) + .dosingInstructions(openmrsMedicationAdministration.getDosingInstructions()) + .dose(openmrsMedicationAdministration.getDose()) + .doseUnits(ConversionUtil.convertToRepresentation(openmrsMedicationAdministration.getDoseUnits(), Representation.REF)) + .route(ConversionUtil.convertToRepresentation(openmrsMedicationAdministration.getRoute(), Representation.REF)) + .site(ConversionUtil.convertToRepresentation(openmrsMedicationAdministration.getSite(), Representation.REF)) + .build(); + } +} + diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java index 5e756bb..f2b4c97 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java @@ -5,7 +5,9 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hl7.fhir.r4.model.MedicationAdministration; import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.factory.MedicationAdministrationFactory; import org.openmrs.module.webservices.rest.web.ConversionUtil; import org.openmrs.module.webservices.rest.web.representation.Representation; @@ -23,6 +25,7 @@ public class MedicationSlotResponse { private String status; private long startTime; private Object order; + private Object medicationAdministration; public static MedicationSlotResponse createFrom(Slot slot) { return MedicationSlotResponse.builder() @@ -32,6 +35,7 @@ public static MedicationSlotResponse createFrom(Slot slot) { .status(slot.getStatus().name()) .startTime(convertLocalDateTimeToUTCEpoc(slot.getStartDateTime())) .order(ConversionUtil.convertToRepresentation(slot.getOrder(), Representation.FULL)) + .medicationAdministration(MedicationAdministrationResponse.createFrom((slot.getMedicationAdministration()))) .build(); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java new file mode 100644 index 0000000..19843e6 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java @@ -0,0 +1,71 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.hl7.fhir.r4.model.MedicationAdministration; +import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; +import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; +import org.openmrs.module.ipd.factory.MedicationAdministrationFactory; +import org.openmrs.module.ipd.service.IPDMedicationAdministrationService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd") +@Slf4j +public class IPDMedicationAdministrationController extends BaseRestController { + + private final IPDMedicationAdministrationService ipdMedicationAdministrationService; + private final MedicationAdministrationFactory medicationAdministrationFactory; + + @Autowired + public IPDMedicationAdministrationController(IPDMedicationAdministrationService ipdMedicationAdministrationService, + SlotService slotService, + FhirMedicationAdministrationDao medicationAdministrationDao, + MedicationAdministrationFactory medicationAdministrationFactory) { + this.ipdMedicationAdministrationService = ipdMedicationAdministrationService; + this.medicationAdministrationFactory = medicationAdministrationFactory; + } + + @RequestMapping(value = "/scheduledMedicationAdministrations", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity createScheduledMedicationAdministration(@RequestBody List medicationAdministrationRequestList) { + try { + List medicationAdministrationResponseList = new ArrayList<>(); + for (MedicationAdministrationRequest medicationAdministrationRequest : medicationAdministrationRequestList) { + MedicationAdministration medicationAdministration = ipdMedicationAdministrationService.saveScheduledMedicationAdministration(medicationAdministrationRequest); + medicationAdministrationResponseList.add(medicationAdministrationFactory.mapMedicationAdministrationToResponse(medicationAdministration)); + } + return new ResponseEntity<>(medicationAdministrationResponseList, OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new medicationAdministration", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + + @RequestMapping(value = "/adhocMedicationAdministrations", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity createAdhocMedicationAdministration(@RequestBody MedicationAdministrationRequest medicationAdministrationRequest) { + try { + MedicationAdministration medicationAdministration = ipdMedicationAdministrationService.saveAdhocMedicationAdministration(medicationAdministrationRequest); + MedicationAdministrationResponse medicationAdministrationResponse = medicationAdministrationFactory.mapMedicationAdministrationToResponse(medicationAdministration); + return new ResponseEntity<>(medicationAdministrationResponse, OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new medicationAdministration", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java new file mode 100644 index 0000000..149581c --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java @@ -0,0 +1,81 @@ +package org.openmrs.module.ipd.factory; + +import org.openmrs.DrugOrder; +import org.openmrs.api.context.Context; +import org.openmrs.module.fhir2.apiext.translators.MedicationAdministrationStatusTranslator; +import org.openmrs.module.fhir2.apiext.translators.MedicationAdministrationTranslator; +import org.openmrs.module.ipd.api.model.MedicationAdministration; +import org.openmrs.module.ipd.api.model.MedicationAdministrationNote; +import org.openmrs.module.ipd.api.model.MedicationAdministrationPerformer; +import org.openmrs.module.ipd.contract.MedicationAdministrationNoteRequest; +import org.openmrs.module.ipd.contract.MedicationAdministrationPerformerRequest; +import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; +import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + + +@Component +public class MedicationAdministrationFactory { + + private MedicationAdministrationTranslator medicationAdministrationTranslator; + private MedicationAdministrationStatusTranslator medicationAdministrationStatusTranslator; + + @Autowired + public MedicationAdministrationFactory(MedicationAdministrationTranslator medicationAdministrationTranslator, + MedicationAdministrationStatusTranslator medicationAdministrationStatusTranslator) { + this.medicationAdministrationTranslator = medicationAdministrationTranslator; + this.medicationAdministrationStatusTranslator = medicationAdministrationStatusTranslator; + } + + public MedicationAdministration mapRequestToMedicationAdministration(MedicationAdministrationRequest request, MedicationAdministration medicationAdministration) { + + medicationAdministration.setAdministeredDateTime(request.getAdministeredDateTimeAsLocaltime()); + medicationAdministration.setStatus(medicationAdministrationStatusTranslator.toOpenmrsType(org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationStatus.fromCode(request.getStatus()))); + medicationAdministration.setPatient(Context.getPatientService().getPatientByUuid(request.getPatientUuid())); + medicationAdministration.setEncounter(Context.getEncounterService().getEncounterByUuid(request.getEncounterUuid())); + medicationAdministration.setDrugOrder((DrugOrder) Context.getOrderService().getOrderByUuid(request.getOrderUuid())); + + List providers = new ArrayList<>(); + if (request.getProviders() != null) { + for (MedicationAdministrationPerformerRequest performer : request.getProviders()) { + MedicationAdministrationPerformer newProvider = new MedicationAdministrationPerformer(); + newProvider.setActor(Context.getProviderService().getProviderByUuid(performer.getProviderUuid())); + newProvider.setFunction(Context.getConceptService().getConceptByName(performer.getFunction())); + providers.add(newProvider); + } + } + medicationAdministration.setPerformers(new HashSet<>(providers)); + List notes = new ArrayList<>(); + if (request.getNotes() != null) { + for (MedicationAdministrationNoteRequest note : request.getNotes()) { + MedicationAdministrationNote newNote = new MedicationAdministrationNote(); + newNote.setAuthor(Context.getProviderService().getProviderByUuid(note.getAuthorUuid())); + newNote.setText(note.getText()); + newNote.setRecordedTime(note.getRecordedTimeAsLocaltime()); + notes.add(newNote); + } + } + medicationAdministration.setNotes(new HashSet<>(notes)); + medicationAdministration.setDrug(Context.getConceptService().getDrugByUuid(request.getDrugUuid())); + medicationAdministration.setDosingInstructions(request.getDosingInstructions()); + medicationAdministration.setDose(request.getDose()); + medicationAdministration.setDoseUnits(Context.getConceptService().getConceptByUuid(request.getDoseUnitsUuid())); + medicationAdministration.setRoute(Context.getConceptService().getConceptByUuid(request.getRouteUuid())); + medicationAdministration.setSite(Context.getConceptService().getConceptByUuid(request.getSiteUuid())); + + return medicationAdministration; + } + + public MedicationAdministrationResponse mapMedicationAdministrationToResponse(org.hl7.fhir.r4.model.MedicationAdministration fhirMedicationAdministration) { + MedicationAdministration openmrsMedicationAdministration = (MedicationAdministration) medicationAdministrationTranslator.toOpenmrsType(fhirMedicationAdministration); + MedicationAdministrationResponse response = MedicationAdministrationResponse.createFrom(openmrsMedicationAdministration); + return response; + } + + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java index 9373754..17c09e8 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java @@ -7,8 +7,11 @@ import org.openmrs.api.PatientService; import org.openmrs.module.bedmanagement.BedDetails; import org.openmrs.module.bedmanagement.service.BedManagementService; +import org.openmrs.module.ipd.api.model.MedicationAdministration; import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.service.SlotService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -16,24 +19,25 @@ import java.util.List; import java.util.stream.Collectors; -import static org.openmrs.module.ipd.api.model.ServiceType.MEDICATION_REQUEST; -import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; - @Component public class SlotFactory { private final BedManagementService bedManagementService; private final ConceptService conceptService; private final PatientService patientService; + private final SlotService slotService; @Autowired - public SlotFactory(BedManagementService bedManagementService, ConceptService conceptService, PatientService patientService) { + public SlotFactory(BedManagementService bedManagementService, ConceptService conceptService, PatientService patientService,SlotService slotService) { this.bedManagementService = bedManagementService; this.conceptService = conceptService; this.patientService = patientService; + this.slotService = slotService; } - public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime, Order drugOrder) { + public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime, + Order drugOrder, MedicationAdministration medicationAdministration, + Slot.SlotStatus status, ServiceType serviceType) { return slotsStartTime.stream().map(slotStartTime -> { Slot slot = new Slot(); @@ -45,14 +49,20 @@ public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime = new ArrayList<>(); + slotsStartTime.add(DateTimeUtil.convertEpocUTCToLocalTimeZone(medicationAdministrationRequest.getAdministeredDateTime())); + ServiceType serviceType = openmrsMedicationAdministration.getDrugOrder() == null ? ServiceType.EMERGENCY_MEDICATION_REQUEST : ServiceType.AS_NEEDED_MEDICATION_REQUEST; + slotFactory.createSlotsForMedicationFrom(schedule, slotsStartTime, openmrsMedicationAdministration.getDrugOrder(), + openmrsMedicationAdministration, Slot.SlotStatus.COMPLETED, serviceType) + .forEach(slotService::saveSlot); + return medicationAdministration; + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index e7ddbf3..707d46a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Optional; +import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; + @Service @Transactional public class IPDScheduleServiceImpl implements IPDScheduleService { @@ -69,7 +71,7 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); - slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order) + slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST) .forEach(slotService::saveSlot); return savedSchedule; diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml index 067eda0..7c18b69 100644 --- a/omod/src/main/resources/config.xml +++ b/omod/src/main/resources/config.xml @@ -13,8 +13,8 @@ org.openmrs.module.webservices.rest org.bahmni.module.bahmnicore org.openmrs.module.bedmanagement + org.bahmni.module.medication-administration - org.openmrs.module.ipd.api.IPDActivator diff --git a/pom.xml b/pom.xml index d5873b0..703f471 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ -Xmx1024m 0.7.9 1.18.26 + 1.11.0 @@ -163,6 +164,29 @@ provided + + + org.openmrs.module + fhir2-api + ${openmrsFhir2Version} + provided + + + + org.openmrs.module + fhir2-omod + ${openmrsFhir2Version} + provided + + + + org.bahmni.module + medication-administration-api + 1.0.0-SNAPSHOT + provided + + + org.openmrs.module From 9a9571d243dfa66d7ec2a9fc693e291ea244391b Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:39:50 +0530 Subject: [PATCH 06/75] IPD Treatment Display Control Get API Changes & Edit Drug Chart API Changes (#8) * IPD Drug Order Fetch API changes * IPD Drug Order schedule update API changes * IPD Drug Order schedule update API changes * IPD Drug Order schedule update API changes * IPD Drug Order schedule update API changes * Fix to convert time to UTC intead of Local Time * Kavitha | refactored treatments API to include emergency medications * Kavitha,Kalai | add provider as part of drug order response --------- Co-authored-by: Kavitha S --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 7 +- .../ipd/api/dao/impl/HibernateSlotDAO.java | 20 ++- .../module/ipd/api/service/SlotService.java | 6 +- .../ipd/api/service/impl/SlotServiceImpl.java | 18 ++ omod/pom.xml | 12 ++ .../contract/DrugOrderScheduleResponse.java | 29 ++++ .../ipd/contract/IPDDrugOrderResponse.java | 40 +++++ .../ipd/contract/IPDTreatmentsResponse.java | 28 ++++ .../ipd/contract/MedicationSlotResponse.java | 16 ++ .../ipd/controller/IPDScheduleController.java | 12 ++ .../ipd/controller/IPDVisitController.java | 48 ++++++ .../MedicationAdministrationFactory.java | 5 +- .../module/ipd/model/DrugOrderSchedule.java | 21 +++ .../module/ipd/model/IPDDrugOrder.java | 23 +++ .../ipd/service/IPDScheduleService.java | 1 + .../module/ipd/service/IPDVisitService.java | 14 ++ .../service/impl/IPDScheduleServiceImpl.java | 19 ++- .../ipd/service/impl/IPDVisitServiceImpl.java | 157 ++++++++++++++++++ .../service/impl/SlotTimeCreationService.java | 56 ++++++- pom.xml | 18 ++ 20 files changed, 531 insertions(+), 19 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDDrugOrderResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDTreatmentsResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/DrugOrderSchedule.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/IPDDrugOrder.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/IPDVisitService.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 5896222..939b1f8 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.dao; import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.api.db.DAOException; @@ -11,16 +12,18 @@ @Repository public interface SlotDAO { - + Slot getSlot(Integer slotId) throws DAOException; Slot getSlotByUUID(String uuid) throws DAOException; Slot saveSlot(Slot slot) throws DAOException; - List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); + List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType); List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType); List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids); + + List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 59ecb5a..a494c1a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -2,6 +2,7 @@ import org.hibernate.query.Query; import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -47,7 +48,7 @@ public Slot saveSlot(Slot slot) throws DAOException { @Override public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference subject, LocalDate forDate, Concept serviceType) { Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and YEAR(slot.startDateTime)=:forYear and MONTH(slot.startDateTime)=:forMonth and DAY(slot.startDateTime)=:forDay and slot.serviceType=:serviceType"); + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and YEAR(slot.startDateTime)=:forYear and MONTH(slot.startDateTime)=:forMonth and DAY(slot.startDateTime)=:forDay and slot.serviceType=:serviceType and slot.voided=0"); query.setParameter("subject", subject); query.setParameter("forYear", forDate.getYear()); @@ -61,7 +62,7 @@ public List getSlotsBySubjectReferenceIdAndForDateAndServiceType(Reference @Override public List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType) { Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and slot.serviceType=:serviceType"); + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and slot.serviceType=:serviceType and slot.voided=0"); query.setParameter("subject", subject); query.setParameter("serviceType", serviceType); @@ -75,7 +76,8 @@ public List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Refere .createQuery("FROM Slot slot " + "WHERE slot.schedule.subject=:subject and " + "slot.serviceType=:serviceType and" - + " slot.order.uuid IN :orderUuids"); + + " slot.order.uuid IN :orderUuids and " + + "slot.voided = 0"); query.setParameter("subject", subject); query.setParameter("serviceType", serviceType); @@ -83,4 +85,16 @@ public List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Refere return query.getResultList(); } + + @Override + public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType) { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and slot.schedule.visit=:visit and slot.serviceType=:serviceType"); + + query.setParameter("subject", subject); + query.setParameter("visit", visit); + query.setParameter("serviceType", serviceType); + + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 468f6b1..46725a5 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -1,8 +1,8 @@ package org.openmrs.module.ipd.api.service; import org.openmrs.Concept; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; -import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.api.APIException; import org.openmrs.api.OpenmrsService; @@ -28,4 +28,8 @@ public interface SlotService extends OpenmrsService { List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, Concept serviceType); List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids); + + void voidSlot(Slot slot,String voidReason); + + List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 318d39d..3eb063a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -1,6 +1,8 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Concept; +import org.openmrs.api.context.Context; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -14,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.util.Date; import java.util.List; @Service @@ -60,4 +63,19 @@ public List getSlotsBySubjectReferenceIdAndServiceType(Reference subject, public List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids) { return slotDAO.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(subject, serviceType, orderUuids); } + + @Override + public void voidSlot(Slot slot, String voidReason) throws APIException { + slot.setVoided(true); + slot.setVoidedBy(Context.getAuthenticatedUser()); + slot.setDateVoided(new Date()); + slot.setVoidReason(voidReason); + slotDAO.saveSlot(slot); + } + + + @Override + public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType) { + return slotDAO.getSlotsByPatientAndVisitAndServiceType(subject, visit, serviceType); + } } diff --git a/omod/pom.xml b/omod/pom.xml index 234d658..c1c3e96 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -123,6 +123,18 @@ provided + + org.openmrs.module + emrapi-api + provided + + + + org.bahmni.module + bahmnicore-api + provided + + org.bahmni.module medication-administration-api diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java new file mode 100644 index 0000000..c7ee133 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -0,0 +1,29 @@ +package org.openmrs.module.ipd.contract; + +import lombok.*; +import org.openmrs.module.ipd.model.DrugOrderSchedule; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DrugOrderScheduleResponse { + + private List firstDaySlotsStartTime; + private List dayWiseSlotsStartTime; + private List remainingDaySlotsStartTime; + private Long slotStartTime; + private Boolean medicationAdministrationStarted; + + public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSchedule){ + return DrugOrderScheduleResponse.builder(). + firstDaySlotsStartTime(drugOrderSchedule.getFirstDaySlotsStartTime()). + dayWiseSlotsStartTime(drugOrderSchedule.getDayWiseSlotsStartTime()). + remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). + slotStartTime(drugOrderSchedule.getSlotStartTime()). + medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDDrugOrderResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDDrugOrderResponse.java new file mode 100644 index 0000000..5ccb047 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDDrugOrderResponse.java @@ -0,0 +1,40 @@ +package org.openmrs.module.ipd.contract; + +import lombok.*; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; +import org.openmrs.module.ipd.model.IPDDrugOrder; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IPDDrugOrderResponse { + + private EncounterTransaction.DrugOrder drugOrder; + private EncounterTransaction.Provider provider; + private DrugOrderScheduleResponse drugOrderSchedule; + + public static IPDDrugOrderResponse createFrom(IPDDrugOrder ipdDrugOrder) { + IPDDrugOrderResponse ipdDrugOrderResponse= IPDDrugOrderResponse.builder(). + drugOrder(ipdDrugOrder.getBahmniDrugOrder().getDrugOrder()) + .provider(ipdDrugOrder.getBahmniDrugOrder().getProvider()) + .build(); + if (ipdDrugOrder.getDrugOrderSchedule() != null){ + ipdDrugOrderResponse.setDrugOrderSchedule(DrugOrderScheduleResponse.createFrom(ipdDrugOrder.getDrugOrderSchedule())); + } + return ipdDrugOrderResponse; + } + + public boolean equals(Object otherOrder) { + if (otherOrder == null) { + return false; + } else if (!(otherOrder instanceof IPDDrugOrderResponse)) { + return false; + } else { + return super.equals(otherOrder); + } + } + + +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDTreatmentsResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDTreatmentsResponse.java new file mode 100644 index 0000000..1b9e195 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDTreatmentsResponse.java @@ -0,0 +1,28 @@ +package org.openmrs.module.ipd.contract; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IPDTreatmentsResponse { + + private List ipdDrugOrders; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private List emergencyMedications; + + public static IPDTreatmentsResponse createFrom(List ipdDrugOrders, List emergencyMedications) { + return IPDTreatmentsResponse.builder() + .ipdDrugOrders(ipdDrugOrders) + .emergencyMedications(emergencyMedications) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java index f2b4c97..b78254e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java @@ -38,4 +38,20 @@ public static MedicationSlotResponse createFrom(Slot slot) { .medicationAdministration(MedicationAdministrationResponse.createFrom((slot.getMedicationAdministration()))) .build(); } + + public static MedicationSlotResponse createFrom(Slot slot, Representation rep) { + if (rep.equals(Representation.REF)) + { + return MedicationSlotResponse.builder() + .id(slot.getId()) + .uuid(slot.getUuid()) + .serviceType(slot.getServiceType().getName().getName()) + .status(slot.getStatus().name()) + .startTime(convertLocalDateTimeToUTCEpoc(slot.getStartDateTime())) + .medicationAdministration(MedicationAdministrationResponse.createFrom((slot.getMedicationAdministration()))) + .build(); + } + return MedicationSlotResponse.createFrom(slot); + + } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index f6bb85a..8fa66f1 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -51,6 +51,18 @@ public ResponseEntity createMedicationSchedule(@RequestBody ScheduleMedi } } + @RequestMapping(value = "type/medication/edit", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedicationRequest scheduleMedicationRequest) { + try { + Schedule schedule = ipdScheduleService.updateMedicationSchedule(scheduleMedicationRequest); + return new ResponseEntity<>(ScheduleMedicationResponse.constructFrom(schedule), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "forDate"}) @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java new file mode 100644 index 0000000..d6857e6 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java @@ -0,0 +1,48 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.api.model.ServiceType; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.contract.IPDDrugOrderResponse; +import org.openmrs.module.ipd.contract.IPDTreatmentsResponse; +import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; +import org.openmrs.module.ipd.model.IPDDrugOrder; +import org.openmrs.module.ipd.service.IPDVisitService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipdVisit/{visitUuid}") +@Slf4j +public class IPDVisitController extends BaseRestController { + + private IPDVisitService ipdVisitService; + + @Autowired + public IPDVisitController(IPDVisitService ipdVisitService) { + this.ipdVisitService = ipdVisitService; + } + + @RequestMapping(value = "/medication", method = RequestMethod.GET) + @ResponseBody + public IPDTreatmentsResponse getVisitWiseMedications ( + @PathVariable("visitUuid") String visitUuid, + @RequestParam(value = "includes", required = false) List includes) throws ParseException { + + List prescribedOrders = ipdVisitService.getPrescribedOrders(visitUuid, true, null, null, null, false); + List prescribedOrderResponse = prescribedOrders.stream().map(IPDDrugOrderResponse::createFrom).collect(Collectors.toList()); + List emergencyMedications = null; + if (includes != null && includes.contains("emergencyMedications")) { + List emergencyMedicationSlots = ipdVisitService.getMedicationSlots(visitUuid, ServiceType.EMERGENCY_MEDICATION_REQUEST); + emergencyMedications = emergencyMedicationSlots.stream().map(slot -> MedicationAdministrationResponse.createFrom(slot.getMedicationAdministration())).collect(Collectors.toList()); + } + return IPDTreatmentsResponse.createFrom(prescribedOrderResponse, emergencyMedications); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java index 149581c..89b5923 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java @@ -7,10 +7,7 @@ import org.openmrs.module.ipd.api.model.MedicationAdministration; import org.openmrs.module.ipd.api.model.MedicationAdministrationNote; import org.openmrs.module.ipd.api.model.MedicationAdministrationPerformer; -import org.openmrs.module.ipd.contract.MedicationAdministrationNoteRequest; -import org.openmrs.module.ipd.contract.MedicationAdministrationPerformerRequest; -import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; -import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; +import org.openmrs.module.ipd.contract.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/DrugOrderSchedule.java b/omod/src/main/java/org/openmrs/module/ipd/model/DrugOrderSchedule.java new file mode 100644 index 0000000..de94347 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/DrugOrderSchedule.java @@ -0,0 +1,21 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DrugOrderSchedule { + + private List firstDaySlotsStartTime; + private List dayWiseSlotsStartTime; + private List remainingDaySlotsStartTime; + private Long slotStartTime; + private List slots; + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/IPDDrugOrder.java b/omod/src/main/java/org/openmrs/module/ipd/model/IPDDrugOrder.java new file mode 100644 index 0000000..d4c809d --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/IPDDrugOrder.java @@ -0,0 +1,23 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.Provider; +import org.openmrs.module.bahmniemrapi.drugorder.contract.BahmniDrugOrder; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction.DrugOrder; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IPDDrugOrder { + + private BahmniDrugOrder bahmniDrugOrder; + private DrugOrderSchedule drugOrderSchedule; + + public static IPDDrugOrder createFrom(BahmniDrugOrder bahmniDrugOrder,DrugOrderSchedule drugOrderSchedule){ + return IPDDrugOrder.builder(). + bahmniDrugOrder(bahmniDrugOrder). + drugOrderSchedule(drugOrderSchedule). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 50f3ca8..98c27d0 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -13,4 +13,5 @@ public interface IPDScheduleService { List getMedicationSlots(String patientUuid, ServiceType serviceType, LocalDate forDate); List getMedicationSlots(String patientUuid, ServiceType serviceType); List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); + Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDVisitService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDVisitService.java new file mode 100644 index 0000000..c000f32 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDVisitService.java @@ -0,0 +1,14 @@ +package org.openmrs.module.ipd.service; + +import org.openmrs.module.ipd.model.IPDDrugOrder; +import org.openmrs.module.ipd.api.model.ServiceType; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.Date; +import java.util.List; + +public interface IPDVisitService { + + List getPrescribedOrders(String visitUuid, Boolean includeActiveVisit, Integer numberOfVisits, Date startDate, Date endDate, Boolean getEffectiveOrdersOnly); + List getMedicationSlots(String visitUuid, ServiceType serviceType); +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 707d46a..64cbc5c 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -25,9 +25,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; @@ -101,6 +100,18 @@ public List getMedicationSlots(String patientUuid, ServiceType serviceType Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); - return slotService.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(subjectReference.get(), concept, orderUuids); + return slotService.getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(subjectReference.get(), concept, orderUuids); } + + @Override + public Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest) { + voidExistingMedicationSlotsForOrder(scheduleMedicationRequest.getPatientUuid(),scheduleMedicationRequest.getOrderUuid(),""); + return saveMedicationSchedule(scheduleMedicationRequest); + } + + private void voidExistingMedicationSlotsForOrder(String patientUuid,String orderUuid,String voidReason){ + List existingSlots = getMedicationSlots(patientUuid,ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{orderUuid}))); + existingSlots.stream().forEach(slot -> slotService.voidSlot(slot,voidReason)); + } + } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java new file mode 100644 index 0000000..def90cb --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java @@ -0,0 +1,157 @@ +package org.openmrs.module.ipd.service.impl; + +import org.bahmni.module.bahmnicore.service.BahmniDrugOrderService; +import org.bahmni.module.bahmnicore.service.BahmniObsService; +import org.openmrs.Concept; +import org.openmrs.DrugOrder; +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.api.ConceptService; +import org.openmrs.api.VisitService; +import org.openmrs.module.bahmniemrapi.drugorder.contract.BahmniDrugOrder; +import org.openmrs.module.bahmniemrapi.drugorder.contract.BahmniOrderAttribute; +import org.openmrs.module.bahmniemrapi.drugorder.mapper.BahmniDrugOrderMapper; +import org.openmrs.module.bahmniemrapi.encountertransaction.contract.BahmniObservation; +import org.openmrs.module.ipd.model.DrugOrderSchedule; +import org.openmrs.module.ipd.model.IPDDrugOrder; +import org.openmrs.module.ipd.api.model.ServiceType; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.model.*; +import org.openmrs.module.ipd.api.service.ReferenceService; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.service.IPDVisitService; +import org.openmrs.module.ipd.service.IPDScheduleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Transactional +public class IPDVisitServiceImpl implements IPDVisitService { + + private BahmniDrugOrderService drugOrderService; + private IPDScheduleService ipdScheduleService; + private SlotTimeCreationService slotTimeCreationService; + private BahmniObsService bahmniObsService; + private ConceptService conceptService; + private BahmniDrugOrderMapper bahmniDrugOrderMapper; + private ReferenceService referenceService; + private VisitService visitService; + private SlotService slotService; + + @Autowired + public IPDVisitServiceImpl(BahmniDrugOrderService drugOrderService, + IPDScheduleService ipdScheduleService, + SlotTimeCreationService slotTimeCreationService, + BahmniObsService bahmniObsService, + ConceptService conceptService, + ReferenceService referenceService, + VisitService visitService, + SlotService slotService) { + this.drugOrderService = drugOrderService; + this.ipdScheduleService = ipdScheduleService; + this.slotTimeCreationService = slotTimeCreationService; + this.bahmniObsService = bahmniObsService; + this.conceptService = conceptService; + this.bahmniDrugOrderMapper = new BahmniDrugOrderMapper(); + this.referenceService = referenceService; + this.visitService = visitService; + this.slotService = slotService; + } + + + + @Override + public List getPrescribedOrders(String visitUuid, Boolean includeActiveVisit, Integer numberOfVisits, Date startDate, Date endDate, Boolean getEffectiveOrdersOnly) { + List visitUuidsList = new ArrayList<>(); + visitUuidsList.add(visitUuid); + Visit visit = visitService.getVisitByUuid(visitUuid); + List prescribedDrugOrders = drugOrderService.getPrescribedDrugOrders(visitUuidsList, visit.getPatient().getUuid(), includeActiveVisit, numberOfVisits, startDate, endDate, getEffectiveOrdersOnly); + return getIPDDrugOrders(visit.getPatient().getUuid(), prescribedDrugOrders); + } + + private List getIPDDrugOrders(String patientUuid, List drugOrders) { + Map drugOrderMap = drugOrderService.getDiscontinuedDrugOrders(drugOrders); + try { + Collection orderAttributeObs = bahmniObsService.observationsFor(patientUuid, getOrdAttributeConcepts(), null, null, false, null, null, null); + List bahmniDrugOrders = bahmniDrugOrderMapper.mapToResponse(drugOrders, orderAttributeObs, drugOrderMap , null); + bahmniDrugOrders=sortDrugOrdersAccordingToTheirSortWeight(bahmniDrugOrders); + Map drugOrderScheduleByOrders = getDrugOrderScheduleForOrders(patientUuid, bahmniDrugOrders); + + return bahmniDrugOrders.stream().map(bahmniDrugOrder -> IPDDrugOrder.createFrom(bahmniDrugOrder,drugOrderScheduleByOrders.get(bahmniDrugOrder.getUuid()))).collect(Collectors.toList()); + + } catch (IOException e) { + throw new RuntimeException("Could not parse drug order", e); + } + } + + private Map getDrugOrderScheduleForOrders(String patientUuid, List bahmniDrugOrders) { + List orderUuids = bahmniDrugOrders.stream() + .map(BahmniDrugOrder::getUuid) + .collect(Collectors.toList()); + List slots = ipdScheduleService.getMedicationSlots(patientUuid, ServiceType.MEDICATION_REQUEST,orderUuids); + Map> groupedByOrders = slots.stream() + .collect(Collectors.groupingBy(slot -> (DrugOrder) slot.getOrder())); + Map drugOrderScheduleByOrders = slotTimeCreationService.getDrugOrderScheduledTime(groupedByOrders); + return drugOrderScheduleByOrders; + } + + private List sortDrugOrdersAccordingToTheirSortWeight(List bahmniDrugOrders) { + Map> bahmniDrugOrderMap = groupDrugOrdersAccordingToOrderSet(bahmniDrugOrders); + List sortDrugOrders = new ArrayList<>(); + for (String key : bahmniDrugOrderMap.keySet()) { + if(key == null) { + continue; + } + List bahmniDrugOrder = bahmniDrugOrderMap.get(key); + Collections.sort(bahmniDrugOrder, new Comparator() { + @Override + public int compare(BahmniDrugOrder o1, BahmniDrugOrder o2) { + return o1.getSortWeight().compareTo(o2.getSortWeight()); + } + }); + } + + for (String s : bahmniDrugOrderMap.keySet()) { + sortDrugOrders.addAll(bahmniDrugOrderMap.get(s)); + } + return sortDrugOrders; + } + + private Map> groupDrugOrdersAccordingToOrderSet(List bahmniDrugOrders) { + Map> groupedDrugOrders = new LinkedHashMap<>(); + + for (BahmniDrugOrder bahmniDrugOrder: bahmniDrugOrders) { + String orderSetUuid = null == bahmniDrugOrder.getOrderGroup() ? null : bahmniDrugOrder.getOrderGroup().getOrderSet().getUuid(); + + if(!groupedDrugOrders.containsKey(orderSetUuid)){ + groupedDrugOrders.put(orderSetUuid, new ArrayList()); + } + + groupedDrugOrders.get(orderSetUuid).add(bahmniDrugOrder); + } + + return groupedDrugOrders; + } + + private Collection getOrdAttributeConcepts() { + Concept orderAttribute = conceptService.getConceptByName(BahmniOrderAttribute.ORDER_ATTRIBUTES_CONCEPT_SET_NAME); + return orderAttribute == null ? Collections.EMPTY_LIST : orderAttribute.getSetMembers(); + } + + @Override + public List getMedicationSlots(String visitUuid, ServiceType serviceType) { + Visit visit = visitService.getVisitByUuid(visitUuid); + Concept concept = conceptService.getConceptByName(serviceType.conceptName()); + Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), visit.getPatient().getUuid()); + + if(!subjectReference.isPresent()) + return Collections.emptyList(); + + return slotService.getSlotsByPatientAndVisitAndServiceType(subjectReference.get(), visit, concept); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index e1f4fc4..ef8efc9 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -1,22 +1,29 @@ package org.openmrs.module.ipd.service.impl; import org.openmrs.DrugOrder; -import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.api.impl.BaseOpenmrsService; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.openmrs.module.ipd.model.DrugOrderSchedule; +import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import static org.openmrs.module.ipd.contract.ScheduleMedicationRequest.MedicationFrequency.FIXED_SCHEDULE_FREQUENCY; import static org.openmrs.module.ipd.contract.ScheduleMedicationRequest.MedicationFrequency.START_TIME_DURATION_FREQUENCY; +@Service @Component -public class SlotTimeCreationService { +public class SlotTimeCreationService extends BaseOpenmrsService { + + public static final List START_TIME_FREQUENCIES= Arrays.asList(new String[]{"Every Hour", "Every 2 hours", "Every 3 hours", "Every 4 hours", "Every 6 hours", "Every 8 hours", "Every 12 hours", "Once a day", "Nocte (At Night)", "Every 30 minutes", "STAT (Immediately)"}); + public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, DrugOrder order) { if (request.getSlotStartTimeAsLocaltime() != null && request.getMedicationFrequency() == START_TIME_DURATION_FREQUENCY) { return getSlotsStartTimeWithStartTimeDurationFrequency(request, order); @@ -29,6 +36,7 @@ public List createSlotsStartTimeFrom(ScheduleMedicationRequest re private List getSlotsStartTimeWithFixedScheduleFrequency(ScheduleMedicationRequest request, DrugOrder order) { int numberOfSlotsStartTimeToBeCreated = (int) (Math.ceil(order.getQuantity() / order.getDose())); + List slotsStartTime = new ArrayList<>(); if (!CollectionUtils.isEmpty(request.getFirstDaySlotsStartTimeAsLocalTime())) { @@ -90,4 +98,42 @@ private List getSlotsStartTimeWithStartTimeDurationFrequency(Sche } return slotsStartTime; } + + public HashMap getDrugOrderScheduledTime(Map> slotsByOrder){ + HashMap drugOrderScheduleHash= new HashMap<>(); + for (DrugOrder drugOrder : slotsByOrder.keySet()) { + Double frequencyPerDay = drugOrder.getFrequency().getFrequencyPerDay(); + String frequency=drugOrder.getFrequency().getName(); + Map> groupedByDateAndEpoch = slotsByOrder.get(drugOrder).stream() + .collect(Collectors.groupingBy( + obj -> obj.getStartDateTime().toLocalDate(), + Collectors.mapping( + obj -> obj.getStartDateTime(), + Collectors.toList() + ) + )); + + List> sortedList = groupedByDateAndEpoch.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) // Sort by LocalDate in ascending order + .map(Map.Entry::getValue) // Get the list of Longs for each entry + .collect(Collectors.toList()); // Collect the list of lists into a single ArrayList + + DrugOrderSchedule drugOrderSchedule=new DrugOrderSchedule(); + if (START_TIME_FREQUENCIES.contains(frequency)){ + drugOrderSchedule.setSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc(sortedList.get(0).get(0))); + } + else if (sortedList.get(0).size() == frequencyPerDay || (sortedList.size() == 1)) { + drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + } else { + drugOrderSchedule.setFirstDaySlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + drugOrderSchedule.setRemainingDaySlotsStartTime(sortedList.get(sortedList.size() - 1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + if (sortedList.size() > 2) { + drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + } + } + drugOrderSchedule.setSlots(slotsByOrder.get(drugOrder)); + drugOrderScheduleHash.put(drugOrder.getUuid(),drugOrderSchedule); + } + return drugOrderScheduleHash; + } } diff --git a/pom.xml b/pom.xml index 703f471..1a8a3be 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,8 @@ 0.7.9 1.18.26 1.11.0 + 0.94-SNAPSHOT + 1.32.0 @@ -157,6 +159,22 @@ ${openmrsPlatformVersion} provided + + + org.openmrs.module + emrapi-api + ${emrapi-omod.version} + provided + + + + org.bahmni.module + bahmnicore-api + ${bahmniVersion} + provided + jar + + org.openmrs.module bedmanagement-api From fcf6cfede9eb7c108d2333294aa636839e9044a0 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:48:34 +0530 Subject: [PATCH 07/75] A-1206156796138532 | Abi | add. functionality to return slot information based on given time frame --- .../org/openmrs/module/ipd/api/dao/SlotDAO.java | 3 +++ .../ipd/api/dao/impl/HibernateSlotDAO.java | 12 ++++++++++++ .../module/ipd/api/service/SlotService.java | 3 +++ .../ipd/api/service/impl/SlotServiceImpl.java | 5 +++++ .../ipd/controller/IPDScheduleController.java | 16 ++++++++++------ .../module/ipd/service/IPDScheduleService.java | 2 ++ .../ipd/service/impl/IPDScheduleServiceImpl.java | 8 ++++++++ 7 files changed, 43 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 939b1f8..8dda610 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Repository; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Repository @@ -26,4 +27,6 @@ public interface SlotDAO { List getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(Reference subject, Concept serviceType, List orderUuids); List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index a494c1a..bbe7d75 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -14,6 +14,7 @@ import org.springframework.stereotype.Repository; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Repository @@ -97,4 +98,15 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis return query.getResultList(); } + @Override + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate)"); + + query.setParameter("subject", subject); + query.setParameter("startDate", localStartDate); + query.setParameter("endDate", localEndDate); + + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 46725a5..bcf38c1 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; @Service @@ -32,4 +33,6 @@ public interface SlotService extends OpenmrsService { void voidSlot(Slot slot,String voidReason); List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); + + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 3eb063a..ac59abd 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -17,6 +17,7 @@ import java.time.LocalDate; import java.util.Date; +import java.time.LocalDateTime; import java.util.List; @Service @@ -78,4 +79,8 @@ public void voidSlot(Slot slot, String voidReason) throws APIException { public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType) { return slotDAO.getSlotsByPatientAndVisitAndServiceType(subject, visit, serviceType); } + @Override + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate); + } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 8fa66f1..615e143 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -16,7 +16,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; -import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -63,14 +63,18 @@ public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedi } } - @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "forDate"}) + @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "startTime", "endTime"}) @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, - @RequestParam(value = "forDate") long forDate) { + @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime) { try { - LocalDate localDate = convertEpocUTCToLocalTimeZone(forDate).toLocalDate(); - List slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, localDate); - return new ResponseEntity<>(constructResponse(slots), OK); + if (startTime != null && endTime != null) { + LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); + LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); + List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate); + return new ResponseEntity<>(constructResponse(slots), OK); + } + throw new Exception(); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 98c27d0..9893fef 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -6,6 +6,7 @@ import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; public interface IPDScheduleService { @@ -14,4 +15,5 @@ public interface IPDScheduleService { List getMedicationSlots(String patientUuid, ServiceType serviceType); List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); + List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 64cbc5c..6218732 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -114,4 +114,12 @@ private void voidExistingMedicationSlotsForOrder(String patientUuid,String order existingSlots.stream().forEach(slot -> slotService.voidSlot(slot,voidReason)); } + + @Override + public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate) { + Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); + if(!subjectReference.isPresent()) + return Collections.emptyList(); + return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(subjectReference.get(), localStartDate,localEndDate); + } } \ No newline at end of file From ba49841f6337f2fce7bb44b0870b6a9036d2ca48 Mon Sep 17 00:00:00 2001 From: Abinaya U Date: Mon, 8 Jan 2024 12:15:09 +0530 Subject: [PATCH 08/75] Abi | fix. method name based on functionality --- .../java/org/openmrs/module/ipd/api/service/SlotService.java | 2 +- .../openmrs/module/ipd/api/service/impl/SlotServiceImpl.java | 2 +- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index bcf38c1..13a54e8 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -34,5 +34,5 @@ public interface SlotService extends OpenmrsService { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); - List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index ac59abd..d951e57 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -80,7 +80,7 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis return slotDAO.getSlotsByPatientAndVisitAndServiceType(subject, visit, serviceType); } @Override - public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 6218732..767d3e2 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -26,7 +26,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; @@ -120,6 +119,6 @@ public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, Loc Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); - return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrameAndServiceType(subjectReference.get(), localStartDate,localEndDate); + return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate); } } \ No newline at end of file From 5ccfaadc40836d8255b35d9a313238615359de43 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Thu, 11 Jan 2024 12:03:16 +0530 Subject: [PATCH 09/75] Abi | fix. filter non-voided slots for the iven time frame (#10) --- .../org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index bbe7d75..926bcb7 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -101,7 +101,7 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis @Override public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate)"); + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate) and slot.voided=0"); query.setParameter("subject", subject); query.setParameter("startDate", localStartDate); From 28efc13146d868ee97208408ad43705a5f5726aa Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:34:00 +0530 Subject: [PATCH 10/75] Changes to accomodate Drugchart view where we need to intended and actual administered time Changes to accomodate Drugchart view where we need to intended and actual administered time --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 3 + .../ipd/api/dao/impl/HibernateSlotDAO.java | 22 +++++ .../openmrs/module/ipd/api/model/Slot.java | 4 +- .../module/ipd/api/service/SlotService.java | 2 + .../ipd/api/service/impl/SlotServiceImpl.java | 5 ++ ...nAdministrationToSlotStatusTranslator.java | 22 +++++ .../module/ipd/api/util/DateTimeUtil.java | 4 + .../module/ipd/api/util/IPDConstants.java | 7 ++ .../impl/HibernateSlotDAOIntegrationTest.java | 89 +++++++++++++++++++ .../api/service/impl/SlotServiceImplTest.java | 16 ++++ .../MedicationAdministrationRequest.java | 3 +- .../ipd/controller/IPDScheduleController.java | 11 ++- .../ipd/service/IPDScheduleService.java | 2 +- ...PDMedicationAdministrationServiceImpl.java | 22 ++--- .../service/impl/IPDScheduleServiceImpl.java | 5 +- 15 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/translators/MedicationAdministrationToSlotStatusTranslator.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/util/IPDConstants.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 8dda610..2d46d1d 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -29,4 +29,7 @@ public interface SlotDAO { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); + } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 926bcb7..724454d 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -8,6 +8,8 @@ import org.openmrs.module.ipd.api.model.Slot; import org.hibernate.SessionFactory; import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.openmrs.util.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -109,4 +111,24 @@ public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference return query.getResultList(); } + + @Override + public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT slot FROM Slot slot " + + "LEFT JOIN slot.medicationAdministration medAdmin " + + "WHERE (slot.schedule.subject = :subject) AND " + + "(((slot.startDateTime BETWEEN :startDateTime AND :endDateTime) AND " + + "(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate or medAdmin is null)) OR " + + "(medAdmin is not null AND " + + "(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate)))"); + + query.setParameter("subject", subject); + query.setParameter("startDateTime", localStartDate); + query.setParameter("endDateTime", localEndDate); + query.setParameter("startDate", DateTimeUtil.convertLocalDateTimeDate(localStartDate)); + query.setParameter("endDate", DateTimeUtil.convertLocalDateTimeDate(localEndDate)); + + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index 33c6e7b..03b6d80 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -22,9 +22,9 @@ public class Slot extends BaseChangeableOpenmrsData { public enum SlotStatus { SCHEDULED, - MISSED, + NOT_DONE, COMPLETED, - CANCELLED + STOPPED } @EqualsAndHashCode.Include diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 13a54e8..328895f 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -35,4 +35,6 @@ public interface SlotService extends OpenmrsService { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index d951e57..079fd18 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -83,4 +83,9 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate); } + + @Override + public List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/translators/MedicationAdministrationToSlotStatusTranslator.java b/api/src/main/java/org/openmrs/module/ipd/api/translators/MedicationAdministrationToSlotStatusTranslator.java new file mode 100644 index 0000000..f1d0079 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/translators/MedicationAdministrationToSlotStatusTranslator.java @@ -0,0 +1,22 @@ +package org.openmrs.module.ipd.api.translators; + +import org.hl7.fhir.r4.model.MedicationAdministration; +import org.openmrs.module.ipd.api.model.Slot; +import org.springframework.stereotype.Component; + +@Component +public class MedicationAdministrationToSlotStatusTranslator { + + public Slot.SlotStatus toSlotStatus(MedicationAdministration.MedicationAdministrationStatus medicationAdministrationStatus){ + if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.COMPLETED)){ + return Slot.SlotStatus.COMPLETED; + } + if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.NOTDONE)){ + return Slot.SlotStatus.NOT_DONE; + } + if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.STOPPED)){ + return Slot.SlotStatus.STOPPED; + } + return null; + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java index 45c6cc3..34f533a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java @@ -15,4 +15,8 @@ public static long convertLocalDateTimeToUTCEpoc(LocalDateTime localDateTime) { public static LocalDateTime convertDateToLocalDateTime(Date date) { return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); } + + public static Date convertLocalDateTimeDate(LocalDateTime localDateTime) { + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/IPDConstants.java b/api/src/main/java/org/openmrs/module/ipd/api/util/IPDConstants.java new file mode 100644 index 0000000..cf264fe --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/util/IPDConstants.java @@ -0,0 +1,7 @@ +package org.openmrs.module.ipd.api.util; + +public class IPDConstants { + + public static final String IPD_VIEW_DRUG_CHART = "drugChart"; + +} diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index 2d26ef5..3b33402 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -7,9 +7,11 @@ import org.openmrs.DrugOrder; import org.openmrs.Patient; import org.openmrs.api.context.Context; +import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; import org.openmrs.module.ipd.api.BaseIntegrationTest; import org.openmrs.module.ipd.api.dao.ScheduleDAO; import org.openmrs.module.ipd.api.dao.SlotDAO; +import org.openmrs.module.ipd.api.model.MedicationAdministration; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; @@ -31,6 +33,9 @@ public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest { @Autowired private SessionFactory sessionFactory; + @Autowired + private FhirMedicationAdministrationDao medicationAdministrationDao; + @Test public void shouldSaveTheSlotForPatientGivenPatientSchedule() { @@ -238,4 +243,88 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceType() { sessionFactory.getCurrentSession().delete(savedSlot2); sessionFactory.getCurrentSession().delete(savedSchedule); } + + @Test + public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Schedule schedule = new Schedule(); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime startTime = LocalDateTime.now(); + LocalDateTime slot1StartTime = LocalDateTime.now().plusHours(1); + LocalDateTime slot2StartTime = LocalDateTime.now().plusDays(-1); + LocalDateTime medicationAdministeredTime= LocalDateTime.now().plusHours(3); + LocalDateTime medicationAdministeredTime2= LocalDateTime.now().plusDays(3); + + + MedicationAdministration medicationAdministration=new MedicationAdministration(); + medicationAdministration.setStatus(testConcept); + medicationAdministration.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime)); + MedicationAdministration savedMedicationAdministration= medicationAdministrationDao.createOrUpdate(medicationAdministration); + + MedicationAdministration medicationAdministration2=new MedicationAdministration(); + medicationAdministration2.setStatus(testConcept); + medicationAdministration2.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime2)); + MedicationAdministration savedMedicationAdministration2= medicationAdministrationDao.createOrUpdate(medicationAdministration2); + + Slot slot1 = new Slot(); + slot1.setSchedule(savedSchedule); + slot1.setServiceType(testConcept); + slot1.setStartDateTime(slot1StartTime); + slot1.setOrder(drugOrder); + + Slot slot2 = new Slot(); + slot2.setSchedule(savedSchedule); + slot2.setServiceType(testConcept); + slot2.setStartDateTime(slot2StartTime); + slot2.setMedicationAdministration(savedMedicationAdministration); + slot2.setOrder(drugOrder2); + + Slot slot3 = new Slot(); + slot3.setSchedule(savedSchedule); + slot3.setServiceType(testConcept); + slot3.setStartDateTime(slot2StartTime); + slot3.setOrder(drugOrder); + + Slot slot4 = new Slot(); + slot4.setSchedule(savedSchedule); + slot4.setServiceType(testConcept); + slot4.setStartDateTime(slot1StartTime); + slot4.setMedicationAdministration(savedMedicationAdministration2); + slot4.setOrder(drugOrder); + + Slot savedSlot1 = slotDAO.saveSlot(slot1); + Slot savedSlot2 = slotDAO.saveSlot(slot2); + Slot savedSlot3 = slotDAO.saveSlot(slot3); + Slot savedSlot4 = slotDAO.saveSlot(slot4); + + + List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6)); + + Assertions.assertEquals(2, slotsBySubjectReferenceIdAndServiceType.size()); + + sessionFactory.getCurrentSession().delete(savedMedicationAdministration); + sessionFactory.getCurrentSession().delete(savedMedicationAdministration2); + sessionFactory.getCurrentSession().delete(savedSlot1); + sessionFactory.getCurrentSession().delete(savedSlot2); + sessionFactory.getCurrentSession().delete(savedSlot3); + sessionFactory.getCurrentSession().delete(savedSlot4); + sessionFactory.getCurrentSession().delete(savedSchedule); + + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index 6e9cdde..9306924 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -15,6 +15,7 @@ import org.openmrs.module.ipd.api.model.Slot; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -119,4 +120,19 @@ public void shouldInvokeGetSlotsByForReferenceAndServiceTypeAndOrderUuidsWithGiv Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids); } + + @Test + public void shouldInvokeGetSlotsBySubjectReferenceAndAdministeredTimeWithGivenTimeFrame() { + + List slots = new ArrayList<>(); + LocalDateTime startTime= LocalDateTime.now(); + LocalDateTime endTime = startTime.plusHours(8); + Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + + Mockito.when(slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime)).thenReturn(slots); + + slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(patientReference,startTime,endTime); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime); + } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java index 30270d6..2a02506 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java @@ -33,7 +33,6 @@ public class MedicationAdministrationRequest { private String slotUuid; public Date getAdministeredDateTimeAsLocaltime() { - return this.administeredDateTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.administeredDateTime)): null; + return this.administeredDateTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.administeredDateTime)): new Date(); } - } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 615e143..ba7860d 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -3,6 +3,8 @@ import lombok.extern.slf4j.Slf4j; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.openmrs.module.ipd.api.util.IPDConstants; import org.openmrs.module.ipd.contract.MedicationScheduleResponse; import org.openmrs.module.ipd.contract.MedicationSlotResponse; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; @@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -66,12 +69,14 @@ public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedi @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "startTime", "endTime"}) @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, - @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime) { + @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime, + @RequestParam(value = "view", required = false) String view) { try { if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); - List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate); + Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); + List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime); return new ResponseEntity<>(constructResponse(slots), OK); } throw new Exception(); @@ -102,9 +107,9 @@ public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value } } - private List constructResponse(List slots) { Map> slotsBySchedule = slots.stream().collect(Collectors.groupingBy(Slot::getSchedule)); return slotsBySchedule.entrySet().stream().map(entry -> createFrom(entry.getKey(), entry.getValue())).collect(Collectors.toList()); } + } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 9893fef..8940ced 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -15,5 +15,5 @@ public interface IPDScheduleService { List getMedicationSlots(String patientUuid, ServiceType serviceType); List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); - List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java index 5ead815..5e70669 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java @@ -13,6 +13,7 @@ import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.api.translators.MedicationAdministrationToSlotStatusTranslator; import org.openmrs.module.ipd.api.util.DateTimeUtil; import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; import org.openmrs.module.ipd.factory.MedicationAdministrationFactory; @@ -39,13 +40,15 @@ public class IPDMedicationAdministrationServiceImpl implements IPDMedicationAdmi private SlotService slotService; private ScheduleService scheduleService; private FhirMedicationAdministrationDao fhirMedicationAdministrationDao; + private MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator; @Autowired public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationService fhirMedicationAdministrationService, MedicationAdministrationTranslator medicationAdministrationTranslator, MedicationAdministrationFactory medicationAdministrationFactory, SlotFactory slotFactory, SlotService slotService, ScheduleService scheduleService, - FhirMedicationAdministrationDao fhirMedicationAdministrationDao) { + FhirMedicationAdministrationDao fhirMedicationAdministrationDao, + MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator) { this.fhirMedicationAdministrationService = fhirMedicationAdministrationService; this.medicationAdministrationTranslator = medicationAdministrationTranslator; this.medicationAdministrationFactory = medicationAdministrationFactory; @@ -53,6 +56,7 @@ public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationServic this.slotService = slotService; this.scheduleService = scheduleService; this.fhirMedicationAdministrationDao = fhirMedicationAdministrationDao; + this.medicationAdministrationToSlotStatusTranslator=medicationAdministrationToSlotStatusTranslator; } private org.hl7.fhir.r4.model.MedicationAdministration createMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest) { @@ -68,17 +72,15 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveScheduledMedicationAdm } else { if (slot.getMedicationAdministration() != null) { return fhirMedicationAdministrationService.get(slot.getMedicationAdministration().getUuid()); - } else if (!StringUtils.isBlank(medicationAdministrationRequest.getUuid())) { + } + if (!StringUtils.isBlank(medicationAdministrationRequest.getUuid())) { return fhirMedicationAdministrationService.get(medicationAdministrationRequest.getUuid()); - } else { - org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest); - if (medicationAdministration.getStatus().equals(org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationStatus.COMPLETED)) { - slot.setStatus(Slot.SlotStatus.COMPLETED); - } - slot.setMedicationAdministration((MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId())); - slotService.saveSlot(slot); - return medicationAdministration; } + org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest); + slot.setStatus(medicationAdministrationToSlotStatusTranslator.toSlotStatus(medicationAdministration.getStatus())); + slot.setMedicationAdministration((MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId())); + slotService.saveSlot(slot); + return medicationAdministration; } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 767d3e2..d5335ab 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -115,10 +115,13 @@ private void voidExistingMedicationSlotsForOrder(String patientUuid,String order @Override - public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate) { + public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime) { Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); + if (considerAdministeredTime) { + return slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(subjectReference.get(), localStartDate, localEndDate); + } return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate); } } \ No newline at end of file From d695d2e8f0c35668222f1d9b142ae1eb472d23fb Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Tue, 16 Jan 2024 14:04:05 +0530 Subject: [PATCH 11/75] BAH-3460 | Kavitha | refactor save adhoc medications (#13) --- .../MedicationAdministrationRequest.java | 6 ++-- .../contract/ScheduleMedicationRequest.java | 2 ++ .../MedicationAdministrationFactory.java | 6 ++-- ...PDMedicationAdministrationServiceImpl.java | 31 ++++++++++++------- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java index 2a02506..43402ec 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationAdministrationRequest.java @@ -26,9 +26,9 @@ public class MedicationAdministrationRequest { private String drugUuid; private String dosingInstructions; private Double dose; - private String doseUnitsUuid; - private String routeUuid; - private String siteUuid; + private String doseUnits; + private String route; + private String site; private Long administeredDateTime; private String slotUuid; diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java index c7f196d..5c83ad1 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java @@ -3,6 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.Setter; import lombok.NoArgsConstructor; import org.openmrs.module.ipd.api.util.DateTimeUtil; @@ -13,6 +14,7 @@ import static org.openmrs.module.ipd.api.util.DateTimeUtil.convertEpocUTCToLocalTimeZone; @Getter +@Setter @Builder @NoArgsConstructor @AllArgsConstructor diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java index 89b5923..695d1cf 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java @@ -61,9 +61,9 @@ public MedicationAdministration mapRequestToMedicationAdministration(MedicationA medicationAdministration.setDrug(Context.getConceptService().getDrugByUuid(request.getDrugUuid())); medicationAdministration.setDosingInstructions(request.getDosingInstructions()); medicationAdministration.setDose(request.getDose()); - medicationAdministration.setDoseUnits(Context.getConceptService().getConceptByUuid(request.getDoseUnitsUuid())); - medicationAdministration.setRoute(Context.getConceptService().getConceptByUuid(request.getRouteUuid())); - medicationAdministration.setSite(Context.getConceptService().getConceptByUuid(request.getSiteUuid())); + medicationAdministration.setDoseUnits(Context.getConceptService().getConceptByName(request.getDoseUnits())); + medicationAdministration.setRoute(Context.getConceptService().getConceptByName(request.getRoute())); + medicationAdministration.setSite(Context.getConceptService().getConceptByName(request.getSite())); return medicationAdministration; } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java index 5e70669..01f9da1 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java @@ -16,7 +16,9 @@ import org.openmrs.module.ipd.api.translators.MedicationAdministrationToSlotStatusTranslator; import org.openmrs.module.ipd.api.util.DateTimeUtil; import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; +import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.factory.MedicationAdministrationFactory; +import org.openmrs.module.ipd.factory.ScheduleFactory; import org.openmrs.module.ipd.factory.SlotFactory; import org.openmrs.module.ipd.service.IPDMedicationAdministrationService; import org.springframework.beans.factory.annotation.Autowired; @@ -41,6 +43,7 @@ public class IPDMedicationAdministrationServiceImpl implements IPDMedicationAdmi private ScheduleService scheduleService; private FhirMedicationAdministrationDao fhirMedicationAdministrationDao; private MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator; + private ScheduleFactory scheduleFactory; @Autowired public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationService fhirMedicationAdministrationService, @@ -48,7 +51,8 @@ public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationServic MedicationAdministrationFactory medicationAdministrationFactory, SlotFactory slotFactory, SlotService slotService, ScheduleService scheduleService, FhirMedicationAdministrationDao fhirMedicationAdministrationDao, - MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator) { + MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator, + ScheduleFactory scheduleFactory) { this.fhirMedicationAdministrationService = fhirMedicationAdministrationService; this.medicationAdministrationTranslator = medicationAdministrationTranslator; this.medicationAdministrationFactory = medicationAdministrationFactory; @@ -57,6 +61,7 @@ public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationServic this.scheduleService = scheduleService; this.fhirMedicationAdministrationDao = fhirMedicationAdministrationDao; this.medicationAdministrationToSlotStatusTranslator=medicationAdministrationToSlotStatusTranslator; + this.scheduleFactory = scheduleFactory; } private org.hl7.fhir.r4.model.MedicationAdministration createMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest) { @@ -90,18 +95,20 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveAdhocMedicationAdminis Visit visit = Context.getVisitService().getActiveVisitsByPatient(patient).get(0); Schedule schedule = scheduleService.getScheduleByVisit(visit); if (schedule == null) { - throw new RuntimeException("Active Schedule not found"); - } else { - org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest); - MedicationAdministration openmrsMedicationAdministration = (MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId()); - List slotsStartTime = new ArrayList<>(); - slotsStartTime.add(DateTimeUtil.convertEpocUTCToLocalTimeZone(medicationAdministrationRequest.getAdministeredDateTime())); - ServiceType serviceType = openmrsMedicationAdministration.getDrugOrder() == null ? ServiceType.EMERGENCY_MEDICATION_REQUEST : ServiceType.AS_NEEDED_MEDICATION_REQUEST; - slotFactory.createSlotsForMedicationFrom(schedule, slotsStartTime, openmrsMedicationAdministration.getDrugOrder(), - openmrsMedicationAdministration, Slot.SlotStatus.COMPLETED, serviceType) - .forEach(slotService::saveSlot); - return medicationAdministration; + ScheduleMedicationRequest scheduleMedicationRequest = new ScheduleMedicationRequest(); + scheduleMedicationRequest.setPatientUuid(medicationAdministrationRequest.getPatientUuid()); + scheduleMedicationRequest.setProviderUuid(medicationAdministrationRequest.getProviders().get(0).getUuid()); + schedule = scheduleService.saveSchedule(scheduleFactory.createScheduleForMedicationFrom(scheduleMedicationRequest, visit)); } + org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest); + MedicationAdministration openmrsMedicationAdministration = (MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId()); + List slotsStartTime = new ArrayList<>(); + slotsStartTime.add(DateTimeUtil.convertEpocUTCToLocalTimeZone(medicationAdministrationRequest.getAdministeredDateTime())); + ServiceType serviceType = openmrsMedicationAdministration.getDrugOrder() == null ? ServiceType.EMERGENCY_MEDICATION_REQUEST : ServiceType.AS_NEEDED_MEDICATION_REQUEST; + slotFactory.createSlotsForMedicationFrom(schedule, slotsStartTime, openmrsMedicationAdministration.getDrugOrder(), + openmrsMedicationAdministration, Slot.SlotStatus.COMPLETED, serviceType) + .forEach(slotService::saveSlot); + return medicationAdministration; } } From 24b6d13f469c93819c121bae89d8432ce0becb32 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Tue, 16 Jan 2024 14:09:19 +0530 Subject: [PATCH 12/75] Changes to stop/void slots associated with drugorder when its stopped (#12) Changes to stop/void slots associated with drugorder when its stopped --- .../openmrs/module/ipd/api/model/Slot.java | 4 +++ .../postprocessor/IPDTransactionHandler.java | 25 ++++++++++++++ .../ipd/service/IPDScheduleService.java | 3 ++ .../service/impl/IPDScheduleServiceImpl.java | 33 ++++++++++++++++--- 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index 03b6d80..70a09eb 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -86,6 +86,10 @@ public enum SlotStatus { @OneToOne @JoinColumn(name = "medication_administration_id", referencedColumnName = "medication_administration_id") private MedicationAdministration medicationAdministration; + + public Boolean isStopped() { + return this.status !=null && this.status == SlotStatus.STOPPED; + } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java new file mode 100644 index 0000000..81c74aa --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.postprocessor; + +import org.openmrs.Encounter; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; +import org.openmrs.module.emrapi.encounter.postprocessor.EncounterTransactionHandler; +import org.openmrs.module.ipd.service.IPDScheduleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IPDTransactionHandler implements EncounterTransactionHandler { + + @Autowired + IPDScheduleService ipdScheduleService; + + @Override + public void forRead(Encounter encounter, EncounterTransaction encounterTransaction) { + // No Implementation needed as of now + } + + @Override + public void forSave(Encounter encounter, EncounterTransaction encounterTransaction) { + ipdScheduleService.handlePostProcessEncounterTransaction(encounter,encounterTransaction); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 8940ced..b7aea6a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -1,5 +1,7 @@ package org.openmrs.module.ipd.service; +import org.openmrs.Encounter; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; @@ -16,4 +18,5 @@ public interface IPDScheduleService { List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime); + void handlePostProcessEncounterTransaction(Encounter encounter, EncounterTransaction encounterTransaction); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index d5335ab..fc017fa 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -1,13 +1,12 @@ package org.openmrs.module.ipd.service.impl; -import org.openmrs.Concept; -import org.openmrs.DrugOrder; -import org.openmrs.Patient; -import org.openmrs.Visit; +import org.openmrs.*; import org.openmrs.api.ConceptService; import org.openmrs.api.OrderService; import org.openmrs.api.PatientService; import org.openmrs.api.VisitService; +import org.openmrs.api.context.Context; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.ServiceType; @@ -26,6 +25,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static org.openmrs.module.ipd.api.model.Slot.SlotStatus.SCHEDULED; @@ -124,4 +124,29 @@ public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, Loc } return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate); } + + @Override + public void handlePostProcessEncounterTransaction(Encounter encounter, EncounterTransaction encounterTransaction) { + if (Boolean.valueOf(Context.getAdministrationService().getGlobalProperty("bahmni-ipd.allowSlotStopOnDrugOrderStop","false"))) { + handleDrugOrderStop(encounterTransaction); + } + } + + private void handleDrugOrderStop(EncounterTransaction encounterTransaction){ + List stoppedDrugOrders = encounterTransaction.getDrugOrders().stream().filter(drugOrder -> drugOrder.getDateStopped() !=null).collect(Collectors.toList()); + String patientUuid = encounterTransaction.getPatientUuid(); + for (EncounterTransaction.DrugOrder drugOrder : stoppedDrugOrders) { + List existingSlots = getMedicationSlots(patientUuid,ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{drugOrder.getPreviousOrderUuid()}))); + if (existingSlots == null || existingSlots.isEmpty()) { + continue; + } + boolean atleastOneMedicationAdministered = existingSlots.stream().anyMatch(slot -> slot.getMedicationAdministration() != null); + if (atleastOneMedicationAdministered){ // Mark status of non administered slots to stopped + existingSlots.stream().forEach(slot -> { if ((slot.getMedicationAdministration() ==null) && !slot.isStopped()) {slot.setStatus(Slot.SlotStatus.STOPPED); slotService.saveSlot(slot);}}); + } else { // Void all slots + existingSlots.stream().forEach(slot -> slotService.voidSlot(slot, "")); + } + } + + } } \ No newline at end of file From c9f4bc060a8d283d01658a85737ea5b02e5eb809 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:51:43 +0530 Subject: [PATCH 13/75] BAH-3460 | fix provider uuid issue for schedule creation (#14) --- .../service/impl/IPDMedicationAdministrationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java index 01f9da1..c2170e3 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java @@ -97,7 +97,7 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveAdhocMedicationAdminis if (schedule == null) { ScheduleMedicationRequest scheduleMedicationRequest = new ScheduleMedicationRequest(); scheduleMedicationRequest.setPatientUuid(medicationAdministrationRequest.getPatientUuid()); - scheduleMedicationRequest.setProviderUuid(medicationAdministrationRequest.getProviders().get(0).getUuid()); + scheduleMedicationRequest.setProviderUuid(medicationAdministrationRequest.getProviders().get(0).getProviderUuid()); schedule = scheduleService.saveSchedule(scheduleFactory.createScheduleForMedicationFrom(scheduleMedicationRequest, visit)); } org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest); From 1361ee7c92c6b0ac35b7a24d9164d3e04a8d68b4 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Mon, 22 Jan 2024 18:58:42 +0530 Subject: [PATCH 14/75] Nursing task enhancement (#15) --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 2 +- .../ipd/api/dao/impl/HibernateSlotDAO.java | 6 ++-- .../openmrs/module/ipd/api/model/Slot.java | 3 ++ .../module/ipd/api/service/SlotService.java | 2 +- .../ipd/api/service/impl/SlotServiceImpl.java | 4 +-- .../contract/DrugOrderScheduleResponse.java | 2 ++ .../ipd/contract/MedicationSlotResponse.java | 3 ++ .../ipd/controller/IPDScheduleController.java | 29 +++++++++++++++---- .../module/ipd/factory/SlotFactory.java | 3 +- .../module/ipd/model/DrugOrderSchedule.java | 2 +- .../ipd/service/IPDScheduleService.java | 3 +- ...PDMedicationAdministrationServiceImpl.java | 2 +- .../service/impl/IPDScheduleServiceImpl.java | 6 ++-- 13 files changed, 48 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 2d46d1d..5f397c7 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -28,7 +28,7 @@ public interface SlotDAO { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); - List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 724454d..4415a89 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -101,13 +101,15 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis return query.getResultList(); } @Override - public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit){ Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate) and slot.voided=0"); + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate) and slot.voided=0 and slot.schedule.visit=:visit"); query.setParameter("subject", subject); query.setParameter("startDate", localStartDate); query.setParameter("endDate", localEndDate); + query.setParameter("visit", visit); + return query.getResultList(); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index 70a09eb..d9299fc 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -87,6 +87,9 @@ public enum SlotStatus { @JoinColumn(name = "medication_administration_id", referencedColumnName = "medication_administration_id") private MedicationAdministration medicationAdministration; + @Column(name = "comments") + private String notes; + public Boolean isStopped() { return this.status !=null && this.status == SlotStatus.STOPPED; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 328895f..782c470 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -34,7 +34,7 @@ public interface SlotService extends OpenmrsService { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); - List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 079fd18..1596d43 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -80,8 +80,8 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis return slotDAO.getSlotsByPatientAndVisitAndServiceType(subject, visit, serviceType); } @Override - public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { - return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate); + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit){ + return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate, visit); } @Override diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index c7ee133..bcad4c5 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -16,6 +16,7 @@ public class DrugOrderScheduleResponse { private List remainingDaySlotsStartTime; private Long slotStartTime; private Boolean medicationAdministrationStarted; + private String notes; public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSchedule){ return DrugOrderScheduleResponse.builder(). @@ -24,6 +25,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). + notes(drugOrderSchedule.getNotes()). build(); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java index b78254e..60d103f 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/MedicationSlotResponse.java @@ -26,6 +26,7 @@ public class MedicationSlotResponse { private long startTime; private Object order; private Object medicationAdministration; + private String notes; public static MedicationSlotResponse createFrom(Slot slot) { return MedicationSlotResponse.builder() @@ -36,6 +37,7 @@ public static MedicationSlotResponse createFrom(Slot slot) { .startTime(convertLocalDateTimeToUTCEpoc(slot.getStartDateTime())) .order(ConversionUtil.convertToRepresentation(slot.getOrder(), Representation.FULL)) .medicationAdministration(MedicationAdministrationResponse.createFrom((slot.getMedicationAdministration()))) + .notes(slot.getNotes()) .build(); } @@ -49,6 +51,7 @@ public static MedicationSlotResponse createFrom(Slot slot, Representation rep) { .status(slot.getStatus().name()) .startTime(convertLocalDateTimeToUTCEpoc(slot.getStartDateTime())) .medicationAdministration(MedicationAdministrationResponse.createFrom((slot.getMedicationAdministration()))) + .notes(slot.getNotes()) .build(); } return MedicationSlotResponse.createFrom(slot); diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index ba7860d..1f09a20 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -1,10 +1,15 @@ package org.openmrs.module.ipd.controller; +import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.api.PatientService; +import org.openmrs.api.VisitService; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.Slot; -import org.openmrs.module.ipd.api.util.DateTimeUtil; import org.openmrs.module.ipd.api.util.IPDConstants; +import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.module.ipd.contract.MedicationScheduleResponse; import org.openmrs.module.ipd.contract.MedicationSlotResponse; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; @@ -19,7 +24,6 @@ import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -36,10 +40,16 @@ public class IPDScheduleController extends BaseRestController { private final IPDScheduleService ipdScheduleService; + private final VisitService visitService; + private final PatientService patientService; + private final ScheduleService scheduleService; @Autowired - public IPDScheduleController(IPDScheduleService ipdScheduleService) { + public IPDScheduleController(IPDScheduleService ipdScheduleService, VisitService visitService, PatientService patientService, ScheduleService scheduleService) { this.ipdScheduleService = ipdScheduleService; + this.visitService = visitService; + this.patientService = patientService; + this.scheduleService = scheduleService; } @RequestMapping(value = "type/medication", method = RequestMethod.POST) @@ -76,8 +86,10 @@ public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "pa LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); - List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime); - return new ResponseEntity<>(constructResponse(slots), OK); + Patient patient = patientService.getPatientByUuid(patientUuid); + Visit visit = visitService.getActiveVisitsByPatient(patient).get(0); + List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime, visit); + return new ResponseEntity<>(constructResponse(slots, visit), OK); } throw new Exception(); } catch (Exception e) { @@ -107,7 +119,12 @@ public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value } } - private List constructResponse(List slots) { + + private List constructResponse(List slots, Visit visit) { + Schedule schedule = scheduleService.getScheduleByVisit(visit); + if(slots.isEmpty() && schedule != null){ + return Lists.newArrayList(createFrom(schedule, slots)); + } Map> slotsBySchedule = slots.stream().collect(Collectors.groupingBy(Slot::getSchedule)); return slotsBySchedule.entrySet().stream().map(entry -> createFrom(entry.getKey(), entry.getValue())).collect(Collectors.toList()); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java index 17c09e8..d9a9753 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java @@ -37,7 +37,7 @@ public SlotFactory(BedManagementService bedManagementService, ConceptService con public List createSlotsForMedicationFrom(Schedule savedSchedule, List slotsStartTime, Order drugOrder, MedicationAdministration medicationAdministration, - Slot.SlotStatus status, ServiceType serviceType) { + Slot.SlotStatus status, ServiceType serviceType, String comments) { return slotsStartTime.stream().map(slotStartTime -> { Slot slot = new Slot(); @@ -57,6 +57,7 @@ public List createSlotsForMedicationFrom(Schedule savedSchedule, List remainingDaySlotsStartTime; private Long slotStartTime; private List slots; - + private String notes; } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index b7aea6a..6e60a47 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -1,5 +1,6 @@ package org.openmrs.module.ipd.service; +import org.openmrs.Visit; import org.openmrs.Encounter; import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.ipd.api.model.Schedule; @@ -17,6 +18,6 @@ public interface IPDScheduleService { List getMedicationSlots(String patientUuid, ServiceType serviceType); List getMedicationSlots(String patientUuid, ServiceType serviceType, List orderUuids); Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); - List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime); + List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime, Visit visit); void handlePostProcessEncounterTransaction(Encounter encounter, EncounterTransaction encounterTransaction); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java index c2170e3..e374b19 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java @@ -106,7 +106,7 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveAdhocMedicationAdminis slotsStartTime.add(DateTimeUtil.convertEpocUTCToLocalTimeZone(medicationAdministrationRequest.getAdministeredDateTime())); ServiceType serviceType = openmrsMedicationAdministration.getDrugOrder() == null ? ServiceType.EMERGENCY_MEDICATION_REQUEST : ServiceType.AS_NEEDED_MEDICATION_REQUEST; slotFactory.createSlotsForMedicationFrom(schedule, slotsStartTime, openmrsMedicationAdministration.getDrugOrder(), - openmrsMedicationAdministration, Slot.SlotStatus.COMPLETED, serviceType) + openmrsMedicationAdministration, Slot.SlotStatus.COMPLETED, serviceType,"") .forEach(slotService::saveSlot); return medicationAdministration; } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index fc017fa..018a0f2 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -69,7 +69,7 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); - slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST) + slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) .forEach(slotService::saveSlot); return savedSchedule; @@ -115,14 +115,14 @@ private void voidExistingMedicationSlotsForOrder(String patientUuid,String order @Override - public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime) { + public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate, Boolean considerAdministeredTime, Visit visit) { Optional subjectReference = referenceService.getReferenceByTypeAndTargetUUID(Patient.class.getTypeName(), patientUuid); if(!subjectReference.isPresent()) return Collections.emptyList(); if (considerAdministeredTime) { return slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(subjectReference.get(), localStartDate, localEndDate); } - return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate); + return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate, visit); } @Override From 2a09418ef1520843b29f93122bb8c2791ebfe444 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:30:18 +0530 Subject: [PATCH 15/75] Abi | fix. schedule notes issue (#17) --- .../openmrs/module/ipd/contract/DrugOrderScheduleResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index bcad4c5..329b3af 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -25,7 +25,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). - notes(drugOrderSchedule.getNotes()). + notes(drugOrderSchedule.getSlots().get(0).getNotes()). build(); } } From 2127545b78e0a6281f480d648acb2663bae04d64 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:35:33 +0530 Subject: [PATCH 16/75] Provider acknowledge flow changes - Update API Introduced for Medication Administration Provider acknowledge flow changes - Update API Introduced for Medication Administration --- ...IPDMedicationAdministrationController.java | 14 +++++++ .../MedicationAdministrationFactory.java | 41 ++++++++++++------- .../IPDMedicationAdministrationService.java | 2 + ...PDMedicationAdministrationServiceImpl.java | 7 ++++ 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java index 19843e6..2e8f9d6 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java @@ -68,4 +68,18 @@ public ResponseEntity createAdhocMedicationAdministration(@RequestBody M } } + @RequestMapping(value = "/adhocMedicationAdministrations/{medicationAdministrationUuid}", method = RequestMethod.PUT) + @ResponseBody + public ResponseEntity updateAdhocMedicationAdministration( + @PathVariable("medicationAdministrationUuid") String medicationAdministrationUuid, + @RequestBody MedicationAdministrationRequest medicationAdministrationRequest) { + try { + MedicationAdministration medicationAdministration = ipdMedicationAdministrationService.updateAdhocMedicationAdministration(medicationAdministrationUuid,medicationAdministrationRequest); + return new ResponseEntity(medicationAdministrationFactory.mapMedicationAdministrationToResponse(medicationAdministration),OK); + } catch (Exception e) { + log.error("Runtime error while trying to update new medicationAdministration", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + } diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java index 695d1cf..7573ac6 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/MedicationAdministrationFactory.java @@ -12,6 +12,7 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -29,42 +30,54 @@ public MedicationAdministrationFactory(MedicationAdministrationTranslator medica this.medicationAdministrationStatusTranslator = medicationAdministrationStatusTranslator; } - public MedicationAdministration mapRequestToMedicationAdministration(MedicationAdministrationRequest request, MedicationAdministration medicationAdministration) { - - medicationAdministration.setAdministeredDateTime(request.getAdministeredDateTimeAsLocaltime()); - medicationAdministration.setStatus(medicationAdministrationStatusTranslator.toOpenmrsType(org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationStatus.fromCode(request.getStatus()))); - medicationAdministration.setPatient(Context.getPatientService().getPatientByUuid(request.getPatientUuid())); - medicationAdministration.setEncounter(Context.getEncounterService().getEncounterByUuid(request.getEncounterUuid())); - medicationAdministration.setDrugOrder((DrugOrder) Context.getOrderService().getOrderByUuid(request.getOrderUuid())); + public MedicationAdministration mapRequestToMedicationAdministration(MedicationAdministrationRequest request, MedicationAdministration existingMedicationAdministration) { + MedicationAdministration medicationAdministration = new MedicationAdministration(); + if (existingMedicationAdministration ==null || existingMedicationAdministration.getId() == null) { + medicationAdministration.setAdministeredDateTime(request.getAdministeredDateTimeAsLocaltime()); + medicationAdministration.setStatus(medicationAdministrationStatusTranslator.toOpenmrsType(org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationStatus.fromCode(request.getStatus()))); + medicationAdministration.setPatient(Context.getPatientService().getPatientByUuid(request.getPatientUuid())); + medicationAdministration.setEncounter(Context.getEncounterService().getEncounterByUuid(request.getEncounterUuid())); + medicationAdministration.setDrugOrder((DrugOrder) Context.getOrderService().getOrderByUuid(request.getOrderUuid())); + medicationAdministration.setDrug(Context.getConceptService().getDrugByUuid(request.getDrugUuid())); + medicationAdministration.setDosingInstructions(request.getDosingInstructions()); + medicationAdministration.setDose(request.getDose()); + medicationAdministration.setDoseUnits(Context.getConceptService().getConceptByName(request.getDoseUnits())); + medicationAdministration.setRoute(Context.getConceptService().getConceptByName(request.getRoute())); + medicationAdministration.setSite(Context.getConceptService().getConceptByName(request.getSite())); + } + else { + medicationAdministration.setUuid(existingMedicationAdministration.getUuid()); + } List providers = new ArrayList<>(); if (request.getProviders() != null) { for (MedicationAdministrationPerformerRequest performer : request.getProviders()) { MedicationAdministrationPerformer newProvider = new MedicationAdministrationPerformer(); + newProvider.setUuid(performer.getUuid()); newProvider.setActor(Context.getProviderService().getProviderByUuid(performer.getProviderUuid())); newProvider.setFunction(Context.getConceptService().getConceptByName(performer.getFunction())); providers.add(newProvider); } + if (existingMedicationAdministration !=null && existingMedicationAdministration.getPerformers() !=null){ + providers.addAll(existingMedicationAdministration.getPerformers()); + } } medicationAdministration.setPerformers(new HashSet<>(providers)); List notes = new ArrayList<>(); if (request.getNotes() != null) { for (MedicationAdministrationNoteRequest note : request.getNotes()) { MedicationAdministrationNote newNote = new MedicationAdministrationNote(); + newNote.setUuid(note.getUuid()); newNote.setAuthor(Context.getProviderService().getProviderByUuid(note.getAuthorUuid())); newNote.setText(note.getText()); newNote.setRecordedTime(note.getRecordedTimeAsLocaltime()); notes.add(newNote); } + if (existingMedicationAdministration !=null && existingMedicationAdministration.getNotes() !=null){ + notes.addAll(existingMedicationAdministration.getNotes()); + } } medicationAdministration.setNotes(new HashSet<>(notes)); - medicationAdministration.setDrug(Context.getConceptService().getDrugByUuid(request.getDrugUuid())); - medicationAdministration.setDosingInstructions(request.getDosingInstructions()); - medicationAdministration.setDose(request.getDose()); - medicationAdministration.setDoseUnits(Context.getConceptService().getConceptByName(request.getDoseUnits())); - medicationAdministration.setRoute(Context.getConceptService().getConceptByName(request.getRoute())); - medicationAdministration.setSite(Context.getConceptService().getConceptByName(request.getSite())); - return medicationAdministration; } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDMedicationAdministrationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDMedicationAdministrationService.java index 5693b2a..6de9108 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDMedicationAdministrationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDMedicationAdministrationService.java @@ -7,6 +7,8 @@ public interface IPDMedicationAdministrationService { MedicationAdministration saveScheduledMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest); + MedicationAdministration updateAdhocMedicationAdministration(String uuid,MedicationAdministrationRequest medicationAdministrationRequest); + MedicationAdministration saveAdhocMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java index e374b19..42f8d22 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDMedicationAdministrationServiceImpl.java @@ -89,6 +89,13 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveScheduledMedicationAdm } } + @Override + public org.hl7.fhir.r4.model.MedicationAdministration updateAdhocMedicationAdministration(String uuid, MedicationAdministrationRequest medicationAdministrationRequest) { + MedicationAdministration medicationAdministration = medicationAdministrationFactory.mapRequestToMedicationAdministration(medicationAdministrationRequest, + (MedicationAdministration) fhirMedicationAdministrationDao.get(uuid)); + return fhirMedicationAdministrationService.update(uuid,medicationAdministrationTranslator.toFhirResource(medicationAdministration)); + } + @Override public org.hl7.fhir.r4.model.MedicationAdministration saveAdhocMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest) { Patient patient = Context.getPatientService().getPatientByUuid(medicationAdministrationRequest.getPatientUuid()); From 97e4823740835d3c9f2a6bd26a4be17470fdacd0 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Wed, 31 Jan 2024 11:57:45 +0530 Subject: [PATCH 17/75] Kavitha | fix slot creation logic for 1 day (#19) --- .../service/impl/SlotTimeCreationService.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index ef8efc9..56e66da 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -27,7 +27,10 @@ public class SlotTimeCreationService extends BaseOpenmrsService { public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, DrugOrder order) { if (request.getSlotStartTimeAsLocaltime() != null && request.getMedicationFrequency() == START_TIME_DURATION_FREQUENCY) { return getSlotsStartTimeWithStartTimeDurationFrequency(request, order); - } else if (!CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) && request.getMedicationFrequency() == FIXED_SCHEDULE_FREQUENCY) { + } else if ((!CollectionUtils.isEmpty(request.getFirstDaySlotsStartTimeAsLocalTime()) || + !CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) || + !CollectionUtils.isEmpty(request.getRemainingDaySlotsStartTimeAsLocalTime())) + && request.getMedicationFrequency() == FIXED_SCHEDULE_FREQUENCY) { return getSlotsStartTimeWithFixedScheduleFrequency(request, order); } @@ -38,7 +41,6 @@ private List getSlotsStartTimeWithFixedScheduleFrequency(Schedule int numberOfSlotsStartTimeToBeCreated = (int) (Math.ceil(order.getQuantity() / order.getDose())); List slotsStartTime = new ArrayList<>(); - if (!CollectionUtils.isEmpty(request.getFirstDaySlotsStartTimeAsLocalTime())) { List slotsToBeAddedForFirstDay = numberOfSlotsStartTimeToBeCreated < request.getFirstDaySlotsStartTimeAsLocalTime().size() ? request.getFirstDaySlotsStartTimeAsLocalTime().subList(0, numberOfSlotsStartTimeToBeCreated) @@ -48,26 +50,26 @@ private List getSlotsStartTimeWithFixedScheduleFrequency(Schedule numberOfSlotsStartTimeToBeCreated -= slotsToBeAddedForFirstDay.size(); } - if (!CollectionUtils.isEmpty(request.getDayWiseSlotsStartTimeAsLocalTime()) && numberOfSlotsStartTimeToBeCreated > 0) { - List initialSlotsToBeAddedForSecondDay = numberOfSlotsStartTimeToBeCreated < request.getDayWiseSlotsStartTimeAsLocalTime().size() - ? request.getDayWiseSlotsStartTimeAsLocalTime().subList(0, numberOfSlotsStartTimeToBeCreated) - : request.getDayWiseSlotsStartTimeAsLocalTime(); + List remainingDaySlotsStartTime = request.getRemainingDaySlotsStartTimeAsLocalTime(); + if (!CollectionUtils.isEmpty(remainingDaySlotsStartTime) && numberOfSlotsStartTimeToBeCreated > 0) { + List slotsToBeAddedForRemainingDay = numberOfSlotsStartTimeToBeCreated < remainingDaySlotsStartTime.size() + ? remainingDaySlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated) + : remainingDaySlotsStartTime; + numberOfSlotsStartTimeToBeCreated -= slotsToBeAddedForRemainingDay.size(); + slotsStartTime.addAll(slotsToBeAddedForRemainingDay); + } + + List nextSlotsStartTime = request.getDayWiseSlotsStartTimeAsLocalTime(); + if (!CollectionUtils.isEmpty(nextSlotsStartTime) && numberOfSlotsStartTimeToBeCreated > 0) { + List initialSlotsToBeAddedForSecondDay = numberOfSlotsStartTimeToBeCreated < nextSlotsStartTime.size() + ? nextSlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated) + : nextSlotsStartTime; slotsStartTime.addAll(initialSlotsToBeAddedForSecondDay); numberOfSlotsStartTimeToBeCreated -= initialSlotsToBeAddedForSecondDay.size(); - - List nextSlotsStartTime = request.getDayWiseSlotsStartTimeAsLocalTime(); - List remainingDaySlotsStartTime = request.getRemainingDaySlotsStartTimeAsLocalTime(); while (numberOfSlotsStartTimeToBeCreated > 0) { nextSlotsStartTime = nextSlotsStartTime.stream().map(slotStartTime -> slotStartTime.plusHours(24)).collect(Collectors.toList()); - if (!CollectionUtils.isEmpty(remainingDaySlotsStartTime) && numberOfSlotsStartTimeToBeCreated <= remainingDaySlotsStartTime.size()){ - List slotsToBeAddedForRemainingDay = numberOfSlotsStartTimeToBeCreated < remainingDaySlotsStartTime.size() - ? remainingDaySlotsStartTime.subList(0, numberOfSlotsStartTimeToBeCreated) - : remainingDaySlotsStartTime; - numberOfSlotsStartTimeToBeCreated -= slotsToBeAddedForRemainingDay.size(); - slotsStartTime.addAll(slotsToBeAddedForRemainingDay); - } - else if (numberOfSlotsStartTimeToBeCreated >= nextSlotsStartTime.size()) { + if (numberOfSlotsStartTimeToBeCreated >= nextSlotsStartTime.size()) { slotsStartTime.addAll(nextSlotsStartTime); numberOfSlotsStartTimeToBeCreated -= nextSlotsStartTime.size(); } else { From 29c3372e07872a9868155175790a042539924c95 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:30:43 +0530 Subject: [PATCH 18/75] Kavitha | add void condition in fetching slots (#20) --- .../org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 4415a89..26e385a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -119,7 +119,7 @@ public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subj Query query = sessionFactory.getCurrentSession() .createQuery("SELECT slot FROM Slot slot " + "LEFT JOIN slot.medicationAdministration medAdmin " + - "WHERE (slot.schedule.subject = :subject) AND " + + "WHERE (slot.schedule.subject = :subject) AND slot.voided = 0 AND " + "(((slot.startDateTime BETWEEN :startDateTime AND :endDateTime) AND " + "(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate or medAdmin is null)) OR " + "(medAdmin is not null AND " + From 9ec1a07a2747d0375a980574cc68518436c31b9e Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:10:58 +0530 Subject: [PATCH 19/75] Abi | update. status as Stopped once administered and stopped a medicine (#21) --- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 018a0f2..500fc39 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -14,6 +14,7 @@ import org.openmrs.module.ipd.api.service.ReferenceService; import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.api.util.DateTimeUtil; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.factory.ScheduleFactory; import org.openmrs.module.ipd.factory.SlotFactory; @@ -142,7 +143,9 @@ private void handleDrugOrderStop(EncounterTransaction encounterTransaction){ } boolean atleastOneMedicationAdministered = existingSlots.stream().anyMatch(slot -> slot.getMedicationAdministration() != null); if (atleastOneMedicationAdministered){ // Mark status of non administered slots to stopped - existingSlots.stream().forEach(slot -> { if ((slot.getMedicationAdministration() ==null) && !slot.isStopped()) {slot.setStatus(Slot.SlotStatus.STOPPED); slotService.saveSlot(slot);}}); + existingSlots.stream().forEach(slot -> { + if ((slot.getMedicationAdministration() == null) && !slot.isStopped() && (DateTimeUtil.convertDateToLocalDateTime(drugOrder.getDateStopped()) + .compareTo(slot.getStartDateTime())) < 0) {slot.setStatus(Slot.SlotStatus.STOPPED); slotService.saveSlot(slot);}}); } else { // Void all slots existingSlots.stream().forEach(slot -> slotService.voidSlot(slot, "")); } From 1ecd098768e05e27cbfbb7df5069abe0815c78db Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:58:09 +0530 Subject: [PATCH 20/75] Changes to bring drug order one visit previous to current visit Changes to bring drug order one visit previous to current visit --- .../ipd/service/impl/IPDVisitServiceImpl.java | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java index def90cb..d765303 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.IntStream; @Service @Transactional @@ -70,15 +71,25 @@ public List getPrescribedOrders(String visitUuid, Boolean includeA List visitUuidsList = new ArrayList<>(); visitUuidsList.add(visitUuid); Visit visit = visitService.getVisitByUuid(visitUuid); + // Logic to fetch immediate preceded Visit's drug orders as well as part of current Visit drug order list as doctors tend to convert OPD to IPD immediately on emergency situations. + String precededVisitUuid= getImmediatePrecededVisit(visit.getPatient(),visitUuid); + if (precededVisitUuid!=null){ + visitUuidsList.add(precededVisitUuid); + } List prescribedDrugOrders = drugOrderService.getPrescribedDrugOrders(visitUuidsList, visit.getPatient().getUuid(), includeActiveVisit, numberOfVisits, startDate, endDate, getEffectiveOrdersOnly); - return getIPDDrugOrders(visit.getPatient().getUuid(), prescribedDrugOrders); + return getIPDDrugOrders(visit.getPatient().getUuid(), prescribedDrugOrders,visit); } - private List getIPDDrugOrders(String patientUuid, List drugOrders) { + private List getIPDDrugOrders(String patientUuid, List drugOrders,Visit currentVisit) { Map drugOrderMap = drugOrderService.getDiscontinuedDrugOrders(drugOrders); + // filter drug orders where its stop date is after current visit start Date + List drugOrdersFiltered = drugOrders.stream() + .filter(drugOrder -> drugOrder.getEffectiveStopDate() == null || drugOrder.getEffectiveStopDate().after(currentVisit.getStartDatetime())) + .collect(Collectors.toList()); + try { Collection orderAttributeObs = bahmniObsService.observationsFor(patientUuid, getOrdAttributeConcepts(), null, null, false, null, null, null); - List bahmniDrugOrders = bahmniDrugOrderMapper.mapToResponse(drugOrders, orderAttributeObs, drugOrderMap , null); + List bahmniDrugOrders = bahmniDrugOrderMapper.mapToResponse(drugOrdersFiltered, orderAttributeObs, drugOrderMap , null); bahmniDrugOrders=sortDrugOrdersAccordingToTheirSortWeight(bahmniDrugOrders); Map drugOrderScheduleByOrders = getDrugOrderScheduleForOrders(patientUuid, bahmniDrugOrders); @@ -154,4 +165,23 @@ public List getMedicationSlots(String visitUuid, ServiceType serviceType) return slotService.getSlotsByPatientAndVisitAndServiceType(subjectReference.get(), visit, concept); } + + private String getImmediatePrecededVisit(Patient patient,String currentVisitUuid){ + String previousVisitUuid=null; + List visits= visitService.getVisitsByPatient(patient); + List sortedVisits = visits.stream() + .sorted(Comparator.comparing(Visit::getStartDatetime).reversed()) + .collect(Collectors.toList()); + + int currentVisitIndex = IntStream.range(0, sortedVisits.size()) + .filter(i -> sortedVisits.get(i).getUuid().equals(currentVisitUuid)) + .findFirst() + .orElse(-1); + + if (currentVisitIndex != -1 && currentVisitIndex + 1 < sortedVisits.size()) { + previousVisitUuid = sortedVisits.get(currentVisitIndex + 1).getUuid(); + } + + return previousVisitUuid; + } } From 449107ecf3c07491622d2930ff37766cc5ee9293 Mon Sep 17 00:00:00 2001 From: Abinaya U Date: Fri, 2 Feb 2024 11:10:44 +0530 Subject: [PATCH 21/75] update. shift api to return slots based on visitUuid --- .../openmrs/module/ipd/controller/IPDScheduleController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 1f09a20..e2ae219 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -80,14 +80,14 @@ public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedi @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime, + @RequestParam(value = "visitUuid") String visitUuid, @RequestParam(value = "view", required = false) String view) { try { if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); - Patient patient = patientService.getPatientByUuid(patientUuid); - Visit visit = visitService.getActiveVisitsByPatient(patient).get(0); + Visit visit = visitService.getVisitByUuid(visitUuid); List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime, visit); return new ResponseEntity<>(constructResponse(slots, visit), OK); } From 4c325b62f79288759037c790e1080a6b1571b1d1 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Fri, 2 Feb 2024 20:11:21 +0530 Subject: [PATCH 22/75] add. check to avoid multiple save (#23) --- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 500fc39..72e9548 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -69,6 +69,10 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat savedSchedule = scheduleService.saveSchedule(schedule); } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); + List existingSlots = getMedicationSlots(patient.getUuid(),ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{order.getUuid()}))); + if (existingSlots !=null && !existingSlots.isEmpty()) { + throw new RuntimeException("Slots already created for this drug order"); + } List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) .forEach(slotService::saveSlot); From a65e6335690ae9b5b277c8476d4cdd77f7fac90d Mon Sep 17 00:00:00 2001 From: Abinaya U Date: Mon, 5 Feb 2024 15:32:53 +0530 Subject: [PATCH 23/75] update. filter slots for drugChart based on visit uuid --- .../org/openmrs/module/ipd/api/dao/SlotDAO.java | 2 +- .../module/ipd/api/dao/impl/HibernateSlotDAO.java | 5 +++-- .../module/ipd/api/service/SlotService.java | 2 +- .../ipd/api/service/impl/SlotServiceImpl.java | 4 ++-- .../dao/impl/HibernateSlotDAOIntegrationTest.java | 15 +++++++++++++-- .../ipd/api/service/impl/SlotServiceImplTest.java | 8 +++++--- .../ipd/service/impl/IPDScheduleServiceImpl.java | 2 +- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 5f397c7..4bf9493 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -30,6 +30,6 @@ public interface SlotDAO { List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); - List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 26e385a..9343300 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -115,17 +115,18 @@ public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference } @Override - public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { + public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit) { Query query = sessionFactory.getCurrentSession() .createQuery("SELECT slot FROM Slot slot " + "LEFT JOIN slot.medicationAdministration medAdmin " + - "WHERE (slot.schedule.subject = :subject) AND slot.voided = 0 AND " + + "WHERE (slot.schedule.subject = :subject) AND slot.voided = 0 AND slot.schedule.visit=:visit AND " + "(((slot.startDateTime BETWEEN :startDateTime AND :endDateTime) AND " + "(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate or medAdmin is null)) OR " + "(medAdmin is not null AND " + "(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate)))"); query.setParameter("subject", subject); + query.setParameter("visit", visit); query.setParameter("startDateTime", localStartDate); query.setParameter("endDateTime", localEndDate); query.setParameter("startDate", DateTimeUtil.convertLocalDateTimeDate(localStartDate)); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 782c470..467b04e 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -36,5 +36,5 @@ public interface SlotService extends OpenmrsService { List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); - List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); + List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 1596d43..cb506ae 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -85,7 +85,7 @@ public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference } @Override - public List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) { - return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate); + public List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit) { + return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate, visit); } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index 3b33402..02ea0b8 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -244,6 +244,7 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceType() { sessionFactory.getCurrentSession().delete(savedSchedule); } + //Need to fic this test case @Test public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { @@ -256,12 +257,22 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + Patient patient = new Patient(123); + patient.setUuid("d869ad24-d2a0-4747-a888-fe55048bb7cg"); + +// Visit visit = new Visit(); +// visit.setPatient(patient); +// visit.setStartDatetime(new Date()); +// visit.setVisitType(Context.getVisitService().getVisitType(1)); +// Visit visit1 = Context.getVisitService().saveVisit(visit); + Schedule schedule = new Schedule(); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); schedule.setEndDate(endDate); schedule.setServiceType(testConcept); + schedule.setVisit(null); Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); @@ -314,9 +325,9 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { Slot savedSlot4 = slotDAO.saveSlot(slot4); - List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6)); + List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6),null); - Assertions.assertEquals(2, slotsBySubjectReferenceIdAndServiceType.size()); + Assertions.assertEquals(0, slotsBySubjectReferenceIdAndServiceType.size()); sessionFactory.getCurrentSession().delete(savedMedicationAdministration); sessionFactory.getCurrentSession().delete(savedMedicationAdministration2); diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index 9306924..6542c40 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -9,6 +9,7 @@ import org.openmrs.Concept; import org.openmrs.ConceptName; import org.openmrs.Patient; +import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Schedule; @@ -128,11 +129,12 @@ public void shouldInvokeGetSlotsBySubjectReferenceAndAdministeredTimeWithGivenTi LocalDateTime startTime= LocalDateTime.now(); LocalDateTime endTime = startTime.plusHours(8); Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid"); + Visit visit = new Visit(123); - Mockito.when(slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime)).thenReturn(slots); + Mockito.when(slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime, visit)).thenReturn(slots); - slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(patientReference,startTime,endTime); + slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(patientReference,startTime,endTime,visit); - Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime); + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime, visit); } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 72e9548..852fa41 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -125,7 +125,7 @@ public List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, Loc if(!subjectReference.isPresent()) return Collections.emptyList(); if (considerAdministeredTime) { - return slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(subjectReference.get(), localStartDate, localEndDate); + return slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(subjectReference.get(), localStartDate, localEndDate, visit); } return slotService.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subjectReference.get(), localStartDate,localEndDate, visit); } From 1b853592c9e22f47dfbc73b267a690acaf54bb3e Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Mon, 5 Feb 2024 16:16:18 +0530 Subject: [PATCH 24/75] Test Case Fix for new change added --- .../impl/HibernateSlotDAOIntegrationTest.java | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index 02ea0b8..2533d5e 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -3,9 +3,7 @@ import org.hibernate.SessionFactory; import org.junit.Test; import org.junit.jupiter.api.Assertions; -import org.openmrs.Concept; -import org.openmrs.DrugOrder; -import org.openmrs.Patient; +import org.openmrs.*; import org.openmrs.api.context.Context; import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; import org.openmrs.module.ipd.api.BaseIntegrationTest; @@ -20,6 +18,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Date; import java.util.List; public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest { @@ -244,7 +243,6 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceType() { sessionFactory.getCurrentSession().delete(savedSchedule); } - //Need to fic this test case @Test public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { @@ -253,26 +251,23 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143"); Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + + Visit visit = new Visit(1); + visit.setPatient(new Patient(123)); + visit.setStartDatetime(new Date()); + visit.setVisitType(new VisitType(321)); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); - Patient patient = new Patient(123); - patient.setUuid("d869ad24-d2a0-4747-a888-fe55048bb7cg"); - -// Visit visit = new Visit(); -// visit.setPatient(patient); -// visit.setStartDatetime(new Date()); -// visit.setVisitType(Context.getVisitService().getVisitType(1)); -// Visit visit1 = Context.getVisitService().saveVisit(visit); - Schedule schedule = new Schedule(); schedule.setSubject(patientReference); schedule.setActor(providerReference); schedule.setStartDate(startDate); schedule.setEndDate(endDate); schedule.setServiceType(testConcept); - schedule.setVisit(null); + schedule.setVisit(visit); Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); @@ -325,9 +320,9 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { Slot savedSlot4 = slotDAO.saveSlot(slot4); - List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6),null); + List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6),visit); - Assertions.assertEquals(0, slotsBySubjectReferenceIdAndServiceType.size()); + Assertions.assertEquals(2, slotsBySubjectReferenceIdAndServiceType.size()); sessionFactory.getCurrentSession().delete(savedMedicationAdministration); sessionFactory.getCurrentSession().delete(savedMedicationAdministration2); @@ -336,6 +331,7 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { sessionFactory.getCurrentSession().delete(savedSlot3); sessionFactory.getCurrentSession().delete(savedSlot4); sessionFactory.getCurrentSession().delete(savedSchedule); + sessionFactory.getCurrentSession().delete(visit); } } From d04c7085b99e8ef6817cc51306323d885a72abc2 Mon Sep 17 00:00:00 2001 From: Arjun G <91885483+Arjun-Go@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:08:19 +0530 Subject: [PATCH 25/75] API to save/schedule the placeholder Tasks for PRN (#24) * add. logic for creating placeholder for as needed medications * add. test for getting medications in given time frame * add. logic to fetch medications of particular service type * update. name of variable --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 2 +- .../ipd/api/dao/impl/HibernateSlotDAO.java | 6 +- .../module/ipd/api/model/ServiceType.java | 3 +- .../ipd/api/service/impl/SlotServiceImpl.java | 13 ++- api/src/main/resources/liquibase.xml | 24 +++++ .../impl/HibernateSlotDAOIntegrationTest.java | 95 ++++++++++++++++++- .../contract/ScheduleMedicationRequest.java | 2 + .../ipd/controller/IPDScheduleController.java | 12 ++- .../module/ipd/factory/SlotFactory.java | 22 +++++ .../service/impl/IPDScheduleServiceImpl.java | 18 ++-- 10 files changed, 177 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 5f397c7..a8265df 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -28,7 +28,7 @@ public interface SlotDAO { List getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType); - List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); + List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit, Concept serviceType); List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 26e385a..266e14f 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -101,15 +101,15 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis return query.getResultList(); } @Override - public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit){ + public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit, Concept serviceType){ Query query = sessionFactory.getCurrentSession() - .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and (slot.startDateTime BETWEEN :startDate and :endDate) and slot.voided=0 and slot.schedule.visit=:visit"); + .createQuery("FROM Slot slot WHERE slot.schedule.subject=:subject and ((slot.startDateTime BETWEEN :startDate and :endDate) or (slot.serviceType = :serviceType)) and slot.voided=0 and slot.schedule.visit=:visit"); query.setParameter("subject", subject); query.setParameter("startDate", localStartDate); query.setParameter("endDate", localEndDate); query.setParameter("visit", visit); - + query.setParameter("serviceType", serviceType); return query.getResultList(); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java index 651daeb..90de59c 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/ServiceType.java @@ -3,7 +3,8 @@ public enum ServiceType { MEDICATION_REQUEST("MedicationRequest"), EMERGENCY_MEDICATION_REQUEST("EmergencyMedicationRequest"), - AS_NEEDED_MEDICATION_REQUEST("AsNeededMedicationRequest"); + AS_NEEDED_MEDICATION_REQUEST("AsNeededMedicationRequest"), + AS_NEEDED_PLACEHOLDER("AsNeededPlaceholder"); private final String conceptName; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 1596d43..ddef5cb 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -1,10 +1,12 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Concept; +import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.api.service.SlotService; import org.openmrs.api.APIException; @@ -27,12 +29,16 @@ public class SlotServiceImpl extends BaseOpenmrsService implements SlotService { private static final Logger log = LoggerFactory.getLogger(SlotServiceImpl.class); private final SlotDAO slotDAO; + private ConceptService conceptService; @Autowired - public SlotServiceImpl(SlotDAO slotDAO) { + public SlotServiceImpl(SlotDAO slotDAO, ConceptService conceptService) { + this.slotDAO = slotDAO; + this.conceptService = conceptService; } - + + @Override @Transactional(readOnly = true) public Slot getSlot(Integer slotId) throws APIException { @@ -81,7 +87,8 @@ public List getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis } @Override public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit){ - return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate, visit); + Concept asNeededPlaceholderServiceType = conceptService.getConceptByName(ServiceType.AS_NEEDED_PLACEHOLDER.conceptName()); + return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate, visit, asNeededPlaceholderServiceType); } @Override diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 8464105..a38f065 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -276,4 +276,28 @@ + + + + SELECT COUNT(*) FROM concept where short_name='AsNeededPlaceholder' and description='AsNeededPlaceholder'; + + + SELECT COUNT(*) FROM concept_name where name ='AsNeededPlaceholder'; + + + Add concept for As Needed Medication Request + + insert into concept (retired, short_name, description, datatype_id, class_id, is_set, creator, date_created, + changed_by, date_changed, uuid) + values (0, 'AsNeededPlaceholder', 'AsNeededPlaceholder', + (select concept_datatype_id from concept_datatype where name = 'Text'), + (select concept_class_id from concept_class where name = 'Misc'), + 0, 1, now(), 1, now(), uuid()); + insert into concept_name (concept_id, name, locale, locale_preferred, creator, date_created, + concept_name_type, voided, uuid) + values ((select concept_id from concept where short_name='AsNeededPlaceholder'), + 'AsNeededPlaceholder', 'en', 1, 1, now(), 'FULLY_SPECIFIED', 0, uuid()); + + + diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index 3b33402..a2f3da6 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -3,9 +3,7 @@ import org.hibernate.SessionFactory; import org.junit.Test; import org.junit.jupiter.api.Assertions; -import org.openmrs.Concept; -import org.openmrs.DrugOrder; -import org.openmrs.Patient; +import org.openmrs.*; import org.openmrs.api.context.Context; import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; import org.openmrs.module.ipd.api.BaseIntegrationTest; @@ -20,6 +18,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Date; import java.util.List; public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest { @@ -327,4 +326,94 @@ public void shouldGetTheSavedSlotsForPatientByAdministeredTime() { sessionFactory.getCurrentSession().delete(savedSchedule); } + + @Test + public void shouldGetTheSavedSlotsForPatientBySubjectReferenceAndAGivenTimeFrame() { + + String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142"; + DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid); + DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143"); + Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5"); + Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce"); + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate()); + LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate()); + + Visit visit = new Visit(1); + visit.setPatient(new Patient(123)); + visit.setStartDatetime(new Date()); + visit.setVisitType(new VisitType(321)); + + Schedule schedule = new Schedule(); + schedule.setSubject(patientReference); + schedule.setActor(providerReference); + schedule.setStartDate(startDate); + schedule.setVisit(visit); + schedule.setEndDate(endDate); + schedule.setServiceType(testConcept); + + Schedule savedSchedule = scheduleDAO.saveSchedule(schedule); + + LocalDateTime startTime = LocalDateTime.now(); + LocalDateTime slot1StartTime = LocalDateTime.now().plusHours(1); + LocalDateTime slot2StartTime = LocalDateTime.now().plusDays(-1); + LocalDateTime medicationAdministeredTime= LocalDateTime.now().plusHours(3); + LocalDateTime medicationAdministeredTime2= LocalDateTime.now().plusDays(3); + + + MedicationAdministration medicationAdministration=new MedicationAdministration(); + medicationAdministration.setStatus(testConcept); + medicationAdministration.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime)); + MedicationAdministration savedMedicationAdministration= medicationAdministrationDao.createOrUpdate(medicationAdministration); + + MedicationAdministration medicationAdministration2=new MedicationAdministration(); + medicationAdministration2.setStatus(testConcept); + medicationAdministration2.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime2)); + MedicationAdministration savedMedicationAdministration2= medicationAdministrationDao.createOrUpdate(medicationAdministration2); + + Slot slot1 = new Slot(); + slot1.setSchedule(savedSchedule); + slot1.setServiceType(testConcept); + slot1.setStartDateTime(slot1StartTime); + slot1.setOrder(drugOrder); + + Slot slot2 = new Slot(); + slot2.setSchedule(savedSchedule); + slot2.setServiceType(testConcept); + slot2.setStartDateTime(slot2StartTime); + slot2.setMedicationAdministration(savedMedicationAdministration); + slot2.setOrder(drugOrder2); + + Slot slot3 = new Slot(); + slot3.setSchedule(savedSchedule); + slot3.setServiceType(testConcept); + slot3.setStartDateTime(slot2StartTime); + slot3.setOrder(drugOrder); + + Slot slot4 = new Slot(); + slot4.setSchedule(savedSchedule); + slot4.setServiceType(testConcept); + slot4.setStartDateTime(slot1StartTime); + slot4.setOrder(drugOrder); + + Slot savedSlot1 = slotDAO.saveSlot(slot1); + Slot savedSlot2 = slotDAO.saveSlot(slot2); + Slot savedSlot3 = slotDAO.saveSlot(slot3); + Slot savedSlot4 = slotDAO.saveSlot(slot4); + + + List slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(patientReference,startTime,startTime.plusHours(6),visit,testConcept); + + Assertions.assertEquals(4, slotsBySubjectReferenceIdAndServiceType.size()); + + sessionFactory.getCurrentSession().delete(savedMedicationAdministration); + sessionFactory.getCurrentSession().delete(savedMedicationAdministration2); + sessionFactory.getCurrentSession().delete(savedSlot1); + sessionFactory.getCurrentSession().delete(savedSlot2); + sessionFactory.getCurrentSession().delete(savedSlot3); + sessionFactory.getCurrentSession().delete(savedSlot4); + sessionFactory.getCurrentSession().delete(savedSchedule); + sessionFactory.getCurrentSession().delete(visit); + + } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java index 5c83ad1..51080fe 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/ScheduleMedicationRequest.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.Setter; import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.util.DateTimeUtil; import java.time.LocalDateTime; @@ -29,6 +30,7 @@ public class ScheduleMedicationRequest { private List dayWiseSlotsStartTime; private List remainingDaySlotsStartTime; private MedicationFrequency medicationFrequency; + private ServiceType serviceType; public enum MedicationFrequency { START_TIME_DURATION_FREQUENCY, diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 1f09a20..ae95c8b 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -7,6 +7,7 @@ import org.openmrs.api.PatientService; import org.openmrs.api.VisitService; import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.api.util.IPDConstants; import org.openmrs.module.ipd.api.service.ScheduleService; @@ -82,7 +83,7 @@ public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "pa @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime, @RequestParam(value = "view", required = false) String view) { try { - if (startTime != null && endTime != null) { +; if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); @@ -101,13 +102,18 @@ public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "pa @RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid"}) @ResponseBody public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value = "patientUuid") String patientUuid, + @RequestParam(value = "serviceType", required = false) ServiceType serviceType, @RequestParam(value = "orderUuids", required = false) List orderUuids) { try { List slots; if (orderUuids == null || orderUuids.isEmpty()) { - slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST); + slots = + serviceType == null ? ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST) : + ipdScheduleService.getMedicationSlots(patientUuid, serviceType); } else { - slots = ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, orderUuids); + slots = + serviceType == null ? ipdScheduleService.getMedicationSlots(patientUuid, MEDICATION_REQUEST, orderUuids) : + ipdScheduleService.getMedicationSlots(patientUuid, serviceType, orderUuids); } List medicationResponses = slots.stream() .map(MedicationSlotResponse::createFrom) diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java index d9a9753..4f63c5b 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/SlotFactory.java @@ -12,6 +12,7 @@ import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.module.ipd.api.util.DateTimeUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -66,4 +67,25 @@ public Slot getSlotFromUUID(String uuid){ return slotService.getSlotByUUID(uuid); } + public Slot createAsNeededPlaceholderSlot(Schedule savedSchedule, Order drugOrder, String comments) { + Slot slot = new Slot(); + + String patientUuid = savedSchedule.getSubject().getTargetUuid(); + Patient patient = patientService.getPatientByUuid(patientUuid); + BedDetails bedAssignmentDetailsByPatient = bedManagementService.getBedAssignmentDetailsByPatient(patient); + if(bedAssignmentDetailsByPatient != null){ + slot.setLocation(bedAssignmentDetailsByPatient.getPhysicalLocation()); + } + + Concept medicationRequestServiceType = conceptService.getConceptByName(ServiceType.AS_NEEDED_PLACEHOLDER.conceptName()); + slot.setServiceType(medicationRequestServiceType); + + slot.setOrder(drugOrder); + slot.setSchedule(savedSchedule); + slot.setStartDateTime(DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate())); + slot.setEndDateTime(DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate())); + slot.setStatus(Slot.SlotStatus.SCHEDULED); + slot.setNotes(comments); + return slot; + } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index 72e9548..11861d2 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -69,13 +69,19 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat savedSchedule = scheduleService.saveSchedule(schedule); } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); - List existingSlots = getMedicationSlots(patient.getUuid(),ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{order.getUuid()}))); - if (existingSlots !=null && !existingSlots.isEmpty()) { - throw new RuntimeException("Slots already created for this drug order"); + if(scheduleMedicationRequest.getServiceType().equals(ServiceType.MEDICATION_REQUEST)){ + List existingSlots = getMedicationSlots(patient.getUuid(),ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{order.getUuid()}))); + if (existingSlots !=null && !existingSlots.isEmpty()) { + throw new RuntimeException("Slots already created for this drug order"); + } + List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); + slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) + .forEach(slotService::saveSlot); + } + else if (scheduleMedicationRequest.getServiceType().equals(ServiceType.AS_NEEDED_PLACEHOLDER)){ + Slot slot = slotFactory.createAsNeededPlaceholderSlot(savedSchedule, order, scheduleMedicationRequest.getComments()); + slotService.saveSlot(slot); } - List slotsStartTime = slotTimeCreationService.createSlotsStartTimeFrom(scheduleMedicationRequest, order); - slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) - .forEach(slotService::saveSlot); return savedSchedule; } From 0a22ff66029452cb6eac93db67aa0a9f5dd033e6 Mon Sep 17 00:00:00 2001 From: Abinaya U Date: Wed, 7 Feb 2024 11:22:48 +0530 Subject: [PATCH 26/75] update. modify imports to have static imports --- .../ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index 2533d5e..ed768bf 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -3,7 +3,11 @@ import org.hibernate.SessionFactory; import org.junit.Test; import org.junit.jupiter.api.Assertions; -import org.openmrs.*; +import org.openmrs.Concept; +import org.openmrs.DrugOrder; +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.VisitType; import org.openmrs.api.context.Context; import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; import org.openmrs.module.ipd.api.BaseIntegrationTest; From d46a8357a494bd4243233446f7aa8a03c5e90ae6 Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Wed, 7 Feb 2024 13:34:13 +0530 Subject: [PATCH 27/75] pendingSlotsAvailable Key added to know whether any pending slots is available for drug Order --- .../openmrs/module/ipd/contract/DrugOrderScheduleResponse.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index 329b3af..bd59952 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.contract; import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.model.DrugOrderSchedule; import java.util.List; @@ -16,6 +17,7 @@ public class DrugOrderScheduleResponse { private List remainingDaySlotsStartTime; private Long slotStartTime; private Boolean medicationAdministrationStarted; + private Boolean pendingSlotsAvailable; private String notes; public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSchedule){ @@ -25,6 +27,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). + pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getStatus().equals(Slot.SlotStatus.SCHEDULED))). notes(drugOrderSchedule.getSlots().get(0).getNotes()). build(); } From 0caa4a84b1bf613dece3ef70550a42f64a1e0e53 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:32:40 +0530 Subject: [PATCH 28/75] condition added to check if slotstart time is after current time (#27) --- .../openmrs/module/ipd/contract/DrugOrderScheduleResponse.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index bd59952..75c8022 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -4,6 +4,7 @@ import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.model.DrugOrderSchedule; +import java.time.LocalDateTime; import java.util.List; @Getter @@ -27,7 +28,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). - pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getStatus().equals(Slot.SlotStatus.SCHEDULED))). + pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> (LocalDateTime.now().isAfter(slot.getStartDateTime()) && slot.getStatus().equals(Slot.SlotStatus.SCHEDULED)))). notes(drugOrderSchedule.getSlots().get(0).getNotes()). build(); } From c980030256f38ba12c45a7ffae1c31a9ebf8fe2d Mon Sep 17 00:00:00 2001 From: srinithishg Date: Wed, 7 Feb 2024 18:03:26 +0530 Subject: [PATCH 29/75] [Sri/kalai] - get the pending slots after the current time in drug order schedule response --- .../openmrs/module/ipd/contract/DrugOrderScheduleResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index 75c8022..1cb8e46 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -28,7 +28,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). - pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> (LocalDateTime.now().isAfter(slot.getStartDateTime()) && slot.getStatus().equals(Slot.SlotStatus.SCHEDULED)))). + pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> (LocalDateTime.now().isBefore(slot.getStartDateTime()) && slot.getStatus().equals(Slot.SlotStatus.SCHEDULED)))). notes(drugOrderSchedule.getSlots().get(0).getNotes()). build(); } From 4c48c41752bee5b9fdd69e4d0e6c6ebe06b96137 Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Thu, 8 Feb 2024 17:42:47 +0530 Subject: [PATCH 30/75] Change to consider MedicationRequest as a default serviceType if is not sent in payload --- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index f35f0ff..a0b7140 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -69,7 +69,8 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat savedSchedule = scheduleService.saveSchedule(schedule); } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); - if(scheduleMedicationRequest.getServiceType().equals(ServiceType.MEDICATION_REQUEST)){ + ServiceType serviceType = scheduleMedicationRequest.getServiceType() !=null ? scheduleMedicationRequest.getServiceType() : ServiceType.MEDICATION_REQUEST; + if(serviceType.equals(ServiceType.MEDICATION_REQUEST)){ List existingSlots = getMedicationSlots(patient.getUuid(),ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{order.getUuid()}))); if (existingSlots !=null && !existingSlots.isEmpty()) { throw new RuntimeException("Slots already created for this drug order"); @@ -78,7 +79,7 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) .forEach(slotService::saveSlot); } - else if (scheduleMedicationRequest.getServiceType().equals(ServiceType.AS_NEEDED_PLACEHOLDER)){ + else if (serviceType.equals(ServiceType.AS_NEEDED_PLACEHOLDER)){ Slot slot = slotFactory.createAsNeededPlaceholderSlot(savedSchedule, order, scheduleMedicationRequest.getComments()); slotService.saveSlot(slot); } From 923828b1fe2c21cd8ad7c528c868f3bf399cac18 Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Thu, 8 Feb 2024 17:57:33 +0530 Subject: [PATCH 31/75] MAde Visit UUid as non-mandatory Param, if visit is not send consider Active Visit of the patient --- .../openmrs/module/ipd/controller/IPDScheduleController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 44b906c..153698a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -81,14 +81,15 @@ public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedi @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime, - @RequestParam(value = "visitUuid") String visitUuid, + @RequestParam(value = "visitUuid",required = false) String visitUuid, @RequestParam(value = "view", required = false) String view) { try { ; if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); - Visit visit = visitService.getVisitByUuid(visitUuid); + Patient patient=patientService.getPatientByUuid(patientUuid); + Visit visit = visitUuid !=null ? visitService.getVisitByUuid(visitUuid) : visitService.getActiveVisitsByPatient(patient).get(0); List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime, visit); return new ResponseEntity<>(constructResponse(slots, visit), OK); } From 80ad1b3ff84f96b03373f3881a116d2fefce452a Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Thu, 8 Feb 2024 18:19:17 +0530 Subject: [PATCH 32/75] Change to consider MedicationRequest as a default serviceType if is not sent in payload (#29) * Change to consider MedicationRequest as a default serviceType if is not sent in payload * MAde Visit UUid as non-mandatory Param, if visit is not send consider Active Visit of the patient --- .../openmrs/module/ipd/controller/IPDScheduleController.java | 5 +++-- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 44b906c..153698a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -81,14 +81,15 @@ public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedi @ResponseBody public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid, @RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime, - @RequestParam(value = "visitUuid") String visitUuid, + @RequestParam(value = "visitUuid",required = false) String visitUuid, @RequestParam(value = "view", required = false) String view) { try { ; if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view); - Visit visit = visitService.getVisitByUuid(visitUuid); + Patient patient=patientService.getPatientByUuid(patientUuid); + Visit visit = visitUuid !=null ? visitService.getVisitByUuid(visitUuid) : visitService.getActiveVisitsByPatient(patient).get(0); List slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime, visit); return new ResponseEntity<>(constructResponse(slots, visit), OK); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index f35f0ff..a0b7140 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -69,7 +69,8 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat savedSchedule = scheduleService.saveSchedule(schedule); } DrugOrder order = (DrugOrder) orderService.getOrderByUuid(scheduleMedicationRequest.getOrderUuid()); - if(scheduleMedicationRequest.getServiceType().equals(ServiceType.MEDICATION_REQUEST)){ + ServiceType serviceType = scheduleMedicationRequest.getServiceType() !=null ? scheduleMedicationRequest.getServiceType() : ServiceType.MEDICATION_REQUEST; + if(serviceType.equals(ServiceType.MEDICATION_REQUEST)){ List existingSlots = getMedicationSlots(patient.getUuid(),ServiceType.MEDICATION_REQUEST,new ArrayList<>(Arrays.asList(new String[]{order.getUuid()}))); if (existingSlots !=null && !existingSlots.isEmpty()) { throw new RuntimeException("Slots already created for this drug order"); @@ -78,7 +79,7 @@ public Schedule saveMedicationSchedule(ScheduleMedicationRequest scheduleMedicat slotFactory.createSlotsForMedicationFrom(savedSchedule, slotsStartTime, order, null, SCHEDULED, ServiceType.MEDICATION_REQUEST, scheduleMedicationRequest.getComments()) .forEach(slotService::saveSlot); } - else if (scheduleMedicationRequest.getServiceType().equals(ServiceType.AS_NEEDED_PLACEHOLDER)){ + else if (serviceType.equals(ServiceType.AS_NEEDED_PLACEHOLDER)){ Slot slot = slotFactory.createAsNeededPlaceholderSlot(savedSchedule, order, scheduleMedicationRequest.getComments()); slotService.saveSlot(slot); } From 4a61a4eb3cdafcd1b66083b90ec859d9950e4734 Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Fri, 9 Feb 2024 12:41:06 +0530 Subject: [PATCH 33/75] Backend changed to accomodate prn slots --- .../ipd/service/impl/IPDVisitServiceImpl.java | 5 ++ .../service/impl/SlotTimeCreationService.java | 55 ++++++++++--------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java index d765303..e14f1ec 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDVisitServiceImpl.java @@ -105,9 +105,14 @@ private Map getDrugOrderScheduleForOrders(String pati .map(BahmniDrugOrder::getUuid) .collect(Collectors.toList()); List slots = ipdScheduleService.getMedicationSlots(patientUuid, ServiceType.MEDICATION_REQUEST,orderUuids); + List prnSlots = ipdScheduleService.getMedicationSlots(patientUuid, ServiceType.AS_NEEDED_MEDICATION_REQUEST,orderUuids); + slots.addAll(prnSlots); Map> groupedByOrders = slots.stream() .collect(Collectors.groupingBy(slot -> (DrugOrder) slot.getOrder())); + Map drugOrderScheduleByOrders = slotTimeCreationService.getDrugOrderScheduledTime(groupedByOrders); + + return drugOrderScheduleByOrders; } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index 56e66da..09c7ffa 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -104,33 +104,34 @@ private List getSlotsStartTimeWithStartTimeDurationFrequency(Sche public HashMap getDrugOrderScheduledTime(Map> slotsByOrder){ HashMap drugOrderScheduleHash= new HashMap<>(); for (DrugOrder drugOrder : slotsByOrder.keySet()) { - Double frequencyPerDay = drugOrder.getFrequency().getFrequencyPerDay(); - String frequency=drugOrder.getFrequency().getName(); - Map> groupedByDateAndEpoch = slotsByOrder.get(drugOrder).stream() - .collect(Collectors.groupingBy( - obj -> obj.getStartDateTime().toLocalDate(), - Collectors.mapping( - obj -> obj.getStartDateTime(), - Collectors.toList() - ) - )); - - List> sortedList = groupedByDateAndEpoch.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) // Sort by LocalDate in ascending order - .map(Map.Entry::getValue) // Get the list of Longs for each entry - .collect(Collectors.toList()); // Collect the list of lists into a single ArrayList - - DrugOrderSchedule drugOrderSchedule=new DrugOrderSchedule(); - if (START_TIME_FREQUENCIES.contains(frequency)){ - drugOrderSchedule.setSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc(sortedList.get(0).get(0))); - } - else if (sortedList.get(0).size() == frequencyPerDay || (sortedList.size() == 1)) { - drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); - } else { - drugOrderSchedule.setFirstDaySlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); - drugOrderSchedule.setRemainingDaySlotsStartTime(sortedList.get(sortedList.size() - 1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); - if (sortedList.size() > 2) { - drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + DrugOrderSchedule drugOrderSchedule = new DrugOrderSchedule(); + if (!drugOrder.getAsNeeded()) { + Double frequencyPerDay = drugOrder.getFrequency().getFrequencyPerDay(); + String frequency = drugOrder.getFrequency().getName(); + Map> groupedByDateAndEpoch = slotsByOrder.get(drugOrder).stream() + .collect(Collectors.groupingBy( + obj -> obj.getStartDateTime().toLocalDate(), + Collectors.mapping( + obj -> obj.getStartDateTime(), + Collectors.toList() + ) + )); + + List> sortedList = groupedByDateAndEpoch.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) // Sort by LocalDate in ascending order + .map(Map.Entry::getValue) // Get the list of Longs for each entry + .collect(Collectors.toList()); // Collect the list of lists into a single ArrayList + + if (START_TIME_FREQUENCIES.contains(frequency)) { + drugOrderSchedule.setSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc(sortedList.get(0).get(0))); + } else if (sortedList.get(0).size() == frequencyPerDay || (sortedList.size() == 1)) { + drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + } else { + drugOrderSchedule.setFirstDaySlotsStartTime(sortedList.get(0).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + drugOrderSchedule.setRemainingDaySlotsStartTime(sortedList.get(sortedList.size() - 1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + if (sortedList.size() > 2) { + drugOrderSchedule.setDayWiseSlotsStartTime(sortedList.get(1).stream().map(DateTimeUtil::convertLocalDateTimeToUTCEpoc).collect(Collectors.toList())); + } } } drugOrderSchedule.setSlots(slotsByOrder.get(drugOrder)); From f272b842c11bc6785fcd057ab13f63a2c1c92f62 Mon Sep 17 00:00:00 2001 From: Kalaiyarasan Raja Date: Fri, 9 Feb 2024 17:43:25 +0530 Subject: [PATCH 34/75] added First Slot Start time to response in DrugOrderSchedule --- .../module/ipd/service/impl/SlotTimeCreationService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index 09c7ffa..074bf79 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -105,7 +105,10 @@ private List getSlotsStartTimeWithStartTimeDurationFrequency(Sche HashMap drugOrderScheduleHash= new HashMap<>(); for (DrugOrder drugOrder : slotsByOrder.keySet()) { DrugOrderSchedule drugOrderSchedule = new DrugOrderSchedule(); - if (!drugOrder.getAsNeeded()) { + if (drugOrder.getAsNeeded()){ + drugOrderSchedule.setSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc(slotsByOrder.get(drugOrder).get(0).getStartDateTime())); + } + else { Double frequencyPerDay = drugOrder.getFrequency().getFrequencyPerDay(); String frequency = drugOrder.getFrequency().getName(); Map> groupedByDateAndEpoch = slotsByOrder.get(drugOrder).stream() From 6c419429cd9452dbe7f27926b7fb5b85b883d2ad Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:21:34 +0530 Subject: [PATCH 35/75] Kavitha | add api to fetch slots by patient list with custom includes (#32) --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 6 ++ .../ipd/api/dao/impl/HibernateSlotDAO.java | 80 ++++++++++++++++++ .../module/ipd/api/service/SlotService.java | 7 ++ .../ipd/api/service/impl/SlotServiceImpl.java | 15 ++++ .../impl/HibernateSlotDAOIntegrationTest.java | 53 ++++++++++++ .../api/service/impl/SlotServiceImplTest.java | 52 ++++++++++++ .../resources/scheduleMedicationsTestData.xml | 41 ++++++++++ .../PatientMedicationSummaryResponse.java | 35 ++++++++ .../PrescribedOrderSlotSummaryResponse.java | 36 +++++++++ .../ipd/controller/IPDScheduleController.java | 24 ++++++ .../ipd/model/PatientMedicationSummary.java | 19 +++++ .../ipd/model/PrescribedOrderSlotSummary.java | 20 +++++ .../ipd/service/IPDScheduleService.java | 3 + .../service/impl/IPDScheduleServiceImpl.java | 81 +++++++++++++++++++ 14 files changed, 472 insertions(+) create mode 100644 api/src/test/resources/scheduleMedicationsTestData.xml create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 6966329..71a5837 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.dao; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -32,4 +33,9 @@ public interface SlotDAO { List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); + + List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 62ca526..9a2003f 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -2,6 +2,7 @@ import org.hibernate.query.Query; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; @@ -134,4 +135,83 @@ public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subj return query.getResultList(); } + + @Override + public List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate) { + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT slot FROM Slot slot \n" + + "INNER JOIN slot.schedule.subject reference \n" + + "INNER JOIN slot.schedule.visit visit \n" + + "WHERE (slot.startDateTime BETWEEN :startDate and :endDate) \n" + + "and slot.voided=0 \n" + + "and visit.stopDatetime is NULL \n" + + "and reference.type = 'org.openmrs.Patient' \n" + + "and reference.targetUuid in (:patientUuidList)"); + + query.setParameterList("patientUuidList", patientUuidList); + query.setParameter("startDate", localStartDate); + query.setParameter("endDate", localEndDate); + + return query.getResultList(); + } + + @Override + public List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate) { + String maxDateTimeSubquery = "SELECT s.order, MAX(s.startDateTime) AS maxStartDateTime " + + "FROM Slot s " + + "INNER JOIN s.schedule.subject reference " + + "INNER JOIN s.schedule.visit visit " + + "WHERE s.startDateTime < :startDate " + + "AND s.voided = 0 " + + "AND visit.stopDatetime IS NULL " + + "AND reference.type = 'org.openmrs.Patient' " + + "AND reference.targetUuid IN (:patientUuidList) " + + "GROUP BY s.order"; + + String latestPreviousSlotsQuery = "SELECT slot " + + "FROM Slot slot " + + "INNER JOIN slot.schedule.subject reference " + + "INNER JOIN slot.schedule.visit visit " + + "WHERE slot.startDateTime < :startDate " + + "AND slot.voided = 0 " + + "AND visit.stopDatetime IS NULL " + + "AND reference.type = 'org.openmrs.Patient' " + + "AND reference.targetUuid IN (:patientUuidList) " + + "AND (slot.order, slot.startDateTime) IN " + + "( " + maxDateTimeSubquery + " ) "; + + Query query = sessionFactory.getCurrentSession() + .createQuery(latestPreviousSlotsQuery); + + query.setParameterList("patientUuidList", patientUuidList); + query.setParameter("startDate", localStartDate); + + return query.getResultList(); + } + + @Override + public List getSlotDurationForPatientsByOrder(List orders, List serviceTypes) { + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT \n" + + " slot.order AS order,\n" + + " MIN(slot.startDateTime) AS minStartDateTime,\n" + + " MAX(slot.startDateTime) AS maxStartDateTime\n" + + "FROM\n" + + " Slot slot\n" + + "INNER JOIN\n" + + " slot.schedule.subject reference\n" + + "INNER JOIN\n" + + " slot.schedule.visit visit \n" + + "WHERE\n" + + " slot.voided = 0\n" + + " AND slot.serviceType IN (:serviceTypes)\n" + + " AND visit.stopDatetime is NULL \n" + + " AND slot.order IN (:orders)\n" + + "GROUP BY\n" + + " slot.order"); + + query.setParameterList("orders", orders); + query.setParameterList("serviceTypes", serviceTypes); + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 467b04e..5e62c4e 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -37,4 +38,10 @@ public interface SlotService extends OpenmrsService { List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); + + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); + + List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 4ca8458..266c25a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; import org.openmrs.Visit; @@ -95,4 +96,18 @@ public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference public List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit) { return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate, visit); } + + @Override + public List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate) { + return slotDAO.getSlotsForPatientListByTime(patientUuidList, localStartDate, localEndDate); + } + + @Override + public List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate) { + return slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuidList, localStartDate); + } + + public List getSlotDurationForPatientsByOrder(List orders, List serviceTypes) { + return slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes); + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index df0a0cf..231d5b2 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Assertions; import org.openmrs.Concept; import org.openmrs.DrugOrder; +import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.Visit; import org.openmrs.VisitType; @@ -21,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -428,4 +430,55 @@ public void shouldGetTheSavedSlotsForPatientBySubjectReferenceAndAGivenTimeFrame sessionFactory.getCurrentSession().delete(visit); } + + @Test + public void shouldGetSlotsForPatientListByTime() { + executeDataSet("scheduleMedicationsTestData.xml"); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-28 11:00:00", formatter); + LocalDateTime endTime = LocalDateTime.parse("2024-01-29 11:00:00", formatter); + List patientUuids = new ArrayList<>(); + patientUuids.add("75e04d42-3ca8-11e3-bf2b-0800271c1b75"); + + List slotsForPatientListByTime = slotDAO.getSlotsForPatientListByTime(patientUuids, startTime, endTime); + + Assertions.assertEquals(3, slotsForPatientListByTime.size()); + } + + @Test + public void shouldGetImmediatePreviousSlotsForPatientListByTime() { + executeDataSet("scheduleMedicationsTestData.xml"); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-28 11:00:00", formatter); + List patientUuids = new ArrayList<>(); + patientUuids.add("75e04d42-3ca8-11e3-bf2b-0800271c1b75"); + + List previousSlots = slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + + Assertions.assertEquals(1, previousSlots.size()); + } + + @Test + public void shouldGetSlotDurationForPatientsByOrder() { + executeDataSet("scheduleMedicationsTestData.xml"); + + List orders = new ArrayList<>(); + Order order = Context.getOrderService().getOrderByUuid("6d0ae386-707a-4629-9850-f15206e63ab0"); + orders.add(order); + List serviceTypes = new ArrayList<>(); + serviceTypes.add(Context.getConceptService().getConceptByName("MedicationRequest")); + + List slotsDuration = slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes); + + Assertions.assertEquals(1, slotsDuration.size()); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-27 20:00:00", formatter); + LocalDateTime endTime = LocalDateTime.parse("2024-01-29 08:00:00", formatter); + + Assertions.assertEquals(startTime, slotsDuration.get(0)[1]); + Assertions.assertEquals(endTime, slotsDuration.get(0)[2]); + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index 6542c40..137ca74 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -8,6 +8,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.openmrs.Concept; import org.openmrs.ConceptName; +import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; @@ -137,4 +138,55 @@ public void shouldInvokeGetSlotsBySubjectReferenceAndAdministeredTimeWithGivenTi Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime, visit); } + + @Test + public void shouldInvokeGetSlotsForPatientListByTime() { + List slots = new ArrayList<>(); + LocalDateTime startTime= LocalDateTime.now(); + LocalDateTime endTime = startTime.plusHours(3); + List patientUuids = new ArrayList<>(); + patientUuids.add("patientUuid1"); + patientUuids.add("patientUuid2"); + + Mockito.when(slotDAO.getSlotsForPatientListByTime(patientUuids, startTime, endTime)).thenReturn(slots); + slotService.getSlotsForPatientListByTime(patientUuids, startTime, endTime); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsForPatientListByTime(patientUuids, startTime, endTime); + } + + @Test + public void shouldInvokeGetImmediatePreviousSlotsForPatientListByTime() { + List slots = new ArrayList<>(); + LocalDateTime startTime= LocalDateTime.now(); + List patientUuids = new ArrayList<>(); + patientUuids.add("patientUuid1"); + patientUuids.add("patientUuid2"); + + Mockito.when(slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime)).thenReturn(slots); + slotService.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + + Mockito.verify(slotDAO, Mockito.times(1)).getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + } + + @Test + public void shouldInvokeGetSlotDurationForPatientsByOrder() { + List slotDurationObjects = new ArrayList<>(); + List orders = new ArrayList<>(); + Order order = new Order(); + order.setUuid("orderUuid1"); + orders.add(order); + order = new Order(); + order.setUuid("orderUuid2"); + orders.add(order); + + List serviceTypes = new ArrayList<>(); + Concept concept = new Concept(); + concept.setUuid("serviceType1"); + serviceTypes.add(concept); + + Mockito.when(slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes)).thenReturn(slotDurationObjects); + slotService.getSlotDurationForPatientsByOrder(orders, serviceTypes); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotDurationForPatientsByOrder(orders, serviceTypes); + } } \ No newline at end of file diff --git a/api/src/test/resources/scheduleMedicationsTestData.xml b/api/src/test/resources/scheduleMedicationsTestData.xml new file mode 100644 index 0000000..920b1d3 --- /dev/null +++ b/api/src/test/resources/scheduleMedicationsTestData.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java new file mode 100644 index 0000000..d7b3509 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java @@ -0,0 +1,35 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.model.PatientMedicationSummary; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PatientMedicationSummaryResponse { + + private String patientUuid; + private List prescribedOrderSlots; + private List emergencyMedicationSlots; + + public static PatientMedicationSummaryResponse createFrom(PatientMedicationSummary patientMedicationSummary) { + List prescribedOrderSlots = patientMedicationSummary.getPrescribedOrderSlots() != null + ? patientMedicationSummary.getPrescribedOrderSlots().stream().map(PrescribedOrderSlotSummaryResponse::createFrom).collect(Collectors.toList()) + : null; + List emergencyMedicationSlots = patientMedicationSummary.getEmergencyMedicationSlots() != null + ? patientMedicationSummary.getEmergencyMedicationSlots().stream().map(MedicationSlotResponse::createFrom).collect(Collectors.toList()) + : null; + return PatientMedicationSummaryResponse.builder() + .patientUuid(patientMedicationSummary.getPatientUuid()) + .prescribedOrderSlots(prescribedOrderSlots) + .emergencyMedicationSlots(emergencyMedicationSlots) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java new file mode 100644 index 0000000..bff5a15 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java @@ -0,0 +1,36 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.model.PrescribedOrderSlotSummary; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrescribedOrderSlotSummaryResponse { + + private String orderUuid; + private List currentSlots; + private MedicationSlotResponse previousSlot; + private Long initialSlotStartTime; + private Long finalSlotStartTime; + + public static PrescribedOrderSlotSummaryResponse createFrom(PrescribedOrderSlotSummary prescribedOrderSlotsSummary){ + MedicationSlotResponse previousSlot = prescribedOrderSlotsSummary.getPreviousSlot() != null + ? MedicationSlotResponse.createFrom(prescribedOrderSlotsSummary.getPreviousSlot()) + : null; + return PrescribedOrderSlotSummaryResponse.builder() + .orderUuid(prescribedOrderSlotsSummary.getOrderUuid()) + .currentSlots(prescribedOrderSlotsSummary.getCurrentSlots().stream().map(slot -> MedicationSlotResponse.createFrom(slot)).collect(Collectors.toList())) + .previousSlot(previousSlot) + .initialSlotStartTime(prescribedOrderSlotsSummary.getInitialSlotStartTime()) + .finalSlotStartTime(prescribedOrderSlotsSummary.getFinalSlotStartTime()) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 153698a..d98a1d5 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -13,8 +13,10 @@ import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.module.ipd.contract.MedicationScheduleResponse; import org.openmrs.module.ipd.contract.MedicationSlotResponse; +import org.openmrs.module.ipd.contract.PatientMedicationSummaryResponse; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import org.openmrs.module.ipd.service.IPDScheduleService; import org.openmrs.module.webservices.rest.web.RestConstants; import org.openmrs.module.webservices.rest.web.RestUtil; @@ -126,6 +128,28 @@ public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value } } + @RequestMapping(value = "type/medication/patientsMedicationSummary", method = RequestMethod.GET, params = {"patientUuids", "startTime", "endTime"}) + @ResponseBody + public ResponseEntity getSlotsForPatientsAndTime(@RequestParam(value = "patientUuids") List patientUuidList, + @RequestParam(value = "startTime") Long startTime, + @RequestParam(value = "endTime") Long endTime, + @RequestParam(value = "includePreviousSlot",required = false) Boolean includePreviousSlot, + @RequestParam(value = "includeSlotDuration",required = false) Boolean includeSlotDuration) { + try { + if (startTime != null && endTime != null) { + LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); + LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); + List patientMedicationSummaries = ipdScheduleService.getSlotsForPatientListByTime(patientUuidList, + localStartDate, localEndDate, includePreviousSlot, includeSlotDuration); + return new ResponseEntity<>(patientMedicationSummaries.stream().map(PatientMedicationSummaryResponse::createFrom).collect(Collectors.toList()), OK); + } + throw new Exception(); + } catch (Exception e) { + log.error("Runtime error while fetching patient medication summaries", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + private List constructResponse(List slots, Visit visit) { Schedule schedule = scheduleService.getScheduleByVisit(visit); diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java b/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java new file mode 100644 index 0000000..e9323fd --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java @@ -0,0 +1,19 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PatientMedicationSummary { + + private String patientUuid; + private List prescribedOrderSlots; + private List emergencyMedicationSlots; + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java b/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java new file mode 100644 index 0000000..4592f07 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java @@ -0,0 +1,20 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrescribedOrderSlotSummary { + + private String orderUuid; + private List currentSlots; + private Slot previousSlot; + private Long initialSlotStartTime; + private Long finalSlotStartTime; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 6e60a47..c220b51 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -7,6 +7,7 @@ import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import java.time.LocalDate; import java.time.LocalDateTime; @@ -20,4 +21,6 @@ public interface IPDScheduleService { Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime, Visit visit); void handlePostProcessEncounterTransaction(Encounter encounter, EncounterTransaction encounterTransaction); + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, + LocalDateTime localEndDate, Boolean includePreviousSlot, Boolean includeSlotDuration); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index a0b7140..ecca043 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -18,6 +18,8 @@ import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.factory.ScheduleFactory; import org.openmrs.module.ipd.factory.SlotFactory; +import org.openmrs.module.ipd.model.PrescribedOrderSlotSummary; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import org.openmrs.module.ipd.service.IPDScheduleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -144,6 +146,85 @@ public void handlePostProcessEncounterTransaction(Encounter encounter, Encounter } } + @Override + public List getSlotsForPatientListByTime(List patientUuidList, + LocalDateTime localStartDate, + LocalDateTime localEndDate, + Boolean includePreviousSlot, + Boolean includeSlotDuration) { + List slots = slotService.getSlotsForPatientListByTime(patientUuidList, localStartDate, localEndDate); + + List previousSlots = null; + if (includePreviousSlot == true) { + previousSlots = slotService.getImmediatePreviousSlotsForPatientListByTime(patientUuidList, localStartDate); + } + + List slotsDuration = null; + if (includeSlotDuration == true) { + List orders = slots.stream() + .map(Slot::getOrder) + .filter(order -> order != null) + .distinct() + .collect(Collectors.toList()); + List serviceTypes = new ArrayList<>(); + serviceTypes.add(Context.getConceptService().getConceptByName(ServiceType.MEDICATION_REQUEST.conceptName())); + serviceTypes.add(Context.getConceptService().getConceptByName(ServiceType.AS_NEEDED_MEDICATION_REQUEST.conceptName())); + + slotsDuration = slotService.getSlotDurationForPatientsByOrder(orders, serviceTypes); + } + + return groupSlotsByMedicationsAndPatients(slots, previousSlots, slotsDuration); + } + + private List groupSlotsByMedicationsAndPatients(List currentSlots, + List previousSlots, + List slotsDuration) { + + Map>> groupedSlots = currentSlots.stream() + .collect(Collectors.groupingBy( + slot -> slot.getSchedule().getSubject().getTargetUuid(), + Collectors.groupingBy( + slot -> slot.getOrder() != null ? slot.getOrder().getUuid() : "emergencyMedications" + ) + )); + + List patientMedicationsList = groupedSlots.entrySet().stream() + .map(entry -> { + PatientMedicationSummary patientMedicationSummary = new PatientMedicationSummary(); + patientMedicationSummary.setPatientUuid(entry.getKey()); + List prescribedOrderSlotsSummaryList = entry.getValue().entrySet().stream() + .filter(subEntry -> subEntry.getKey() != null) + .map(subEntry -> { + PrescribedOrderSlotSummary prescribedOrderSlotSummary = new PrescribedOrderSlotSummary(); + prescribedOrderSlotSummary.setOrderUuid(subEntry.getKey()); + prescribedOrderSlotSummary.setCurrentSlots(subEntry.getValue()); + if (previousSlots != null) { + prescribedOrderSlotSummary.setPreviousSlot(previousSlots.stream() + .filter(slot -> slot.getOrder().getUuid().equals(subEntry.getKey())) + .findFirst() + .orElse(null)); + } + if (slotsDuration != null) { + Object[] durationObj = slotsDuration.stream() + .filter(item -> ((Order) item[0]).getUuid().equals(subEntry.getKey())) + .findFirst() + .orElse(null); + prescribedOrderSlotSummary.setInitialSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc((LocalDateTime) durationObj[1])); + prescribedOrderSlotSummary.setFinalSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc((LocalDateTime) durationObj[2])); + } + return prescribedOrderSlotSummary; + }) + .collect(Collectors.toList()); + patientMedicationSummary.setPrescribedOrderSlots(prescribedOrderSlotsSummaryList); + patientMedicationSummary.setEmergencyMedicationSlots(entry.getValue().get("emergencyMedications")); + + return patientMedicationSummary; + }) + .collect(Collectors.toList()); + + return patientMedicationsList; + } + private void handleDrugOrderStop(EncounterTransaction encounterTransaction){ List stoppedDrugOrders = encounterTransaction.getDrugOrders().stream().filter(drugOrder -> drugOrder.getDateStopped() !=null).collect(Collectors.toList()); String patientUuid = encounterTransaction.getPatientUuid(); From a20a5809b1829fef239265793c2d6b278c482808 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:53:38 +0530 Subject: [PATCH 36/75] Ward Level DashBoard API Changes (#30) * Ward Level DashBoard API Changes --- api/pom.xml | 5 ++ .../openmrs/module/ipd/api/dao/WardDAO.java | 15 ++++ .../ipd/api/dao/impl/HibernateWardDAO.java | 76 +++++++++++++++++++ .../module/ipd/api/model/AdmittedPatient.java | 30 ++++++++ .../ipd/api/model/IPDWardPatientDetails.java | 17 +++++ .../ipd/api/model/WardPatientsSummary.java | 18 +++++ .../module/ipd/api/service/WardService.java | 12 +++ .../ipd/api/service/impl/WardServiceImpl.java | 55 ++++++++++++++ .../impl/HibernateWardDAOIntegrationTest.java | 26 +++++++ .../ipd/contract/AdmittedPatientResponse.java | 25 ++++++ .../IPDWardPatientDetailsResponse.java | 24 ++++++ .../IPDWardPatientSummaryResponse.java | 21 +++++ .../module/ipd/contract/IPDWardResponse.java | 25 ++++++ .../ipd/controller/IPDWardController.java | 53 +++++++++++++ .../module/ipd/service/IPDWardService.java | 13 ++++ .../ipd/service/impl/IPDWardServiceImpl.java | 33 ++++++++ 16 files changed, 448 insertions(+) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java diff --git a/api/pom.xml b/api/pom.xml index 7dfdbee..f119a5e 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -111,6 +111,11 @@ lombok provided + + org.openmrs.module + bedmanagement-api + provided + org.openmrs.web openmrs-web diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java new file mode 100644 index 0000000..aaa297f --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -0,0 +1,15 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.Location; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +import java.util.List; + +public interface WardDAO { + + List getAdmittedPatients(Location location); + + WardPatientsSummary getWardPatientSummary(Location location); + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java new file mode 100644 index 0000000..44e3c27 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -0,0 +1,76 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.openmrs.Location; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import org.hibernate.query.Query; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class HibernateWardDAO implements WardDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateWardDAO.class); + + private final SessionFactory sessionFactory; + + @Autowired + public HibernateWardDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public List getAdmittedPatients(Location location) { + Session session = this.sessionFactory.getCurrentSession(); + try { + Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + + "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId)))" + + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + + "JOIN org.openmrs.Encounter e on e.visit = v " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l on locmap.location = l " + + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + + "LEFT JOIN Slot s on s.order = o " + + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location " + + "GROUP BY assignment.patient, v " + + "ORDER BY assignment.startDatetime desc"); + + query.setParameter("location", location); + return query.getResultList(); + } + catch (Exception ex){ + log.error("Exception at WardDAO getAdmittedPatients ",ex.getStackTrace()); + } + return new ArrayList<>(); + } + + @Override + public WardPatientsSummary getWardPatientSummary(Location location) { + Session session = this.sessionFactory.getCurrentSession(); + try { + Query query = session.createQuery( + "select NEW org.openmrs.module.ipd.api.model.WardPatientsSummary(COUNT(assignment)) " + + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l on locmap.location = l " + + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location"); + query.setParameter("location", location); + return (WardPatientsSummary) query.getSingleResult(); + } catch (Exception e) { + log.error("Exception at WardDAO getAdmittedPatients ",e.getStackTrace()); + } + return new WardPatientsSummary(); + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java new file mode 100644 index 0000000..760d461 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java @@ -0,0 +1,30 @@ +package org.openmrs.module.ipd.api.model; + +import org.openmrs.module.bedmanagement.entity.BedPatientAssignment; + +public class AdmittedPatient extends BedPatientAssignment { + + private Long newTreatments; + + public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments){ + super.setId(bedPatientAssignment.getId()); + super.setBed(bedPatientAssignment.getBed()); + super.setPatient(bedPatientAssignment.getPatient()); + super.setEncounter(bedPatientAssignment.getEncounter()); + super.setStartDatetime(bedPatientAssignment.getStartDatetime()); + super.setEndDatetime(bedPatientAssignment.getEndDatetime()); + super.setUuid(bedPatientAssignment.getUuid()); + super.setVoided(bedPatientAssignment.getVoided()); + super.setVoidReason(bedPatientAssignment.getVoidReason()); + this.newTreatments=newTreatments; + } + + public void setNewTreatments(Long newTreatments) { + this.newTreatments = newTreatments; + } + + public Long getNewTreatments() { + return newTreatments; + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java new file mode 100644 index 0000000..63f4a52 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java @@ -0,0 +1,17 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class IPDWardPatientDetails { + + private List activePatients; + private WardPatientsSummary ipdWardWardPatientsSummary; + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java new file mode 100644 index 0000000..ccccf6b --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java @@ -0,0 +1,18 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Getter +public class WardPatientsSummary { + private Long totalPatients = 0L; + + // to be added in future +// private Integer myPatients; +// private Integer toBeDischargedPatients; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java new file mode 100644 index 0000000..c5faff9 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -0,0 +1,12 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + + +public interface WardService { + + WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + + IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit); +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java new file mode 100644 index 0000000..a1d8743 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -0,0 +1,55 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.openmrs.Location; +import org.openmrs.api.LocationService; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.openmrs.module.ipd.api.service.WardService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional +public class WardServiceImpl implements WardService { + + private final WardDAO wardDAO; + + @Autowired + public WardServiceImpl(WardDAO wardDAO) { + this.wardDAO = wardDAO; + } + + + @Override + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { + Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); + return wardDAO.getWardPatientSummary(location); + } + + @Override + public IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit) { + Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); + List activePatients= wardDAO.getAdmittedPatients(location); + if (activePatients==null){ + return new IPDWardPatientDetails(new ArrayList<>(),new WardPatientsSummary()); + } + offset = Math.min(offset, activePatients.size()); + limit = Math.min(limit, activePatients.size() - offset); + + WardPatientsSummary wardPatientsSummary = computePatientStats(activePatients); + return new IPDWardPatientDetails(activePatients.subList(offset, offset + limit), wardPatientsSummary); + } + + private WardPatientsSummary computePatientStats(List activePatients){ + WardPatientsSummary wardPatientsSummary =new WardPatientsSummary(); + wardPatientsSummary.setTotalPatients(activePatients !=null ? activePatients.size() : 0L); + return wardPatientsSummary; + } +} diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java new file mode 100644 index 0000000..58d810e --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -0,0 +1,26 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private WardDAO wardDAO; + + @Autowired + private SessionFactory sessionFactory; + + + @Test + public void shouldGetAdmittedPatients() { + List assignments= wardDAO.getAdmittedPatients(null); + + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java new file mode 100644 index 0000000..d1b927b --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +@Getter +@Setter +@Builder +public class AdmittedPatientResponse { + + private Object patientDetails; + private Object bedDetails; + private Long newTreatments; + + public static AdmittedPatientResponse createFrom(AdmittedPatient admittedPatient) { + return AdmittedPatientResponse.builder(). + patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getPatient(), Representation.DEFAULT)). + bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBed(),Representation.REF)). + newTreatments(admittedPatient.getNewTreatments()).build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java new file mode 100644 index 0000000..10e8f33 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java @@ -0,0 +1,24 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +public class IPDWardPatientDetailsResponse { + + private List admittedPatients; + private Long totalPatients; + + + public static IPDWardPatientDetailsResponse createFrom(IPDWardPatientDetails ipdWardPatientDetails) { + return IPDWardPatientDetailsResponse.builder(). + admittedPatients(ipdWardPatientDetails.getActivePatients().stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList())). + totalPatients(ipdWardPatientDetails.getIpdWardWardPatientsSummary().getTotalPatients()). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java new file mode 100644 index 0000000..71c342a --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java @@ -0,0 +1,21 @@ +package org.openmrs.module.ipd.contract; + + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +@Getter +@Setter +@Builder +public class IPDWardPatientSummaryResponse { + + private Long totalPatients; + + public static IPDWardPatientSummaryResponse createFrom(WardPatientsSummary wardPatientsSummary){ + return IPDWardPatientSummaryResponse.builder(). + totalPatients(wardPatientsSummary.getTotalPatients()). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java new file mode 100644 index 0000000..e82967e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.Location; +import org.openmrs.module.bedmanagement.AdmissionLocation; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class IPDWardResponse { + private String uuid; + private String name; + + public static IPDWardResponse createFrom (AdmissionLocation admissionLocation){ + return IPDWardResponse.builder(). + uuid(admissionLocation.getWard().getUuid()). + name(admissionLocation.getWard().getName()). + build(); + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java new file mode 100644 index 0000000..c177e56 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -0,0 +1,53 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.api.model.*; +import org.openmrs.module.ipd.contract.*; +import org.openmrs.module.ipd.service.IPDWardService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd/wards") +@Slf4j +public class IPDWardController extends BaseRestController { + + private IPDWardService ipdWardService; + + @Autowired + public IPDWardController(IPDWardService ipdWardService) { + this.ipdWardService = ipdWardService; + } + + @RequestMapping(value = "{wardUuid}/summary",method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") String wardUuid) throws ParseException { + WardPatientsSummary wardPatientsSummary = ipdWardService.getIPDWardPatientSummary(wardUuid); + return new ResponseEntity<>(IPDWardPatientSummaryResponse.createFrom(wardPatientsSummary), OK); + } + + @RequestMapping(value = "{wardUuid}/patients", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String wardUuid, + @RequestParam(value = "offset") Integer offset, + @RequestParam (value = "limit") Integer limit) throws ParseException { + try { + IPDWardPatientDetails wardPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); + return new ResponseEntity<>(IPDWardPatientDetailsResponse.createFrom(wardPatientDetails), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java new file mode 100644 index 0000000..346307c --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -0,0 +1,13 @@ +package org.openmrs.module.ipd.service; + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +public interface IPDWardService { + + WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + + IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit); + + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java new file mode 100644 index 0000000..2b10a5e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -0,0 +1,33 @@ +package org.openmrs.module.ipd.service.impl; + + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.openmrs.module.ipd.api.service.WardService; +import org.openmrs.module.ipd.service.IPDWardService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class IPDWardServiceImpl implements IPDWardService { + + private final WardService wardService; + + @Autowired + public IPDWardServiceImpl(WardService wardService) { + this.wardService = wardService; + } + + + @Override + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { + return wardService.getIPDWardPatientSummary(wardUuid); + } + + @Override + public IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit) { + return wardService.getWardPatientsByUuid(wardUuid,offset,limit); + } +} From ab4e348052a8789097e77abb71f996948e8b7025 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:59:43 +0530 Subject: [PATCH 37/75] Kavitha | add null check to get slots for list of patients (#34) --- .../module/ipd/service/impl/IPDScheduleServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index ecca043..89fefc9 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -155,12 +155,12 @@ public List getSlotsForPatientListByTime(List List slots = slotService.getSlotsForPatientListByTime(patientUuidList, localStartDate, localEndDate); List previousSlots = null; - if (includePreviousSlot == true) { + if (Boolean.TRUE.equals(includePreviousSlot)) { previousSlots = slotService.getImmediatePreviousSlotsForPatientListByTime(patientUuidList, localStartDate); } List slotsDuration = null; - if (includeSlotDuration == true) { + if (Boolean.TRUE.equals(includeSlotDuration)) { List orders = slots.stream() .map(Slot::getOrder) .filter(order -> order != null) From b7d950789a24d42045194af735150863ebbec88b Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:34:24 +0530 Subject: [PATCH 38/75] Search functionality API added & Refactor get patients API (#33) --- .../openmrs/module/ipd/api/dao/WardDAO.java | 4 +- .../ipd/api/dao/impl/HibernateWardDAO.java | 92 ++++++++- .../module/ipd/api/model/AdmittedPatient.java | 17 +- .../module/ipd/api/service/WardService.java | 9 +- .../ipd/api/service/impl/WardServiceImpl.java | 22 +-- .../impl/HibernateWardDAOIntegrationTest.java | 12 +- api/src/test/resources/WardDAOTestData.xml | 181 ++++++++++++++++++ .../ipd/contract/AdmittedPatientResponse.java | 4 +- .../ipd/controller/IPDWardController.java | 22 ++- .../module/ipd/service/IPDWardService.java | 9 +- .../ipd/service/impl/IPDWardServiceImpl.java | 11 +- 11 files changed, 342 insertions(+), 41 deletions(-) create mode 100644 api/src/test/resources/WardDAOTestData.xml diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index aaa297f..d5cb409 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -8,7 +8,9 @@ public interface WardDAO { - List getAdmittedPatients(Location location); + List searchAdmittedPatients(Location location,List searchKeys,String searchValue,Integer offset,Integer limit); + + List getAdmittedPatientsByLocation(Location location,Integer offset,Integer limit); WardPatientsSummary getWardPatientSummary(Location location); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 44e3c27..fa2f493 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -29,7 +29,7 @@ public HibernateWardDAO(SessionFactory sessionFactory) { } @Override - public List getAdmittedPatients(Location location) { + public List getAdmittedPatientsByLocation(Location location,Integer offset,Integer limit) { Session session = this.sessionFactory.getCurrentSession(); try { Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + @@ -46,6 +46,7 @@ public List getAdmittedPatients(Location location) { "ORDER BY assignment.startDatetime desc"); query.setParameter("location", location); + query.setFirstResult(offset).setMaxResults(limit); return query.getResultList(); } catch (Exception ex){ @@ -73,4 +74,93 @@ public WardPatientsSummary getWardPatientSummary(Location location) { return new WardPatientsSummary(); } + @Override + public List searchAdmittedPatients(Location location, List searchKeys, String searchValue,Integer offset,Integer limit) { + try { + Session session = sessionFactory.getCurrentSession(); + + String selectQuery = "select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + + "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId))) " + + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + + "JOIN org.openmrs.Patient p on assignment.patient = p " + + "JOIN org.openmrs.Person pr on pr.personId=p.patientId " + + "JOIN org.openmrs.Encounter e on e.visit = v " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l on locmap.location = l " + + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + + "LEFT JOIN Slot s on s.order = o "; + + // Construct additional joins and where clause based on search keys + StringBuilder additionalJoins = new StringBuilder(""); + StringBuilder whereClause = new StringBuilder(""); + generateSQLSearchConditions(searchKeys,additionalJoins,whereClause); + + // Construct group by clause + String groupBy = " GROUP BY assignment.patient, v ORDER BY assignment.startDatetime desc "; + + // Create query + Query query = session.createQuery(selectQuery + additionalJoins + whereClause + groupBy); + + // Set parameters + query.setParameter("location", location); + setQueryParameters(query, searchKeys, searchValue); + query.setFirstResult(offset).setMaxResults(limit); + + return query.getResultList(); + } catch (Exception ex) { + log.error("Exception at WardDAO searching ", ex.getMessage()); + return new ArrayList<>(); + } + } + + private void generateSQLSearchConditions(List searchKeys,StringBuilder additionalJoins,StringBuilder whereClause) { + whereClause.append("where (assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location)"); + if (searchKeys != null && !searchKeys.isEmpty()) { + whereClause.append(" and ("); + for (int i = 0; i < searchKeys.size(); i++) { + switch (searchKeys.get(i)) { + case "bedNumber": + whereClause.append(" assignment.bed.bedNumber LIKE :bedNumber "); + break; + case "patientIdentifier": + additionalJoins.append(" JOIN p.identifiers pi "); + whereClause.append(" pi.identifier LIKE :patientIdentifier "); + break; + case "patientName": + additionalJoins.append(" JOIN pr.names prn "); + whereClause.append(" (prn.givenName LIKE :patientName or prn.middleName LIKE :patientName or prn.familyName LIKE :patientName) "); + break; + } + if (i < searchKeys.size() - 1) { + whereClause.append(" or "); + } + } + whereClause.append(" ) "); + } + } + + private void setQueryParameters(Query query, List searchKeys, String searchValue) { + if (searchKeys != null && searchValue != null && !searchValue.isEmpty()) { + if (searchKeys.contains("bedNumber")) { + query.setParameter("bedNumber", "%" + searchValue + "%"); + } + if (searchKeys.contains("patientIdentifier")) { + query.setParameter("patientIdentifier", "%" + searchValue + "%"); + } + if (searchKeys.contains("patientName")) { + query.setParameter("patientName", "%" + searchValue + "%"); + } + } + } + + private StringBuilder appendORIfMoreSearchKeysPresent(int i,int size,StringBuilder whereClause){ + if (size==(i+1)){ + return whereClause; + } + return whereClause.append(" or "); + } + + + } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java index 760d461..234e659 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java @@ -2,25 +2,18 @@ import org.openmrs.module.bedmanagement.entity.BedPatientAssignment; -public class AdmittedPatient extends BedPatientAssignment { +public class AdmittedPatient { + private BedPatientAssignment bedPatientAssignment; private Long newTreatments; public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments){ - super.setId(bedPatientAssignment.getId()); - super.setBed(bedPatientAssignment.getBed()); - super.setPatient(bedPatientAssignment.getPatient()); - super.setEncounter(bedPatientAssignment.getEncounter()); - super.setStartDatetime(bedPatientAssignment.getStartDatetime()); - super.setEndDatetime(bedPatientAssignment.getEndDatetime()); - super.setUuid(bedPatientAssignment.getUuid()); - super.setVoided(bedPatientAssignment.getVoided()); - super.setVoidReason(bedPatientAssignment.getVoidReason()); + this.bedPatientAssignment=bedPatientAssignment; this.newTreatments=newTreatments; } - public void setNewTreatments(Long newTreatments) { - this.newTreatments = newTreatments; + public BedPatientAssignment getBedPatientAssignment() { + return bedPatientAssignment; } public Long getNewTreatments() { diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java index c5faff9..af6da40 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -1,12 +1,17 @@ package org.openmrs.module.ipd.api.service; -import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import java.util.List; + public interface WardService { WardPatientsSummary getIPDWardPatientSummary(String wardUuid); - IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit); + List getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit); + + List searchWardPatients(String wardUuid, List searchKeys,String searchValue, Integer offset, Integer limit); + } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index a1d8743..2c641f6 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -5,7 +5,6 @@ import org.openmrs.api.context.Context; import org.openmrs.module.ipd.api.dao.WardDAO; import org.openmrs.module.ipd.api.model.AdmittedPatient; -import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; import org.openmrs.module.ipd.api.model.WardPatientsSummary; import org.openmrs.module.ipd.api.service.WardService; import org.springframework.beans.factory.annotation.Autowired; @@ -34,22 +33,15 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit) { + public List getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - List activePatients= wardDAO.getAdmittedPatients(location); - if (activePatients==null){ - return new IPDWardPatientDetails(new ArrayList<>(),new WardPatientsSummary()); - } - offset = Math.min(offset, activePatients.size()); - limit = Math.min(limit, activePatients.size() - offset); - - WardPatientsSummary wardPatientsSummary = computePatientStats(activePatients); - return new IPDWardPatientDetails(activePatients.subList(offset, offset + limit), wardPatientsSummary); + return wardDAO.getAdmittedPatientsByLocation(location,offset,limit); } - private WardPatientsSummary computePatientStats(List activePatients){ - WardPatientsSummary wardPatientsSummary =new WardPatientsSummary(); - wardPatientsSummary.setTotalPatients(activePatients !=null ? activePatients.size() : 0L); - return wardPatientsSummary; + @Override + public List searchWardPatients(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit) { + Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); + return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue,offset,limit); } + } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java index 58d810e..6ce6e11 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -2,6 +2,10 @@ import org.hibernate.SessionFactory; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openmrs.Location; +import org.openmrs.api.LocationService; +import org.openmrs.api.context.Context; import org.openmrs.module.ipd.api.BaseIntegrationTest; import org.openmrs.module.ipd.api.dao.WardDAO; import org.openmrs.module.ipd.api.model.AdmittedPatient; @@ -19,8 +23,12 @@ public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { @Test - public void shouldGetAdmittedPatients() { - List assignments= wardDAO.getAdmittedPatients(null); + public void shouldGetAdmittedPatientsByLocation() { + + Location location= Context.getService(LocationService.class).getLocationByUuid("7779d653-393b-4118-9c83-a3715b82d4ac"); + List admittedPatients= wardDAO.getAdmittedPatientsByLocation(location,0,10); + + Assertions.assertEquals(0, admittedPatients.size()); } } diff --git a/api/src/test/resources/WardDAOTestData.xml b/api/src/test/resources/WardDAOTestData.xml new file mode 100644 index 0000000..3688c59 --- /dev/null +++ b/api/src/test/resources/WardDAOTestData.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java index d1b927b..650690e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java @@ -18,8 +18,8 @@ public class AdmittedPatientResponse { public static AdmittedPatientResponse createFrom(AdmittedPatient admittedPatient) { return AdmittedPatientResponse.builder(). - patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getPatient(), Representation.DEFAULT)). - bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBed(),Representation.REF)). + patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getPatient(), Representation.DEFAULT)). + bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getBed(),Representation.REF)). newTreatments(admittedPatient.getNewTreatments()).build(); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index c177e56..94d02c9 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.*; import java.text.ParseException; +import java.util.List; +import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.OK; @@ -42,8 +44,24 @@ public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit) throws ParseException { try { - IPDWardPatientDetails wardPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); - return new ResponseEntity<>(IPDWardPatientDetailsResponse.createFrom(wardPatientDetails), OK); + List admittedPatients = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); + return new ResponseEntity<>(admittedPatients.stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList()), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + + @RequestMapping(value = "{wardUuid}/patients/search", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity searchIPDWardPatient(@PathVariable("wardUuid") String wardUuid, + @RequestParam(value = "offset") Integer offset, + @RequestParam (value = "limit") Integer limit, + @RequestParam(value = "searchKeys") List searchKeys, + @RequestParam(value = "searchValue") String searchValue) throws ParseException { + try { + List admittedPatients = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit); + return new ResponseEntity<>(admittedPatients.stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList()), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 346307c..5f7c7e1 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -1,13 +1,18 @@ package org.openmrs.module.ipd.service; -import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import java.util.List; + public interface IPDWardService { WardPatientsSummary getIPDWardPatientSummary(String wardUuid); - IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit); + List getIPDPatientByWard(String wardUuid, Integer offset, Integer limit); + + List searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue,Integer offset, Integer limit); + } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index 2b10a5e..eb572bf 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -1,7 +1,7 @@ package org.openmrs.module.ipd.service.impl; -import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; import org.openmrs.module.ipd.api.service.WardService; import org.openmrs.module.ipd.service.IPDWardService; @@ -9,6 +9,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @Transactional public class IPDWardServiceImpl implements IPDWardService { @@ -27,7 +29,12 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit) { + public List getIPDPatientByWard(String wardUuid, Integer offset, Integer limit) { return wardService.getWardPatientsByUuid(wardUuid,offset,limit); } + + @Override + public List searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit) { + return wardService.searchWardPatients(wardUuid,searchKeys,searchValue,offset,limit); + } } From dc5230e327029fe38130209f34893320554c43a5 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:52:14 +0530 Subject: [PATCH 39/75] Add boolean key to show if all slots are attended (#35) --- .../openmrs/module/ipd/contract/DrugOrderScheduleResponse.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java index 1cb8e46..e00077f 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/DrugOrderScheduleResponse.java @@ -19,6 +19,7 @@ public class DrugOrderScheduleResponse { private Long slotStartTime; private Boolean medicationAdministrationStarted; private Boolean pendingSlotsAvailable; + private Boolean allSlotsAttended; private String notes; public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSchedule){ @@ -28,6 +29,7 @@ public static DrugOrderScheduleResponse createFrom(DrugOrderSchedule drugOrderSc remainingDaySlotsStartTime(drugOrderSchedule.getRemainingDaySlotsStartTime()). slotStartTime(drugOrderSchedule.getSlotStartTime()). medicationAdministrationStarted(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getMedicationAdministration() != null)). + allSlotsAttended(!(drugOrderSchedule.getSlots().stream().anyMatch(slot -> slot.getStatus().equals(Slot.SlotStatus.SCHEDULED)))). pendingSlotsAvailable(drugOrderSchedule.getSlots().stream().anyMatch(slot -> (LocalDateTime.now().isBefore(slot.getStartDateTime()) && slot.getStatus().equals(Slot.SlotStatus.SCHEDULED)))). notes(drugOrderSchedule.getSlots().get(0).getNotes()). build(); From 1bd9b4d167d435baf55f6a40bc491e942b9dc495 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Thu, 29 Feb 2024 11:38:27 +0530 Subject: [PATCH 40/75] Add totalPatient in Patient List & Search API response --- .../openmrs/module/ipd/api/dao/WardDAO.java | 4 +-- .../ipd/api/dao/impl/HibernateWardDAO.java | 7 ++--- .../module/ipd/api/service/WardService.java | 4 +-- .../ipd/api/service/impl/WardServiceImpl.java | 8 ++--- .../impl/HibernateWardDAOIntegrationTest.java | 2 +- omod/pom.xml | 8 ++++- .../ipd/controller/IPDWardController.java | 9 +++--- .../module/ipd/service/IPDWardService.java | 7 +++-- .../ipd/service/impl/IPDWardServiceImpl.java | 30 ++++++++++++++++--- 9 files changed, 53 insertions(+), 26 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index d5cb409..43d8f15 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -8,9 +8,9 @@ public interface WardDAO { - List searchAdmittedPatients(Location location,List searchKeys,String searchValue,Integer offset,Integer limit); + List searchAdmittedPatients(Location location,List searchKeys,String searchValue); - List getAdmittedPatientsByLocation(Location location,Integer offset,Integer limit); + List getAdmittedPatientsByLocation(Location location); WardPatientsSummary getWardPatientSummary(Location location); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index fa2f493..254da74 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -29,7 +29,7 @@ public HibernateWardDAO(SessionFactory sessionFactory) { } @Override - public List getAdmittedPatientsByLocation(Location location,Integer offset,Integer limit) { + public List getAdmittedPatientsByLocation(Location location) { Session session = this.sessionFactory.getCurrentSession(); try { Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + @@ -46,7 +46,7 @@ public List getAdmittedPatientsByLocation(Location location,Int "ORDER BY assignment.startDatetime desc"); query.setParameter("location", location); - query.setFirstResult(offset).setMaxResults(limit); + return query.getResultList(); } catch (Exception ex){ @@ -75,7 +75,7 @@ public WardPatientsSummary getWardPatientSummary(Location location) { } @Override - public List searchAdmittedPatients(Location location, List searchKeys, String searchValue,Integer offset,Integer limit) { + public List searchAdmittedPatients(Location location, List searchKeys, String searchValue) { try { Session session = sessionFactory.getCurrentSession(); @@ -105,7 +105,6 @@ public List searchAdmittedPatients(Location location, List getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit); + List getWardPatientsByUuid(String wardUuid); - List searchWardPatients(String wardUuid, List searchKeys,String searchValue, Integer offset, Integer limit); + List searchWardPatients(String wardUuid, List searchKeys, String searchValue); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index 2c641f6..ec72ca8 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -33,15 +33,15 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public List getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit) { + public List getWardPatientsByUuid(String wardUuid) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.getAdmittedPatientsByLocation(location,offset,limit); + return wardDAO.getAdmittedPatientsByLocation(location); } @Override - public List searchWardPatients(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit) { + public List searchWardPatients(String wardUuid, List searchKeys, String searchValue) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue,offset,limit); + return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue); } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java index 6ce6e11..4cb29c8 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -26,7 +26,7 @@ public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { public void shouldGetAdmittedPatientsByLocation() { Location location= Context.getService(LocationService.class).getLocationByUuid("7779d653-393b-4118-9c83-a3715b82d4ac"); - List admittedPatients= wardDAO.getAdmittedPatientsByLocation(location,0,10); + List admittedPatients= wardDAO.getAdmittedPatientsByLocation(location); Assertions.assertEquals(0, admittedPatients.size()); diff --git a/omod/pom.xml b/omod/pom.xml index c1c3e96..8895021 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -163,6 +163,12 @@ servlet-api test - + + commons-digester + commons-digester + 2.1 + compile + + \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index 94d02c9..68f3ea3 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -14,7 +14,6 @@ import java.text.ParseException; import java.util.List; -import java.util.stream.Collectors; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.OK; @@ -44,8 +43,8 @@ public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit) throws ParseException { try { - List admittedPatients = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); - return new ResponseEntity<>(admittedPatients.stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList()), OK); + IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); + return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); @@ -60,8 +59,8 @@ public ResponseEntity searchIPDWardPatient(@PathVariable("wardUuid") Str @RequestParam(value = "searchKeys") List searchKeys, @RequestParam(value = "searchValue") String searchValue) throws ParseException { try { - List admittedPatients = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit); - return new ResponseEntity<>(admittedPatients.stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList()), OK); + IPDPatientDetails ipdPatientDetails = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit); + return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 5f7c7e1..44780b4 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.service; -import org.openmrs.module.ipd.api.model.AdmittedPatient; + +import org.openmrs.module.ipd.api.model.IPDPatientDetails; import org.openmrs.module.ipd.api.model.WardPatientsSummary; import java.util.List; @@ -9,9 +10,9 @@ public interface IPDWardService { WardPatientsSummary getIPDWardPatientSummary(String wardUuid); - List getIPDPatientByWard(String wardUuid, Integer offset, Integer limit); + IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit); - List searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue,Integer offset, Integer limit); + IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index eb572bf..8a4d8fa 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -2,6 +2,7 @@ import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.IPDPatientDetails; import org.openmrs.module.ipd.api.model.WardPatientsSummary; import org.openmrs.module.ipd.api.service.WardService; import org.openmrs.module.ipd.service.IPDWardService; @@ -9,6 +10,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; @Service @@ -29,12 +31,32 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public List getIPDPatientByWard(String wardUuid, Integer offset, Integer limit) { - return wardService.getWardPatientsByUuid(wardUuid,offset,limit); + public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit) { + + List admittedPatients = wardService.getWardPatientsByUuid(wardUuid); + + if (admittedPatients ==null ){ + return new IPDPatientDetails(new ArrayList<>(),0); + } + + offset = Math.min(offset, admittedPatients.size()); + limit = Math.min(limit, admittedPatients.size() - offset); + + return new IPDPatientDetails(admittedPatients.subList(offset, offset + limit), admittedPatients.size()); } @Override - public List searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit) { - return wardService.searchWardPatients(wardUuid,searchKeys,searchValue,offset,limit); + public IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, + Integer offset, Integer limit) { + + List admittedPatients = wardService.searchWardPatients(wardUuid,searchKeys,searchValue); + if (admittedPatients ==null ){ + return new IPDPatientDetails(new ArrayList<>(),0); + } + + offset = Math.min(offset, admittedPatients.size()); + limit = Math.min(limit, admittedPatients.size() - offset); + + return new IPDPatientDetails(admittedPatients.subList(offset, offset + limit), admittedPatients.size()); } } From 0f4916bfc9c780b211cffd651d26ce89e362cce1 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Thu, 29 Feb 2024 12:04:52 +0530 Subject: [PATCH 41/75] Add missing classes --- .../ipd/api/model/IPDPatientDetails.java | 17 ++++++++++++++ .../contract/IPDPatientDetailsResponse.java | 23 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/IPDPatientDetails.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/IPDPatientDetailsResponse.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/IPDPatientDetails.java b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDPatientDetails.java new file mode 100644 index 0000000..2805000 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDPatientDetails.java @@ -0,0 +1,17 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class IPDPatientDetails { + + private List admittedPatients; + private Integer patientCount; + +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDPatientDetailsResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDPatientDetailsResponse.java new file mode 100644 index 0000000..eebedfd --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDPatientDetailsResponse.java @@ -0,0 +1,23 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.module.ipd.api.model.IPDPatientDetails; +import java.util.List; +import java.util.stream.Collectors; + +@Builder +@Getter +@Setter +public class IPDPatientDetailsResponse { + private List admittedPatients; + private Integer totalPatients; + + public static IPDPatientDetailsResponse createFrom(IPDPatientDetails ipdPatientDetails) { + return IPDPatientDetailsResponse.builder() + .admittedPatients(ipdPatientDetails.getAdmittedPatients().stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList())) + .totalPatients(ipdPatientDetails.getPatientCount()) + .build(); + } +} From f7352e6ea0c8ce0c1fd2f859e26b58c3fe2a91c5 Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:40:24 +0530 Subject: [PATCH 42/75] Kavitha | refactored slot creation logic for continuous medication (#38) --- .../module/ipd/service/impl/SlotTimeCreationService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index 074bf79..4d25cbb 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -83,9 +83,9 @@ private List getSlotsStartTimeWithFixedScheduleFrequency(Schedule } private List getSlotsStartTimeWithStartTimeDurationFrequency(ScheduleMedicationRequest request, DrugOrder order) { - int numberOfSlotsStartTimeToBeCreated = (int) (Math.ceil(order.getQuantity() / order.getDose())); + int numberOfSlotsStartTimeToBeCreated = (order.getQuantity() == 0.0 || order.getFrequency() == null || order.getDuration() == null) ? 1 : (int) (Math.ceil(order.getQuantity() / order.getDose())); List slotsStartTime = new ArrayList<>(); - Double slotDurationInHours = 24 / order.getFrequency().getFrequencyPerDay(); + Double slotDurationInHours = order.getFrequency() != null ? 24 / order.getFrequency().getFrequencyPerDay() : 0; LocalDateTime slotStartTime = request.getSlotStartTimeAsLocaltime(); while (numberOfSlotsStartTimeToBeCreated-- > 0) { slotsStartTime.add(slotStartTime); @@ -105,7 +105,7 @@ private List getSlotsStartTimeWithStartTimeDurationFrequency(Sche HashMap drugOrderScheduleHash= new HashMap<>(); for (DrugOrder drugOrder : slotsByOrder.keySet()) { DrugOrderSchedule drugOrderSchedule = new DrugOrderSchedule(); - if (drugOrder.getAsNeeded()){ + if (drugOrder.getAsNeeded() || drugOrder.getFrequency() == null || drugOrder.getDuration() == null || drugOrder.getQuantity() == 0.0) { drugOrderSchedule.setSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc(slotsByOrder.get(drugOrder).get(0).getStartDateTime())); } else { From 063bcefcdb11f0c982426f08bfdee957b2951d88 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:50:45 +0530 Subject: [PATCH 43/75] add. scheduler to mark non-administered slots as missed (#39) --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 4 +++ .../ipd/api/dao/impl/HibernateSlotDAO.java | 32 ++++++++++++++++- .../openmrs/module/ipd/api/model/Slot.java | 3 +- .../scheduler/tasks/MarkSlotsAsMissed.java | 36 +++++++++++++++++++ .../module/ipd/api/service/SlotService.java | 8 +++++ .../ipd/api/service/impl/SlotServiceImpl.java | 34 +++++++++++++++--- api/src/main/resources/liquibase.xml | 16 +++++++++ .../resources/moduleApplicationContext.xml | 27 +++++++++++++- .../api/service/impl/SlotServiceImplTest.java | 29 +++++++++++++++ 9 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/MarkSlotsAsMissed.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 71a5837..e28cca8 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -38,4 +38,8 @@ public interface SlotDAO { List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); + + List getLastSlotForAnOrder(LocalDateTime dateTime); + + List getScheduledSlots(List orders); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 9a2003f..845e49a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -10,7 +10,6 @@ import org.hibernate.SessionFactory; import org.openmrs.api.db.DAOException; import org.openmrs.module.ipd.api.util.DateTimeUtil; -import org.openmrs.util.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -18,6 +17,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.List; @Repository @@ -214,4 +214,34 @@ public List getSlotDurationForPatientsByOrder(List orders, List query.setParameterList("serviceTypes", serviceTypes); return query.getResultList(); } + + @Override + public List getLastSlotForAnOrder(LocalDateTime localStartDateTime){ + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT s from Slot s\n" + + "where s.startDateTime IN (SELECT MAX(s1.startDateTime) \n" + + "from Slot s1 WHERE \n" + + "s1.startDateTime>:previousDate \n" + + "and s1.startDateTime<=:currentDate \n" + + "and s1.order IS NOT NULL \n" + + "and s1.order = s.order \n" + + "and s1.voided = 0 \n" + + "GROUP by s1.order \n) " + + "and s.voided = 0 \n" + + "GROUP by s.order"); + + query.setParameter("currentDate", localStartDateTime); + query.setParameter("previousDate", localStartDateTime.minus(1, ChronoUnit.DAYS)); + return query.getResultList(); + } + + @Override + public List getScheduledSlots(List orders){ + Query query = sessionFactory.getCurrentSession() + .createQuery("From Slot slot WHERE slot.order IN (:order) and slot.status=:status and slot.voided=0"); + + query.setParameter("order", orders); + query.setParameter("status", Slot.SlotStatus.SCHEDULED); + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java index d9299fc..4cc0b3a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java @@ -24,7 +24,8 @@ public enum SlotStatus { SCHEDULED, NOT_DONE, COMPLETED, - STOPPED + STOPPED, + MISSED } @EqualsAndHashCode.Include diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/MarkSlotsAsMissed.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/MarkSlotsAsMissed.java new file mode 100644 index 0000000..aae3b05 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/MarkSlotsAsMissed.java @@ -0,0 +1,36 @@ +package org.openmrs.module.ipd.api.scheduler.tasks; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.Order; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.model.Slot; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.scheduler.tasks.AbstractTask; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class MarkSlotsAsMissed extends AbstractTask { + @Override + public void execute() { + + SlotService slotService = Context.getService(SlotService.class); + LocalDateTime currentDateTime = LocalDateTime.now(); + List lastSlotForAnOrder = slotService.getLastSlotForAnOrder(currentDateTime); + List orders = new ArrayList<>(); + Map maxTimeForAnOrder = new HashMap<>(); + if (!lastSlotForAnOrder.isEmpty()) { + lastSlotForAnOrder.stream().forEach(slot -> { + maxTimeForAnOrder.put(slot.getOrder(), slot.getStartDateTime()); + orders.add(slot.getOrder()); + }); + List scheduledSlots = slotService.getScheduledSlots(orders); + slotService.markSlotsAsMissed(scheduledSlots, maxTimeForAnOrder); + } + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 5e62c4e..05856ab 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -12,6 +12,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; +import java.util.Map; @Service public interface SlotService extends OpenmrsService { @@ -44,4 +45,11 @@ public interface SlotService extends OpenmrsService { List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); + + + List getLastSlotForAnOrder(LocalDateTime currentDay); + + List getScheduledSlots(List orders); + + void markSlotsAsMissed(List markSlotStatusAsMissed, Map slotsForADay); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 266c25a..2f94af5 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -2,16 +2,16 @@ import org.openmrs.Concept; import org.openmrs.Order; +import org.openmrs.Visit; +import org.openmrs.api.APIException; import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; -import org.openmrs.Visit; +import org.openmrs.api.impl.BaseOpenmrsService; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.api.service.SlotService; -import org.openmrs.api.APIException; -import org.openmrs.api.impl.BaseOpenmrsService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -19,9 +19,11 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; -import java.util.Date; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Map; @Service @Transactional @@ -110,4 +112,28 @@ public List getImmediatePreviousSlotsForPatientListByTime(List pat public List getSlotDurationForPatientsByOrder(List orders, List serviceTypes) { return slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes); } + @Override + public List getLastSlotForAnOrder(LocalDateTime startDateTime) { + return slotDAO.getLastSlotForAnOrder(startDateTime); + } + + @Override + public List getScheduledSlots(List orders) { + return slotDAO.getScheduledSlots(orders); + } + + @Override + public void markSlotsAsMissed(List scheduledSlots, Map maxTimeForAnOrder) { + List slotsToBeMarkedAsMissed = new ArrayList<>(); + + scheduledSlots.stream().forEach(slot -> { + if (slot.getStartDateTime().compareTo(maxTimeForAnOrder.get(slot.getOrder())) < 0) + slotsToBeMarkedAsMissed.add(slot); + }); + + slotsToBeMarkedAsMissed.forEach(slot -> { + slot.setStatus(Slot.SlotStatus.MISSED); + slotDAO.saveSlot(slot); + }); + } } diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index a38f065..844971f 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -300,4 +300,20 @@ + + + + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Mark Slots As Missed"; + + + + INSERT INTO + scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, + start_on_startup, created_by, date_created, uuid) + VALUES + ('Mark Slots As Missed', 'Mark Slots As Missed', 'org.openmrs.module.ipd.api.scheduler.tasks.MarkSlotsAsMissed', + TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 86340, false, 1, NOW(), UUID()); + + + diff --git a/api/src/main/resources/moduleApplicationContext.xml b/api/src/main/resources/moduleApplicationContext.xml index a91ef45..0dde695 100644 --- a/api/src/main/resources/moduleApplicationContext.xml +++ b/api/src/main/resources/moduleApplicationContext.xml @@ -9,5 +9,30 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - + + + + + + + + + + + + + + + + + + + + + org.openmrs.module.ipd.api.service.SlotService + + + + + \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index 137ca74..8a08728 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -19,6 +19,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -189,4 +190,32 @@ public void shouldInvokeGetSlotDurationForPatientsByOrder() { Mockito.verify(slotDAO, Mockito.times(1)).getSlotDurationForPatientsByOrder(orders, serviceTypes); } + @Test + public void shouldInvokeMarkSlotsAsMissed() { + Order order = new Order(); + Slot slot1 = new Slot(); + LocalDateTime localDateTime = LocalDateTime.now(); + slot1.setStatus(Slot.SlotStatus.SCHEDULED); + slot1.setOrder(order); + slot1.setStartDateTime(localDateTime); + + LocalDateTime futureTime = LocalDateTime.now().plusHours(2); + + Slot slot2 = new Slot(); + slot2.setStatus(Slot.SlotStatus.SCHEDULED); + slot2.setOrder(order); + slot2.setStartDateTime(futureTime); + ArrayList slots = new ArrayList<>(); + slots.add(slot1); + slots.add(slot2); + HashMap maxTimeForAnOrder = new HashMap<>(); + + Mockito.when(slotDAO.saveSlot(slot1)).thenReturn(slot1); + + + maxTimeForAnOrder.put(order, futureTime); + slotService.markSlotsAsMissed(slots, maxTimeForAnOrder); + Mockito.verify(slotDAO, Mockito.times(1)).saveSlot(slot1); + + } } \ No newline at end of file From 4785da8bca20160d3b98275c1b5707014fe9ed63 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:43:00 +0530 Subject: [PATCH 44/75] Bookmarking API - API To Create Care Team & its Participants (#37) Bookmarking API - API To Create Care Team & its Participants (#37) --- .../module/ipd/api/dao/CareTeamDAO.java | 14 +++ .../api/dao/impl/HibernateCareTeamDAO.java | 41 +++++++ .../module/ipd/api/model/AdmittedPatient.java | 1 + .../module/ipd/api/model/CareTeam.java | 105 ++++++++++++++++++ .../ipd/api/model/CareTeamParticipant.java | 99 +++++++++++++++++ .../ipd/api/service/CareTeamService.java | 18 +++ .../api/service/impl/CareTeamServiceImpl.java | 39 +++++++ .../module/ipd/api/util/DateTimeUtil.java | 7 ++ api/src/main/resources/liquibase.xml | 88 +++++++++++++++ .../HibernateCareTeamDAOIntegrationTest.java | 92 +++++++++++++++ .../service/impl/CareTeamServiceImplTest.java | 59 ++++++++++ .../test/resources/CareTeamDAOTestData.xml | 22 ++++ .../contract/CareTeamParticipantRequest.java | 24 ++++ .../contract/CareTeamParticipantResponse.java | 30 +++++ .../module/ipd/contract/CareTeamRequest.java | 15 +++ .../module/ipd/contract/CareTeamResponse.java | 28 +++++ .../ipd/controller/IPDCareTeamController.java | 47 ++++++++ .../module/ipd/factory/CareTeamFactory.java | 68 ++++++++++++ .../ipd/service/IPDCareTeamService.java | 12 ++ .../service/impl/IPDCareTeamServiceImpl.java | 49 ++++++++ 20 files changed, 858 insertions(+) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/CareTeamDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAO.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/CareTeam.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/model/CareTeamParticipant.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/CareTeamService.java create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImpl.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAOIntegrationTest.java create mode 100644 api/src/test/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImplTest.java create mode 100644 api/src/test/resources/CareTeamDAOTestData.xml create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamRequest.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/controller/IPDCareTeamController.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/IPDCareTeamService.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDCareTeamServiceImpl.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/CareTeamDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/CareTeamDAO.java new file mode 100644 index 0000000..f07d2e8 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/CareTeamDAO.java @@ -0,0 +1,14 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.Visit; +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.Schedule; + +public interface CareTeamDAO { + + CareTeam saveCareTeam(CareTeam careTeam) throws DAOException; + + CareTeam getCareTeamByVisit(Visit visit) throws DAOException; + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAO.java new file mode 100644 index 0000000..f696dbc --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAO.java @@ -0,0 +1,41 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.hibernate.query.Query; +import org.openmrs.Visit; +import org.openmrs.api.db.DAOException; +import org.openmrs.module.ipd.api.dao.CareTeamDAO; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class HibernateCareTeamDAO implements CareTeamDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateCareTeamDAO.class); + private final SessionFactory sessionFactory; + + @Autowired + public HibernateCareTeamDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public CareTeam saveCareTeam(CareTeam careTeam) throws DAOException { + sessionFactory.getCurrentSession().saveOrUpdate(careTeam); + return careTeam; + } + + @Override + public CareTeam getCareTeamByVisit(Visit visit) throws DAOException { + Query query = sessionFactory.getCurrentSession() + .createQuery("FROM CareTeam careteam " + + "WHERE careteam.visit = :visit "); + + query.setParameter("visit", visit); + + return (CareTeam) query.uniqueResult(); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java index 234e659..e53416b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java @@ -7,6 +7,7 @@ public class AdmittedPatient { private BedPatientAssignment bedPatientAssignment; private Long newTreatments; + public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments){ this.bedPatientAssignment=bedPatientAssignment; this.newTreatments=newTreatments; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeam.java b/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeam.java new file mode 100644 index 0000000..9f6f47c --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeam.java @@ -0,0 +1,105 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.openmrs.BaseChangeableOpenmrsData; +import org.openmrs.Concept; +import org.openmrs.Patient; +import org.openmrs.Visit; + +import javax.persistence.*; +import java.util.Date; +import java.util.Set; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) +@Entity +@Table(name = "care_team") +public class CareTeam extends BaseChangeableOpenmrsData { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "care_team_id") + private Integer careTeamId; + + /** + * FHIR:subject + * Patient for Whom care team is for + */ + @ManyToOne(optional = true) + @JoinColumn(name = "patient_id") + private Patient patient; + + @OneToOne + @JoinColumn(name = "visit_id", referencedColumnName = "visit_id") + private Visit visit; + + /** + * FHIR:period.start + * Starting time with inclusive boundary + */ + @Column(name = "start_time") + private Date startTime; + + /** + * FHIR:period.end + * Ending time with inclusive boundary, if not ongoing + */ + @Column(name = "end_time") + private Date endTime; + + /** + * FHIR:performer + * @see + * https://build.fhir.org/careteam-definitions.html#CareTeam.participant + * Identifies all people and organizations who are expected to be involved in the care team. + */ + @OneToMany(cascade = CascadeType.ALL) + @JoinColumn(name = "care_team_id") + private Set participants; + + + @Override + public Integer getId() { + return this.careTeamId; + } + + @Override + public void setId(Integer careTeamId) { + this.careTeamId=careTeamId; + } + + public Patient getPatient() { + return patient; + } + + public void setPatient(Patient patient) { + this.patient = patient; + } + + public Visit getVisit() { + return visit; + } + + public void setVisit(Visit visit) { + this.visit = visit; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeamParticipant.java b/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeamParticipant.java new file mode 100644 index 0000000..6cb82cc --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/CareTeamParticipant.java @@ -0,0 +1,99 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.openmrs.BaseChangeableOpenmrsData; +import org.openmrs.Provider; + +import javax.persistence.*; +import java.util.Date; +import java.util.Objects; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) +@Entity +@Table(name = "care_team_participant") +public class CareTeamParticipant extends BaseChangeableOpenmrsData { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "care_team_participant_id") + private Integer careTeamParticipantId; + + /** + * FHIR:member + * Indicates Who is involved . + */ + @OneToOne(optional = false) + @JoinColumn(name = "provider_id") + private Provider provider; + + /** + * FHIR:coverage.coveragePeriod.start + * Starting time with inclusive boundary + */ + @Column(name = "start_time") + private Date startTime; + + /** + * FHIR:coverage.coveragePeriod.end + * Ending time with inclusive boundary, if not ongoing + */ + @Column(name = "end_time") + private Date endTime; + + @Override + public Integer getId() { + return getCareTeamParticipantId(); + } + + @Override + public void setId(Integer careTeamParticipantId) { + this.careTeamParticipantId=careTeamParticipantId; + } + + public Provider getProvider() { + return provider; + } + + public void setProvider(Provider provider) { + this.provider = provider; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj != null && this.getClass() == obj.getClass()) { + CareTeamParticipant other = (CareTeamParticipant) obj; + return Objects.equals(this.getUuid(), other.getUuid()); + } else { + return false; + } + } + + public int hashCode() { + int hash = Objects.hash(new Object[]{this.getUuid()}); + return hash; + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/CareTeamService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/CareTeamService.java new file mode 100644 index 0000000..83b235c --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/CareTeamService.java @@ -0,0 +1,18 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.Visit; +import org.openmrs.api.APIException; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.Schedule; +import org.springframework.stereotype.Service; +import org.openmrs.api.OpenmrsService; + + +@Service +public interface CareTeamService extends OpenmrsService { + + CareTeam saveCareTeam(CareTeam careTeam) throws APIException; + + CareTeam getCareTeamByVisit(Visit visit) throws APIException; + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImpl.java new file mode 100644 index 0000000..84c253e --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImpl.java @@ -0,0 +1,39 @@ +package org.openmrs.module.ipd.api.service.impl; + + +import org.openmrs.Visit; +import org.openmrs.api.APIException; +import org.openmrs.api.impl.BaseOpenmrsService; +import org.openmrs.module.ipd.api.dao.CareTeamDAO; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.Schedule; +import org.openmrs.module.ipd.api.service.CareTeamService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class CareTeamServiceImpl extends BaseOpenmrsService implements CareTeamService { + + private static final Logger log = LoggerFactory.getLogger(CareTeamServiceImpl.class); + + private final CareTeamDAO careTeamDAO; + + @Autowired + public CareTeamServiceImpl(CareTeamDAO careTeamDAO) { + this.careTeamDAO = careTeamDAO; + } + + @Override + public CareTeam saveCareTeam(CareTeam careTeam) throws APIException { + return careTeamDAO.saveCareTeam(careTeam); + } + + @Override + public CareTeam getCareTeamByVisit(Visit visit) throws APIException { + return careTeamDAO.getCareTeamByVisit(visit); + } +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java index 34f533a..7588d4b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/util/DateTimeUtil.java @@ -2,6 +2,7 @@ import java.time.*; import java.util.Date; +import java.util.concurrent.TimeUnit; public class DateTimeUtil { public static LocalDateTime convertEpocUTCToLocalTimeZone(long utcTime) { @@ -19,4 +20,10 @@ public static LocalDateTime convertDateToLocalDateTime(Date date) { public static Date convertLocalDateTimeDate(LocalDateTime localDateTime) { return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); } + + public static Date convertEpochTimeToDate(Long utcTime) { + return new Date(TimeUnit.SECONDS.toMillis(utcTime)); + } + + } \ No newline at end of file diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 844971f..dd87526 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -300,6 +300,94 @@ + + + + + + + Creating care_team table + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAOIntegrationTest.java new file mode 100644 index 0000000..f2003ea --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateCareTeamDAOIntegrationTest.java @@ -0,0 +1,92 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openmrs.*; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.CareTeamDAO; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.CareTeamParticipant; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; + +public class HibernateCareTeamDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private CareTeamDAO careTeamDAO; + + @Autowired + private SessionFactory sessionFactory; + + @Test + public void shouldSaveTheCareTeamCreatedForPatientGivenPatientVisit() { + + executeDataSet("CareTeamDAOTestData.xml"); + + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + Visit visit=Context.getVisitService().getVisitByUuid("84d8b838-1111-11e3-b47b-c6959a448789"); + Provider provider=Context.getProviderService().getProviderByUuid("2bdc3f7d-d911-401a-84e9-5494dda83e8e"); + + + CareTeamParticipant participant = new CareTeamParticipant(); + participant.setStartTime(visit.getStartDatetime()); + participant.setProvider(provider); + Set participantSet=new HashSet<>(); + participantSet.add(participant); + + CareTeam careTeam = new CareTeam(); + careTeam.setPatient(visit.getPatient()); + careTeam.setStartTime(visit.getStartDatetime()); + careTeam.setVisit(visit); + careTeam.setParticipants(participantSet); + + CareTeam savedCareTeam = careTeamDAO.saveCareTeam(careTeam); + + List participantsList = new ArrayList<>(savedCareTeam.getParticipants()); + + Assertions.assertEquals(visit.getPatient().getPatientId(), savedCareTeam.getPatient().getPatientId()); + Assertions.assertEquals(provider, participantsList.get(0).getProvider()); + Assertions.assertEquals(visit, savedCareTeam.getVisit()); + + sessionFactory.getCurrentSession().delete(savedCareTeam); + } + + + @Test + public void shouldGetCareTeamGivenPatientVisit() { + + executeDataSet("CareTeamDAOTestData.xml"); + + Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN"); + Visit visit=Context.getVisitService().getVisitByUuid("84d8b838-1111-11e3-b47b-c6959a448789"); + Provider provider=Context.getProviderService().getProviderByUuid("2bdc3f7d-d911-401a-84e9-5494dda83e8e"); + + + CareTeamParticipant participant = new CareTeamParticipant(); + participant.setStartTime(visit.getStartDatetime()); + participant.setProvider(provider); + Set participantSet=new HashSet<>(); + participantSet.add(participant); + + CareTeam careTeam = new CareTeam(); + careTeam.setPatient(visit.getPatient()); + careTeam.setStartTime(visit.getStartDatetime()); + careTeam.setVisit(visit); + careTeam.setParticipants(participantSet); + + CareTeam savedCareTeam=careTeamDAO.saveCareTeam(careTeam); + + CareTeam careTeamByVisit= careTeamDAO.getCareTeamByVisit(visit); + + Assertions.assertEquals(savedCareTeam.getCareTeamId(),careTeamByVisit.getCareTeamId()); + Assertions.assertEquals(visit,careTeamByVisit.getVisit()); + Assertions.assertEquals(1,careTeam.getParticipants().size()); + + sessionFactory.getCurrentSession().delete(savedCareTeam); + } + + +} \ No newline at end of file diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImplTest.java new file mode 100644 index 0000000..468423b --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/CareTeamServiceImplTest.java @@ -0,0 +1,59 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.openmrs.Concept; +import org.openmrs.ConceptName; +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.module.ipd.api.dao.CareTeamDAO; +import org.openmrs.module.ipd.api.dao.ScheduleDAO; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.Reference; +import org.openmrs.module.ipd.api.model.Schedule; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +@RunWith(MockitoJUnitRunner.class) +public class CareTeamServiceImplTest { + + @InjectMocks + private CareTeamServiceImpl careTeamService; + + @Mock + private CareTeamDAO careTeamDAO; + + @Test + public void shouldInvokeSaveCareTeamWithGivenCareTeam() { + CareTeam careTeam = new CareTeam(); + CareTeam expectedCareTeam = new CareTeam(); + expectedCareTeam.setId(1); + + Mockito.when(careTeamDAO.saveCareTeam(careTeam)).thenReturn(expectedCareTeam); + + careTeamService.saveCareTeam(careTeam); + + Mockito.verify(careTeamDAO, Mockito.times(1)).saveCareTeam(careTeam); + } + + @Test + public void shouldInvokeGetCareTeamWithGivenVisit() { + CareTeam expectedCareTeam = new CareTeam(); + Visit visit = new Visit(); + expectedCareTeam.setId(1); + + Mockito.when(careTeamDAO.getCareTeamByVisit(visit)).thenReturn(expectedCareTeam); + + careTeamService.getCareTeamByVisit(visit); + + Mockito.verify(careTeamDAO, Mockito.times(1)).getCareTeamByVisit(visit); + } + +} diff --git a/api/src/test/resources/CareTeamDAOTestData.xml b/api/src/test/resources/CareTeamDAOTestData.xml new file mode 100644 index 0000000..222818f --- /dev/null +++ b/api/src/test/resources/CareTeamDAOTestData.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantRequest.java new file mode 100644 index 0000000..a98afec --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantRequest.java @@ -0,0 +1,24 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Builder +public class CareTeamParticipantRequest { + + private String uuid; + private Long startTime; + private Long endTime; + private String providerUuid; + private Boolean voided; + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantResponse.java new file mode 100644 index 0000000..427c6c5 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamParticipantResponse.java @@ -0,0 +1,30 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import org.openmrs.module.ipd.api.model.CareTeamParticipant; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +@Getter +@Builder +public class CareTeamParticipantResponse { + + private String uuid; + private Object provider; + private Long startTime; + private Long endTime; + private Boolean voided; + + public static CareTeamParticipantResponse createFrom(CareTeamParticipant careTeamParticipant) { + return CareTeamParticipantResponse.builder(). + uuid(careTeamParticipant.getUuid()). + provider(ConversionUtil.convertToRepresentation(careTeamParticipant.getProvider(), Representation.REF)). + startTime(careTeamParticipant.getStartTime().getTime()). + endTime(careTeamParticipant.getEndTime().getTime()). + voided(careTeamParticipant.getVoided()). + build(); + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamRequest.java b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamRequest.java new file mode 100644 index 0000000..4073924 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamRequest.java @@ -0,0 +1,15 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class CareTeamRequest { + private String patientUuid; + private List careTeamParticipantsRequest; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamResponse.java new file mode 100644 index 0000000..ade81b7 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/CareTeamResponse.java @@ -0,0 +1,28 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import org.openmrs.module.ipd.api.model.CareTeam; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +public class CareTeamResponse { + + private String uuid; + private String patientUuid; + private List participants; + + public static CareTeamResponse createFrom(CareTeam careTeam){ + return CareTeamResponse.builder(). + uuid(careTeam.getUuid()). + patientUuid(careTeam.getPatient().getUuid()). + participants(careTeam.getParticipants().stream(). + filter(careTeamParticipant -> !careTeamParticipant.getVoided()). + map(CareTeamParticipantResponse::createFrom).collect(Collectors.toList())). + build(); + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDCareTeamController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDCareTeamController.java new file mode 100644 index 0000000..e713dcd --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDCareTeamController.java @@ -0,0 +1,47 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.contract.CareTeamRequest; +import org.openmrs.module.ipd.contract.CareTeamResponse; +import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; +import org.openmrs.module.ipd.service.IPDCareTeamService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd/careteam") +@Slf4j +public class IPDCareTeamController extends BaseRestController { + + private final IPDCareTeamService ipdCareTeamService; + + @Autowired + public IPDCareTeamController(IPDCareTeamService ipdCareTeamService) { + this.ipdCareTeamService = ipdCareTeamService; + } + + @RequestMapping(value = "/participants", method = RequestMethod.POST) + @ResponseBody + public ResponseEntity createMedicationSchedule(@RequestBody CareTeamRequest careTeamRequest) { + try { + CareTeam careTeam = ipdCareTeamService.saveCareTeamParticipants(careTeamRequest); + return new ResponseEntity<>(CareTeamResponse.createFrom(careTeam), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java new file mode 100644 index 0000000..1e3c574 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java @@ -0,0 +1,68 @@ +package org.openmrs.module.ipd.factory; + +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.api.APIException; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.model.CareTeamParticipant; +import org.openmrs.module.ipd.api.util.DateTimeUtil; +import org.openmrs.module.ipd.contract.CareTeamParticipantRequest; +import org.openmrs.module.ipd.contract.CareTeamRequest; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class CareTeamFactory { + + + public CareTeam createCareTeamFromRequest(CareTeamRequest request, Patient patient, Visit visit) { + CareTeam careTeam = new CareTeam(); + careTeam.setVisit(visit); + careTeam.setPatient(patient); + careTeam.setStartTime(visit.getStartDatetime()); + + if (request.getCareTeamParticipantsRequest() !=null){ + List careTeamParticipants = new ArrayList<>(); + for (CareTeamParticipantRequest participantRequest: request.getCareTeamParticipantsRequest()) { + CareTeamParticipant participant = new CareTeamParticipant(); + participant.setStartTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getStartTime())); + participant.setEndTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getEndTime())); + participant.setProvider(Context.getProviderService().getProviderByUuid(participantRequest.getProviderUuid())); + careTeamParticipants.add(participant); + } + careTeam.setParticipants(new HashSet<>(careTeamParticipants)); + } + return careTeam; + } + + public CareTeam updateCareTeamFromRequest(CareTeamRequest careTeamRequest, CareTeam careTeam) { + if (careTeamRequest.getCareTeamParticipantsRequest() !=null){ + List careTeamParticipants = new ArrayList<>(); + for (CareTeamParticipantRequest participantRequest: careTeamRequest.getCareTeamParticipantsRequest()) { + if (participantRequest.getUuid()!=null){ + CareTeamParticipant careTeamParticipant = careTeam.getParticipants().stream() + .filter(participant -> participant.getUuid().equals(participantRequest.getUuid())) + .findFirst().get(); + careTeamParticipant.setStartTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getStartTime())); + careTeamParticipant.setEndTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getEndTime())); + careTeamParticipant.setProvider(Context.getProviderService().getProviderByUuid(participantRequest.getProviderUuid())); + if (participantRequest.getVoided() != null) careTeamParticipant.setVoided(participantRequest.getVoided()); + } + else { + Boolean participantAlreadyExists = careTeam.getParticipants().stream(). + anyMatch(participant -> participant.getVoided()!=true + && DateTimeUtil.convertEpochTimeToDate(participantRequest.getStartTime()).equals(participant.getStartTime())); + if (participantAlreadyExists) throw new APIException("Participant Already exists for given time frame"); + CareTeamParticipant participant = new CareTeamParticipant(); + participant.setStartTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getStartTime())); + participant.setEndTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getEndTime())); + participant.setProvider(Context.getProviderService().getProviderByUuid(participantRequest.getProviderUuid())); + careTeam.getParticipants().add(participant); + } + } + } + return careTeam; + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDCareTeamService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDCareTeamService.java new file mode 100644 index 0000000..42243a8 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDCareTeamService.java @@ -0,0 +1,12 @@ +package org.openmrs.module.ipd.service; + +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.contract.CareTeamParticipantRequest; +import org.openmrs.module.ipd.contract.CareTeamRequest; + +import java.util.List; + +public interface IPDCareTeamService { + + CareTeam saveCareTeamParticipants(CareTeamRequest careTeamRequest); +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDCareTeamServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDCareTeamServiceImpl.java new file mode 100644 index 0000000..48e53db --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDCareTeamServiceImpl.java @@ -0,0 +1,49 @@ +package org.openmrs.module.ipd.service.impl; + +import org.openmrs.Patient; +import org.openmrs.Visit; +import org.openmrs.api.ConceptService; +import org.openmrs.api.PatientService; +import org.openmrs.api.VisitService; +import org.openmrs.module.ipd.api.model.CareTeam; +import org.openmrs.module.ipd.api.service.CareTeamService; +import org.openmrs.module.ipd.contract.CareTeamRequest; +import org.openmrs.module.ipd.factory.CareTeamFactory; +import org.openmrs.module.ipd.service.IPDCareTeamService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class IPDCareTeamServiceImpl implements IPDCareTeamService { + + private final CareTeamService careTeamService; + private final CareTeamFactory careTeamFactory; + private final ConceptService conceptService; + private final VisitService visitService; + private final PatientService patientService; + + @Autowired + public IPDCareTeamServiceImpl(CareTeamService careTeamService, CareTeamFactory careTeamFactory, ConceptService conceptService, VisitService visitService, PatientService patientService) { + this.careTeamService = careTeamService; + this.careTeamFactory = careTeamFactory; + this.conceptService = conceptService; + this.visitService = visitService; + this.patientService = patientService; + } + + @Override + public CareTeam saveCareTeamParticipants(CareTeamRequest careTeamRequest) { + Patient patient = patientService.getPatientByUuid(careTeamRequest.getPatientUuid()); + Visit visit = visitService.getActiveVisitsByPatient(patient).get(0); + CareTeam careTeam = careTeamService.getCareTeamByVisit(visit); + if (careTeam==null || careTeam.getCareTeamId()==null){ + careTeam = careTeamFactory.createCareTeamFromRequest(careTeamRequest,patient,visit); + } + else { + careTeam = careTeamFactory.updateCareTeamFromRequest(careTeamRequest, careTeam); + } + return careTeamService.saveCareTeam(careTeam); + } +} From d29bbc9a502a6c9ee6dedd030c1becb48a04638c Mon Sep 17 00:00:00 2001 From: Umair Fayaz <59157924+umair-fayaz@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:06:47 +0530 Subject: [PATCH 45/75] Adds careTeam information to AdmittedPatient (#40) --- .../module/ipd/api/dao/impl/HibernateWardDAO.java | 3 ++- .../openmrs/module/ipd/api/model/AdmittedPatient.java | 5 ++++- .../module/ipd/contract/AdmittedPatientResponse.java | 10 ++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 254da74..1766e9c 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -33,10 +33,11 @@ public List getAdmittedPatientsByLocation(Location location) { Session session = this.sessionFactory.getCurrentSession(); try { Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + - "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId)))" + + "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId)), careTeam)" + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + "JOIN org.openmrs.Encounter e on e.visit = v " + + "LEFT JOIN CareTeam careTeam on careTeam.visit = v " + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java index e53416b..5210ed5 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java @@ -6,11 +6,13 @@ public class AdmittedPatient { private BedPatientAssignment bedPatientAssignment; private Long newTreatments; + private CareTeam careTeam; - public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments){ + public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments, CareTeam careTeam){ this.bedPatientAssignment=bedPatientAssignment; this.newTreatments=newTreatments; + this.careTeam=careTeam; } public BedPatientAssignment getBedPatientAssignment() { @@ -21,4 +23,5 @@ public Long getNewTreatments() { return newTreatments; } + public CareTeam getCareTeam() { return careTeam; } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java index 650690e..16ae0d8 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java @@ -15,11 +15,17 @@ public class AdmittedPatientResponse { private Object patientDetails; private Object bedDetails; private Long newTreatments; - + private Object careTeam; public static AdmittedPatientResponse createFrom(AdmittedPatient admittedPatient) { - return AdmittedPatientResponse.builder(). + AdmittedPatientResponse admittedPatientResponse = AdmittedPatientResponse.builder(). patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getPatient(), Representation.DEFAULT)). bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getBed(),Representation.REF)). newTreatments(admittedPatient.getNewTreatments()).build(); + + if ( admittedPatient.getCareTeam() != null ) { + admittedPatientResponse.setCareTeam(CareTeamResponse.createFrom(admittedPatient.getCareTeam())); + } + + return admittedPatientResponse; } } From 83d3e08c359540c6840749e6eeef7331475bba9d Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 12 Mar 2024 12:34:19 +0530 Subject: [PATCH 46/75] Adds visitDetails to AdmittedPatientResponse --- .../openmrs/module/ipd/contract/AdmittedPatientResponse.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java index 16ae0d8..75f7e8b 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java @@ -14,12 +14,14 @@ public class AdmittedPatientResponse { private Object patientDetails; private Object bedDetails; + private Object visitDetails; private Long newTreatments; private Object careTeam; public static AdmittedPatientResponse createFrom(AdmittedPatient admittedPatient) { AdmittedPatientResponse admittedPatientResponse = AdmittedPatientResponse.builder(). patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getPatient(), Representation.DEFAULT)). bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getBed(),Representation.REF)). + visitDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBedPatientAssignment().getEncounter().getVisit(), Representation.REF)). newTreatments(admittedPatient.getNewTreatments()).build(); if ( admittedPatient.getCareTeam() != null ) { From 5809e897ddb0292313efd902bd3132c944ebf983 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:53:19 +0530 Subject: [PATCH 47/75] Removed starttime,endtime & provider in update flow (#42) --- .../java/org/openmrs/module/ipd/factory/CareTeamFactory.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java b/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java index 1e3c574..7eee78a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java +++ b/omod/src/main/java/org/openmrs/module/ipd/factory/CareTeamFactory.java @@ -45,9 +45,6 @@ public CareTeam updateCareTeamFromRequest(CareTeamRequest careTeamRequest, CareT CareTeamParticipant careTeamParticipant = careTeam.getParticipants().stream() .filter(participant -> participant.getUuid().equals(participantRequest.getUuid())) .findFirst().get(); - careTeamParticipant.setStartTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getStartTime())); - careTeamParticipant.setEndTime(DateTimeUtil.convertEpochTimeToDate(participantRequest.getEndTime())); - careTeamParticipant.setProvider(Context.getProviderService().getProviderByUuid(participantRequest.getProviderUuid())); if (participantRequest.getVoided() != null) careTeamParticipant.setVoided(participantRequest.getVoided()); } else { From 64b65c47d9da8336023bb9583ca78b06b579cd33 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Thu, 14 Mar 2024 15:52:25 +0530 Subject: [PATCH 48/75] Adds provider details and time check for getAdmittedPatients --- .../openmrs/module/ipd/api/dao/WardDAO.java | 4 ++- .../ipd/api/dao/impl/HibernateWardDAO.java | 33 ++++++++++++++++--- .../module/ipd/api/service/WardService.java | 1 + .../ipd/api/service/impl/WardServiceImpl.java | 13 ++++++-- .../impl/HibernateWardDAOIntegrationTest.java | 2 +- .../ipd/controller/IPDWardController.java | 15 +++++++++ .../module/ipd/service/IPDWardService.java | 3 +- .../ipd/service/impl/IPDWardServiceImpl.java | 15 +++++++++ 8 files changed, 75 insertions(+), 11 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index 43d8f15..08f3990 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -1,16 +1,18 @@ package org.openmrs.module.ipd.api.dao; import org.openmrs.Location; +import org.openmrs.Provider; import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import java.time.LocalDateTime; import java.util.List; public interface WardDAO { List searchAdmittedPatients(Location location,List searchKeys,String searchValue); - List getAdmittedPatientsByLocation(Location location); + List getAdmittedPatients(Location location, Provider provider, LocalDateTime currentDateTime); WardPatientsSummary getWardPatientSummary(Location location); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 1766e9c..934bbc9 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -3,6 +3,7 @@ import org.hibernate.Session; import org.hibernate.SessionFactory; import org.openmrs.Location; +import org.openmrs.Provider; import org.openmrs.module.ipd.api.dao.WardDAO; import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; @@ -13,6 +14,7 @@ import org.hibernate.query.Query; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -29,10 +31,10 @@ public HibernateWardDAO(SessionFactory sessionFactory) { } @Override - public List getAdmittedPatientsByLocation(Location location) { + public List getAdmittedPatients(Location location, Provider provider, LocalDateTime dateTime) { Session session = this.sessionFactory.getCurrentSession(); try { - Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + + String queryString = "select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId)), careTeam)" + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + @@ -40,14 +42,35 @@ public List getAdmittedPatientsByLocation(Location location) { "LEFT JOIN CareTeam careTeam on careTeam.visit = v " + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + + "JOIN careTeam.participants ctp " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + "LEFT JOIN Slot s on s.order = o " + - "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location " + - "GROUP BY assignment.patient, v " + - "ORDER BY assignment.startDatetime desc"); + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location "; + + if (provider != null) { + queryString += "and ctp.provider = :provider "; + } + + if (dateTime != null) { + queryString += "and :dateTime between ctp.startTime and ctp.endTime "; + } + + + queryString += "GROUP BY assignment.patient, v " + + "ORDER BY assignment.startDatetime desc"; + + Query query = session.createQuery(queryString); query.setParameter("location", location); + if (provider != null) { + query.setParameter("provider", provider); + } + + if (dateTime != null) { + query.setParameter("dateTime", dateTime); + } + return query.getResultList(); } catch (Exception ex){ diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java index c1604df..5d57708 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -14,4 +14,5 @@ public interface WardService { List searchWardPatients(String wardUuid, List searchKeys, String searchValue); + List getProviderWardPatientsByUuid(String wardUuid, String providerUuid); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index ec72ca8..9d5a3e3 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Location; +import org.openmrs.Provider; import org.openmrs.api.LocationService; import org.openmrs.api.context.Context; import org.openmrs.module.ipd.api.dao.WardDAO; @@ -11,7 +12,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; +import java.time.LocalDateTime; import java.util.List; @Service @@ -35,7 +36,15 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { @Override public List getWardPatientsByUuid(String wardUuid) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.getAdmittedPatientsByLocation(location); + return wardDAO.getAdmittedPatients(location,null, null); + } + + @Override + public List getProviderWardPatientsByUuid(String wardUuid, String providerUuid) { + Location location = Context.getService(LocationService.class).getLocationByUuid(wardUuid); + Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); + LocalDateTime currentDateTime = LocalDateTime.now(); + return wardDAO.getAdmittedPatients(location, provider, currentDateTime); } @Override diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java index 4cb29c8..daed69e 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -26,7 +26,7 @@ public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { public void shouldGetAdmittedPatientsByLocation() { Location location= Context.getService(LocationService.class).getLocationByUuid("7779d653-393b-4118-9c83-a3715b82d4ac"); - List admittedPatients= wardDAO.getAdmittedPatientsByLocation(location); + List admittedPatients= wardDAO.getAdmittedPatients(location, null, null); Assertions.assertEquals(0, admittedPatients.size()); diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index 68f3ea3..e337bbe 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -51,6 +51,21 @@ public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String } } + @RequestMapping(value = "{wardUuid}/myPatients", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getIPDWardPatientsForProvider(@PathVariable("wardUuid") String wardUuid, + @RequestParam(value = "providerUuid") String providerUuid, + @RequestParam(value = "offset") Integer offset, + @RequestParam (value = "limit") Integer limit) throws ParseException { + try { + IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDProviderPatientsByWard(wardUuid, providerUuid, offset, limit); + return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + @RequestMapping(value = "{wardUuid}/patients/search", method = RequestMethod.GET) @ResponseBody public ResponseEntity searchIPDWardPatient(@PathVariable("wardUuid") String wardUuid, diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 44780b4..2997822 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -14,6 +14,5 @@ public interface IPDWardService { IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit); - - + IPDPatientDetails getIPDProviderPatientsByWard(String wardUuid, String providerUuid, Integer offset, Integer limit); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index 8a4d8fa..392d8b7 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -45,6 +45,21 @@ public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, In return new IPDPatientDetails(admittedPatients.subList(offset, offset + limit), admittedPatients.size()); } + @Override + public IPDPatientDetails getIPDProviderPatientsByWard(String wardUuid, String providerUuid, Integer offset, Integer limit) { + + List admittedPatients = wardService.getProviderWardPatientsByUuid(wardUuid, providerUuid); + + if (admittedPatients ==null ){ + return new IPDPatientDetails(new ArrayList<>(),0); + } + + offset = Math.min(offset, admittedPatients.size()); + limit = Math.min(limit, admittedPatients.size() - offset); + + return new IPDPatientDetails(admittedPatients.subList(offset, offset + limit), admittedPatients.size()); + } + @Override public IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit) { From 3ef205f155a3e75243103afcdd8fe2dbb2f66647 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Fri, 15 Mar 2024 16:19:46 +0530 Subject: [PATCH 49/75] Change LocalDateTime to Date --- api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java | 4 ++-- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 4 ++-- .../openmrs/module/ipd/api/service/impl/WardServiceImpl.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index 08f3990..c0f938b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -5,14 +5,14 @@ import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.model.WardPatientsSummary; -import java.time.LocalDateTime; +import java.util.Date; import java.util.List; public interface WardDAO { List searchAdmittedPatients(Location location,List searchKeys,String searchValue); - List getAdmittedPatients(Location location, Provider provider, LocalDateTime currentDateTime); + List getAdmittedPatients(Location location, Provider provider, Date currentDateTime); WardPatientsSummary getWardPatientSummary(Location location); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 934bbc9..708a49f 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -14,8 +14,8 @@ import org.hibernate.query.Query; -import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Date; import java.util.List; @Repository @@ -31,7 +31,7 @@ public HibernateWardDAO(SessionFactory sessionFactory) { } @Override - public List getAdmittedPatients(Location location, Provider provider, LocalDateTime dateTime) { + public List getAdmittedPatients(Location location, Provider provider, Date dateTime) { Session session = this.sessionFactory.getCurrentSession(); try { String queryString = "select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index 9d5a3e3..19b699e 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -12,7 +12,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; +import java.util.Date; import java.util.List; @Service @@ -43,7 +43,7 @@ public List getWardPatientsByUuid(String wardUuid) { public List getProviderWardPatientsByUuid(String wardUuid, String providerUuid) { Location location = Context.getService(LocationService.class).getLocationByUuid(wardUuid); Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); - LocalDateTime currentDateTime = LocalDateTime.now(); + Date currentDateTime = new Date(); return wardDAO.getAdmittedPatients(location, provider, currentDateTime); } From 3fcf066ffa3a8eb7f3b71b0b8c12206110d4c953 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Mon, 18 Mar 2024 12:51:15 +0530 Subject: [PATCH 50/75] Rename methods --- .../java/org/openmrs/module/ipd/api/service/WardService.java | 2 +- .../openmrs/module/ipd/api/service/impl/WardServiceImpl.java | 2 +- .../org/openmrs/module/ipd/controller/IPDWardController.java | 2 +- .../java/org/openmrs/module/ipd/service/IPDWardService.java | 2 +- .../openmrs/module/ipd/service/impl/IPDWardServiceImpl.java | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java index 5d57708..0559a31 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -14,5 +14,5 @@ public interface WardService { List searchWardPatients(String wardUuid, List searchKeys, String searchValue); - List getProviderWardPatientsByUuid(String wardUuid, String providerUuid); + List getPatientsByWardAndProvider(String wardUuid, String providerUuid); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index 19b699e..b7cfe79 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -40,7 +40,7 @@ public List getWardPatientsByUuid(String wardUuid) { } @Override - public List getProviderWardPatientsByUuid(String wardUuid, String providerUuid) { + public List getPatientsByWardAndProvider(String wardUuid, String providerUuid) { Location location = Context.getService(LocationService.class).getLocationByUuid(wardUuid); Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); Date currentDateTime = new Date(); diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index e337bbe..74da002 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -58,7 +58,7 @@ public ResponseEntity getIPDWardPatientsForProvider(@PathVariable("wardU @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit) throws ParseException { try { - IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDProviderPatientsByWard(wardUuid, providerUuid, offset, limit); + IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientsByWardAndProvider(wardUuid, providerUuid, offset, limit); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 2997822..94fa3b2 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -14,5 +14,5 @@ public interface IPDWardService { IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit); - IPDPatientDetails getIPDProviderPatientsByWard(String wardUuid, String providerUuid, Integer offset, Integer limit); + IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index 392d8b7..28318ff 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -46,9 +46,9 @@ public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, In } @Override - public IPDPatientDetails getIPDProviderPatientsByWard(String wardUuid, String providerUuid, Integer offset, Integer limit) { + public IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit) { - List admittedPatients = wardService.getProviderWardPatientsByUuid(wardUuid, providerUuid); + List admittedPatients = wardService.getPatientsByWardAndProvider(wardUuid, providerUuid); if (admittedPatients ==null ){ return new IPDPatientDetails(new ArrayList<>(),0); From 917277bdabc5ec63bc4b2d62093f49340f735ddf Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Mon, 18 Mar 2024 13:52:41 +0530 Subject: [PATCH 51/75] Adds ability to sort by Bed Number --- .../openmrs/module/ipd/api/dao/WardDAO.java | 4 +-- .../ipd/api/dao/impl/HibernateWardDAO.java | 26 ++++++++++++++----- .../module/ipd/api/service/WardService.java | 6 ++--- .../ipd/api/service/impl/WardServiceImpl.java | 12 ++++----- .../impl/HibernateWardDAOIntegrationTest.java | 2 +- .../ipd/controller/IPDWardController.java | 15 ++++++----- .../module/ipd/service/IPDWardService.java | 6 ++--- .../ipd/service/impl/IPDWardServiceImpl.java | 12 ++++----- 8 files changed, 50 insertions(+), 33 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index c0f938b..f8fb1c7 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -10,9 +10,9 @@ public interface WardDAO { - List searchAdmittedPatients(Location location,List searchKeys,String searchValue); + List searchAdmittedPatients(Location location, List searchKeys, String searchValue, String sortBy); - List getAdmittedPatients(Location location, Provider provider, Date currentDateTime); + List getAdmittedPatients(Location location, Provider provider, Date currentDateTime, String sortBy); WardPatientsSummary getWardPatientSummary(Location location); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 708a49f..9fb24b0 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -30,8 +30,22 @@ public HibernateWardDAO(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } + private static String generateGroupByClauseForSorting(String sortBy) { + String groupBy = " GROUP BY assignment.patient, v "; + + switch (sortBy) { + case "bedNumber": + groupBy += " ORDER BY assignment.bed.bedNumber "; + break; + default: + groupBy += " ORDER BY assignment.startDatetime desc "; + break; + } + return groupBy; + } + @Override - public List getAdmittedPatients(Location location, Provider provider, Date dateTime) { + public List getAdmittedPatients(Location location, Provider provider, Date dateTime, String sortBy) { Session session = this.sessionFactory.getCurrentSession(); try { String queryString = "select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + @@ -55,11 +69,11 @@ public List getAdmittedPatients(Location location, Provider pro queryString += "and :dateTime between ctp.startTime and ctp.endTime "; } + String groupBy = generateGroupByClauseForSorting(sortBy); - queryString += "GROUP BY assignment.patient, v " + - "ORDER BY assignment.startDatetime desc"; + String finalQuery = queryString + groupBy; - Query query = session.createQuery(queryString); + Query query = session.createQuery(finalQuery); query.setParameter("location", location); @@ -99,7 +113,7 @@ public WardPatientsSummary getWardPatientSummary(Location location) { } @Override - public List searchAdmittedPatients(Location location, List searchKeys, String searchValue) { + public List searchAdmittedPatients(Location location, List searchKeys, String searchValue, String sortBy) { try { Session session = sessionFactory.getCurrentSession(); @@ -121,7 +135,7 @@ public List searchAdmittedPatients(Location location, List getWardPatientsByUuid(String wardUuid); + List getWardPatientsByUuid(String wardUuid, String sortBy); - List searchWardPatients(String wardUuid, List searchKeys, String searchValue); + List searchWardPatients(String wardUuid, List searchKeys, String searchValue, String sortBy); - List getPatientsByWardAndProvider(String wardUuid, String providerUuid); + List getPatientsByWardAndProvider(String wardUuid, String providerUuid, String sortBy); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index b7cfe79..6960022 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -34,23 +34,23 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public List getWardPatientsByUuid(String wardUuid) { + public List getWardPatientsByUuid(String wardUuid, String sortBy) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.getAdmittedPatients(location,null, null); + return wardDAO.getAdmittedPatients(location,null, null, sortBy); } @Override - public List getPatientsByWardAndProvider(String wardUuid, String providerUuid) { + public List getPatientsByWardAndProvider(String wardUuid, String providerUuid, String sortBy) { Location location = Context.getService(LocationService.class).getLocationByUuid(wardUuid); Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); Date currentDateTime = new Date(); - return wardDAO.getAdmittedPatients(location, provider, currentDateTime); + return wardDAO.getAdmittedPatients(location, provider, currentDateTime, sortBy); } @Override - public List searchWardPatients(String wardUuid, List searchKeys, String searchValue) { + public List searchWardPatients(String wardUuid, List searchKeys, String searchValue, String sortBy) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue); + return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue,sortBy); } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java index daed69e..a932f79 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -26,7 +26,7 @@ public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { public void shouldGetAdmittedPatientsByLocation() { Location location= Context.getService(LocationService.class).getLocationByUuid("7779d653-393b-4118-9c83-a3715b82d4ac"); - List admittedPatients= wardDAO.getAdmittedPatients(location, null, null); + List admittedPatients= wardDAO.getAdmittedPatients(location, null, null, null); Assertions.assertEquals(0, admittedPatients.size()); diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index 74da002..49f72c4 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -41,9 +41,10 @@ public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") @ResponseBody public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String wardUuid, @RequestParam(value = "offset") Integer offset, - @RequestParam (value = "limit") Integer limit) throws ParseException { + @RequestParam (value = "limit") Integer limit, + @RequestParam(value = "sortBy") String sortBy) throws ParseException { try { - IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); + IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit,sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); @@ -56,9 +57,10 @@ public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String public ResponseEntity getIPDWardPatientsForProvider(@PathVariable("wardUuid") String wardUuid, @RequestParam(value = "providerUuid") String providerUuid, @RequestParam(value = "offset") Integer offset, - @RequestParam (value = "limit") Integer limit) throws ParseException { + @RequestParam (value = "limit") Integer limit, + @RequestParam(value = "sortBy") String sortBy) throws ParseException { try { - IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientsByWardAndProvider(wardUuid, providerUuid, offset, limit); + IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientsByWardAndProvider(wardUuid, providerUuid, offset, limit, sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); @@ -72,9 +74,10 @@ public ResponseEntity searchIPDWardPatient(@PathVariable("wardUuid") Str @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit, @RequestParam(value = "searchKeys") List searchKeys, - @RequestParam(value = "searchValue") String searchValue) throws ParseException { + @RequestParam(value = "searchValue") String searchValue, + @RequestParam(value = "sortBy") String sortBy) throws ParseException { try { - IPDPatientDetails ipdPatientDetails = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit); + IPDPatientDetails ipdPatientDetails = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit,sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); } catch (Exception e) { log.error("Runtime error while trying to create new schedule", e); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 94fa3b2..51af3e9 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -10,9 +10,9 @@ public interface IPDWardService { WardPatientsSummary getIPDWardPatientSummary(String wardUuid); - IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit); + IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit, String sortBy); - IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit); + IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, Integer offset, Integer limit, String sortBy); - IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit); + IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit, String sortBy); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index 28318ff..e97728d 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -31,9 +31,9 @@ public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { } @Override - public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit) { + public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit, String sortBy) { - List admittedPatients = wardService.getWardPatientsByUuid(wardUuid); + List admittedPatients = wardService.getWardPatientsByUuid(wardUuid,sortBy); if (admittedPatients ==null ){ return new IPDPatientDetails(new ArrayList<>(),0); @@ -46,9 +46,9 @@ public IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, In } @Override - public IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit) { + public IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String providerUuid, Integer offset, Integer limit, String sortBy) { - List admittedPatients = wardService.getPatientsByWardAndProvider(wardUuid, providerUuid); + List admittedPatients = wardService.getPatientsByWardAndProvider(wardUuid, providerUuid, sortBy); if (admittedPatients ==null ){ return new IPDPatientDetails(new ArrayList<>(),0); @@ -62,9 +62,9 @@ public IPDPatientDetails getIPDPatientsByWardAndProvider(String wardUuid, String @Override public IPDPatientDetails searchIPDPatientsInWard(String wardUuid, List searchKeys, String searchValue, - Integer offset, Integer limit) { + Integer offset, Integer limit, String sortBy) { - List admittedPatients = wardService.searchWardPatients(wardUuid,searchKeys,searchValue); + List admittedPatients = wardService.searchWardPatients(wardUuid,searchKeys,searchValue,sortBy); if (admittedPatients ==null ){ return new IPDPatientDetails(new ArrayList<>(),0); } From fa931e24b6a5ae6f7b9b4a1b53062bff3e27684c Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Mon, 18 Mar 2024 15:03:01 +0530 Subject: [PATCH 52/75] CareTeam info added to search API as well (#44) CareTeam info added to search API as well (#44) --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 708a49f..8845f01 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -104,12 +104,13 @@ public List searchAdmittedPatients(Location location, List Date: Mon, 18 Mar 2024 17:25:42 +0530 Subject: [PATCH 53/75] Removed CareTeam Particpants join condition (#45) Removed CareTeam Particpants join condition (#45) --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 8845f01..33a28f1 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -42,7 +42,7 @@ public List getAdmittedPatients(Location location, Provider pro "LEFT JOIN CareTeam careTeam on careTeam.visit = v " + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + - "JOIN careTeam.participants ctp " + + //"JOIN careTeam.participants ctp " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + "LEFT JOIN Slot s on s.order = o " + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location "; From 722e4c1f0c5f073653a05db8157a453e0ae8e532 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 19 Mar 2024 08:00:58 +0530 Subject: [PATCH 54/75] Changes Inner join to left outer join --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 9fb24b0..aa61519 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -56,7 +56,7 @@ public List getAdmittedPatients(Location location, Provider pro "LEFT JOIN CareTeam careTeam on careTeam.visit = v " + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + - "JOIN careTeam.participants ctp " + + "LEFT JOIN careTeam.participants ctp " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + "LEFT JOIN Slot s on s.order = o " + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location "; From a493e8ca0bf1ca5d3e897e7d9aa55327523de270 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 19 Mar 2024 08:01:28 +0530 Subject: [PATCH 55/75] Makes sortBy optional parameter --- .../openmrs/module/ipd/controller/IPDWardController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index 49f72c4..5ddcd94 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -42,7 +42,7 @@ public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String wardUuid, @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit, - @RequestParam(value = "sortBy") String sortBy) throws ParseException { + @RequestParam(value = "sortBy", required = false) String sortBy) throws ParseException { try { IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit,sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); @@ -58,7 +58,7 @@ public ResponseEntity getIPDWardPatientsForProvider(@PathVariable("wardU @RequestParam(value = "providerUuid") String providerUuid, @RequestParam(value = "offset") Integer offset, @RequestParam (value = "limit") Integer limit, - @RequestParam(value = "sortBy") String sortBy) throws ParseException { + @RequestParam(value = "sortBy", required = false) String sortBy) throws ParseException { try { IPDPatientDetails ipdPatientDetails = ipdWardService.getIPDPatientsByWardAndProvider(wardUuid, providerUuid, offset, limit, sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); @@ -75,7 +75,7 @@ public ResponseEntity searchIPDWardPatient(@PathVariable("wardUuid") Str @RequestParam (value = "limit") Integer limit, @RequestParam(value = "searchKeys") List searchKeys, @RequestParam(value = "searchValue") String searchValue, - @RequestParam(value = "sortBy") String sortBy) throws ParseException { + @RequestParam(value = "sortBy", required = false) String sortBy) throws ParseException { try { IPDPatientDetails ipdPatientDetails = ipdWardService.searchIPDPatientsInWard(wardUuid,searchKeys,searchValue,offset,limit,sortBy); return new ResponseEntity<>(IPDPatientDetailsResponse.createFrom(ipdPatientDetails), OK); From db25995cbce127af4eba85d00e6de32161eff875 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 19 Mar 2024 15:39:46 +0530 Subject: [PATCH 56/75] Add a check in generateGroupByClauseForSorting to handle null values --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index bd0c32a..96c7927 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -33,6 +33,8 @@ public HibernateWardDAO(SessionFactory sessionFactory) { private static String generateGroupByClauseForSorting(String sortBy) { String groupBy = " GROUP BY assignment.patient, v "; + sortBy = sortBy != null ? sortBy : "default"; + switch (sortBy) { case "bedNumber": groupBy += " ORDER BY assignment.bed.bedNumber "; From 1206481db9b585dfb7866b661e5f4347d551d325 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 19 Mar 2024 17:36:24 +0530 Subject: [PATCH 57/75] Extract ORDER BY from GROUP BY --- .../ipd/api/dao/impl/HibernateWardDAO.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 96c7927..8042fc0 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -30,20 +30,20 @@ public HibernateWardDAO(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } - private static String generateGroupByClauseForSorting(String sortBy) { - String groupBy = " GROUP BY assignment.patient, v "; + private static String generateOrderByClauseForSorting(String sortBy) { + String orderBy = " "; sortBy = sortBy != null ? sortBy : "default"; switch (sortBy) { case "bedNumber": - groupBy += " ORDER BY assignment.bed.bedNumber "; + orderBy += "ORDER BY assignment.bed.bedNumber "; break; default: - groupBy += " ORDER BY assignment.startDatetime desc "; + orderBy += "ORDER BY assignment.startDatetime desc "; break; } - return groupBy; + return orderBy; } @Override @@ -71,9 +71,11 @@ public List getAdmittedPatients(Location location, Provider pro queryString += "and :dateTime between ctp.startTime and ctp.endTime "; } - String groupBy = generateGroupByClauseForSorting(sortBy); + String groupBy = " GROUP BY assignment.patient, v "; - String finalQuery = queryString + groupBy; + String orderBy = generateOrderByClauseForSorting(sortBy); + + String finalQuery = queryString + groupBy + orderBy; Query query = session.createQuery(finalQuery); @@ -138,10 +140,12 @@ public List searchAdmittedPatients(Location location, List Date: Thu, 21 Mar 2024 17:29:46 +0530 Subject: [PATCH 58/75] Add myPatient count for provider in summary API --- .../openmrs/module/ipd/api/dao/WardDAO.java | 2 +- .../ipd/api/dao/impl/HibernateWardDAO.java | 24 ++++++++++++------- .../ipd/api/model/WardPatientsSummary.java | 2 +- .../module/ipd/api/service/WardService.java | 2 +- .../ipd/api/service/impl/WardServiceImpl.java | 5 ++-- .../IPDWardPatientSummaryResponse.java | 2 ++ .../ipd/controller/IPDWardController.java | 5 ++-- .../module/ipd/service/IPDWardService.java | 2 +- .../ipd/service/impl/IPDWardServiceImpl.java | 4 ++-- 9 files changed, 30 insertions(+), 18 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index f8fb1c7..8447843 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -14,6 +14,6 @@ public interface WardDAO { List getAdmittedPatients(Location location, Provider provider, Date currentDateTime, String sortBy); - WardPatientsSummary getWardPatientSummary(Location location); + WardPatientsSummary getWardPatientSummary(Location location, Provider provider); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 8042fc0..ee73777 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -98,21 +98,29 @@ public List getAdmittedPatients(Location location, Provider pro } @Override - public WardPatientsSummary getWardPatientSummary(Location location) { + public WardPatientsSummary getWardPatientSummary(Location location, Provider provider) { Session session = this.sessionFactory.getCurrentSession(); try { Query query = session.createQuery( - "select NEW org.openmrs.module.ipd.api.model.WardPatientsSummary(COUNT(assignment)) " + - "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + - "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + - "JOIN org.openmrs.Location l on locmap.location = l " + - "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + - "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location"); + "SELECT NEW org.openmrs.module.ipd.api.model.WardPatientsSummary(" + + "COUNT(assignment) AS totalPatients, " + + "COUNT(DISTINCT CASE WHEN ctp.provider = :provider THEN assignment.patient ELSE null END) AS totalProviderPatients) " + + "FROM org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap ON locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l ON locmap.location = l " + + "JOIN org.openmrs.Visit v ON v.patient = assignment.patient " + + "LEFT JOIN CareTeam careTeam ON careTeam.patient = v.patient " + + "LEFT JOIN careTeam.participants ctp " + + "WHERE assignment.endDatetime IS NULL AND v.stopDatetime IS NULL AND l.parentLocation = :location AND (ctp.provider IS NULL OR ctp.provider = :provider)"); + query.setParameter("location", location); + query.setParameter("provider", provider); + return (WardPatientsSummary) query.getSingleResult(); } catch (Exception e) { - log.error("Exception at WardDAO getAdmittedPatients ",e.getStackTrace()); + log.error("Exception at WardDAO getAdmittedPatients ", e.getStackTrace()); } + return new WardPatientsSummary(); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java index ccccf6b..d2da22c 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java @@ -11,8 +11,8 @@ @Getter public class WardPatientsSummary { private Long totalPatients = 0L; + private Long totalProviderPatients = 0L; // to be added in future -// private Integer myPatients; // private Integer toBeDischargedPatients; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java index ac3a7df..e358643 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -8,7 +8,7 @@ public interface WardService { - WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + WardPatientsSummary getIPDWardPatientSummary(String wardUuid, String providerUuid); List getWardPatientsByUuid(String wardUuid, String sortBy); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index 6960022..e890b97 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -28,9 +28,10 @@ public WardServiceImpl(WardDAO wardDAO) { @Override - public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid, String providerUuid) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); - return wardDAO.getWardPatientSummary(location); + Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); + return wardDAO.getWardPatientSummary(location, provider); } @Override diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java index 71c342a..fc3bfa2 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java @@ -12,10 +12,12 @@ public class IPDWardPatientSummaryResponse { private Long totalPatients; + private Long totalProviderPatients; public static IPDWardPatientSummaryResponse createFrom(WardPatientsSummary wardPatientsSummary){ return IPDWardPatientSummaryResponse.builder(). totalPatients(wardPatientsSummary.getTotalPatients()). + totalProviderPatients(wardPatientsSummary.getTotalProviderPatients()). build(); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java index 5ddcd94..61f2e7d 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -32,8 +32,9 @@ public IPDWardController(IPDWardService ipdWardService) { @RequestMapping(value = "{wardUuid}/summary",method = RequestMethod.GET) @ResponseBody - public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") String wardUuid) throws ParseException { - WardPatientsSummary wardPatientsSummary = ipdWardService.getIPDWardPatientSummary(wardUuid); + public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") String wardUuid, + @RequestParam(value = "providerUuid") String providerUuid) throws ParseException { + WardPatientsSummary wardPatientsSummary = ipdWardService.getIPDWardPatientSummary(wardUuid, providerUuid); return new ResponseEntity<>(IPDWardPatientSummaryResponse.createFrom(wardPatientsSummary), OK); } diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java index 51af3e9..97d2b88 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -8,7 +8,7 @@ public interface IPDWardService { - WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + WardPatientsSummary getIPDWardPatientSummary(String wardUuid, String providerUuid); IPDPatientDetails getIPDPatientByWard(String wardUuid, Integer offset, Integer limit, String sortBy); diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java index e97728d..2f487dd 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -26,8 +26,8 @@ public IPDWardServiceImpl(WardService wardService) { @Override - public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { - return wardService.getIPDWardPatientSummary(wardUuid); + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid, String providerUuid) { + return wardService.getIPDWardPatientSummary(wardUuid, providerUuid); } @Override From b208b497e78362ccd35ec4dcb8aa1e6e20fad391 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Fri, 22 Mar 2024 16:55:23 +0530 Subject: [PATCH 59/75] Include void check for provider patients --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index ee73777..703727b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -58,7 +58,7 @@ public List getAdmittedPatients(Location location, Provider pro "LEFT JOIN CareTeam careTeam on careTeam.visit = v " + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + - "LEFT JOIN careTeam.participants ctp " + + "LEFT JOIN careTeam.participants ctp ON ctp.voided = 0 " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + "LEFT JOIN Slot s on s.order = o " + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location "; From 29ae1677262e62cd3a36547ecd5ab852db31452a Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Fri, 22 Mar 2024 16:56:44 +0530 Subject: [PATCH 60/75] Include currentDateTime for provider shift validation --- .../openmrs/module/ipd/api/dao/WardDAO.java | 2 +- .../ipd/api/dao/impl/HibernateWardDAO.java | 48 ++++++++++++------- .../ipd/api/service/impl/WardServiceImpl.java | 3 +- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java index 8447843..c08b66a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -14,6 +14,6 @@ public interface WardDAO { List getAdmittedPatients(Location location, Provider provider, Date currentDateTime, String sortBy); - WardPatientsSummary getWardPatientSummary(Location location, Provider provider); + WardPatientsSummary getWardPatientSummary(Location location, Provider provider, Date currentDateTime); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index 703727b..ffecf28 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -98,27 +98,43 @@ public List getAdmittedPatients(Location location, Provider pro } @Override - public WardPatientsSummary getWardPatientSummary(Location location, Provider provider) { + public WardPatientsSummary getWardPatientSummary(Location location, Provider provider, Date dateTime) { Session session = this.sessionFactory.getCurrentSession(); try { - Query query = session.createQuery( - "SELECT NEW org.openmrs.module.ipd.api.model.WardPatientsSummary(" + - "COUNT(assignment) AS totalPatients, " + - "COUNT(DISTINCT CASE WHEN ctp.provider = :provider THEN assignment.patient ELSE null END) AS totalProviderPatients) " + - "FROM org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + - "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap ON locmap.bed = assignment.bed " + - "JOIN org.openmrs.Location l ON locmap.location = l " + - "JOIN org.openmrs.Visit v ON v.patient = assignment.patient " + - "LEFT JOIN CareTeam careTeam ON careTeam.patient = v.patient " + - "LEFT JOIN careTeam.participants ctp " + - "WHERE assignment.endDatetime IS NULL AND v.stopDatetime IS NULL AND l.parentLocation = :location AND (ctp.provider IS NULL OR ctp.provider = :provider)"); + Query totalPatientsQuery = session.createQuery( + "SELECT COUNT(assignment) " + + "FROM org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap ON locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l ON locmap.location = l " + + "JOIN org.openmrs.Visit v ON v.patient = assignment.patient " + + "WHERE assignment.endDatetime IS NULL AND v.stopDatetime IS NULL AND l.parentLocation = :location" + ); + + totalPatientsQuery.setParameter("location", location); + + Long totalPatients = (Long) totalPatientsQuery.uniqueResult(); + + Query totalProviderPatientsQuery = session.createQuery( + "SELECT COUNT(DISTINCT CASE WHEN ctp.provider = :provider THEN assignment.patient ELSE null END) " + + "FROM org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap ON locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l ON locmap.location = l " + + "JOIN org.openmrs.Visit v ON v.patient = assignment.patient " + + "LEFT JOIN CareTeam careTeam ON careTeam.patient = v.patient " + + "LEFT JOIN careTeam.participants ctp ON ctp.voided = 0 " + + "WHERE assignment.endDatetime IS NULL AND v.stopDatetime IS NULL AND l.parentLocation = :location " + + "AND (ctp.provider = :provider AND :dateTime BETWEEN ctp.startTime AND ctp.endTime)" + ); - query.setParameter("location", location); - query.setParameter("provider", provider); + totalProviderPatientsQuery.setParameter("location", location); + totalProviderPatientsQuery.setParameter("provider", provider); + totalProviderPatientsQuery.setParameter("dateTime", dateTime); + + Long totalProviderPatients = (Long) totalProviderPatientsQuery.uniqueResult(); - return (WardPatientsSummary) query.getSingleResult(); + return new WardPatientsSummary(totalPatients, totalProviderPatients); } catch (Exception e) { - log.error("Exception at WardDAO getAdmittedPatients ", e.getStackTrace()); + log.error("Exception at WardDAO getAdmittedPatients ", e); } return new WardPatientsSummary(); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index e890b97..f91506d 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -31,7 +31,8 @@ public WardServiceImpl(WardDAO wardDAO) { public WardPatientsSummary getIPDWardPatientSummary(String wardUuid, String providerUuid) { Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); Provider provider = Context.getProviderService().getProviderByUuid(providerUuid); - return wardDAO.getWardPatientSummary(location, provider); + Date currentDateTime = new Date(); + return wardDAO.getWardPatientSummary(location, provider, currentDateTime); } @Override From f219c9aaf08961296cc21385674feaa7ef4e7e2f Mon Sep 17 00:00:00 2001 From: kavitha-sundararajan <90255023+kavitha-sundararajan@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:18:14 +0530 Subject: [PATCH 61/75] BAH-3723|Kavitha| Event handling model & create task for admit event (#48) * BAH-3723|Kavitha| add event handling model and create task for admit event * Kavitha| add null check for event type * Kavitha | update fhir2 extension module version --- api/pom.xml | 12 +++++ omod/pom.xml | 12 +++++ .../module/ipd/events/ConfigLoader.java | 41 +++++++++++++++ .../module/ipd/events/IPDEventManager.java | 36 +++++++++++++ .../module/ipd/events/IPDEventUtils.java | 22 ++++++++ .../ipd/events/factory/IPDEventFactory.java | 8 +++ .../factory/impl/IPDEventFactoryImpl.java | 38 ++++++++++++++ .../ipd/events/handler/IPDEventHandler.java | 7 +++ .../impl/PatientAdmitEventHandler.java | 52 +++++++++++++++++++ .../impl/RolloverTaskEventHandler.java | 29 +++++++++++ .../impl/ShiftStartTaskEventHandler.java | 28 ++++++++++ .../module/ipd/events/model/ConfigDetail.java | 19 +++++++ .../module/ipd/events/model/IPDEvent.java | 18 +++++++ .../module/ipd/events/model/IPDEventType.java | 7 +++ .../module/ipd/events/model/TaskDetail.java | 16 ++++++ .../postprocessor/IPDTransactionHandler.java | 11 ++++ .../src/main/resources/application.properties | 3 ++ omod/src/main/resources/config.xml | 1 + .../resources/webModuleApplicationContext.xml | 1 + pom.xml | 18 ++++++- 20 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java create mode 100644 omod/src/main/resources/application.properties diff --git a/api/pom.xml b/api/pom.xml index f119a5e..cc20907 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -145,6 +145,18 @@ provided + + org.bahmni.module + fhir2Extension-api + provided + + + + org.bahmni.module + fhir2Extension-omod + provided + + org.bahmni.module medication-administration-api diff --git a/omod/pom.xml b/omod/pom.xml index 8895021..11a3f26 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -123,6 +123,18 @@ provided + + org.bahmni.module + fhir2Extension-api + provided + + + + org.bahmni.module + fhir2Extension-omod + provided + + org.openmrs.module emrapi-api diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java b/omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java new file mode 100644 index 0000000..3b390fa --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java @@ -0,0 +1,41 @@ +package org.openmrs.module.ipd.events; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.events.model.ConfigDetail; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Component +@Slf4j +public class ConfigLoader { + private List configs = new ArrayList<>(); + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Value("${config-file.path}") + private String routeConfigurationFileLocation; + + public List getConfigs() { + if (configs.isEmpty()) { + loadConfiguration(); + } + return this.configs; + } + + private void loadConfiguration() { + try { + File routeConfigurationFile = new FileSystemResource(routeConfigurationFileLocation).getFile(); + this.configs = objectMapper.readValue(routeConfigurationFile, new TypeReference>() {}); + } catch (IOException exception) { + log.error("Failed to load configuration for file : " + routeConfigurationFileLocation, exception); + } + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java b/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java new file mode 100644 index 0000000..7614774 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java @@ -0,0 +1,36 @@ +package org.openmrs.module.ipd.events; + +import org.openmrs.module.ipd.events.factory.IPDEventFactory; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.events.model.IPDEventType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IPDEventManager { + @Autowired + ConfigLoader configLoader; + + @Autowired + IPDEventFactory eventFactory; + + public IPDEventType getEventTypeForEncounter(String type) { + switch (type) { + case "ADMISSION": + return IPDEventType.PATIENT_ADMIT; + case "SHIFT_START_TASK": + return IPDEventType.SHIFT_START_TASK; + case "ROLLOVER_TASK": + return IPDEventType.ROLLOVER_TASK; + default: + return null; + } + } + + public void processEvent(IPDEvent event) { + IPDEventHandler handler = eventFactory.createEventHandler(event.getIpdEventType()); + handler.handleEvent(event); + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java b/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java new file mode 100644 index 0000000..42abc30 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java @@ -0,0 +1,22 @@ +package org.openmrs.module.ipd.events; + +import org.openmrs.module.fhir2.model.FhirTask; +import org.openmrs.module.fhirExtension.web.contract.TaskRequest; +import org.openmrs.module.ipd.events.model.IPDEvent; + +import java.util.Date; + +public class IPDEventUtils { + + public static TaskRequest createNonMedicationTaskRequest(IPDEvent ipdEvent, String name, String taskType) { + TaskRequest taskRequest = new TaskRequest(); + taskRequest.setName(name); + taskRequest.setTaskType(taskType); + taskRequest.setEncounterUuid(ipdEvent.getEncounterUuid()); + taskRequest.setPatientUuid(ipdEvent.getPatientUuid()); + taskRequest.setRequestedStartTime(new Date()); + taskRequest.setIntent(FhirTask.TaskIntent.ORDER); + taskRequest.setStatus(FhirTask.TaskStatus.REQUESTED); + return taskRequest; + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java b/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java new file mode 100644 index 0000000..690a467 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java @@ -0,0 +1,8 @@ +package org.openmrs.module.ipd.events.factory; + +import org.openmrs.module.ipd.events.model.IPDEventType; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; + +public interface IPDEventFactory { + IPDEventHandler createEventHandler(IPDEventType eventType); +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java b/omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java new file mode 100644 index 0000000..faf7ddb --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java @@ -0,0 +1,38 @@ +package org.openmrs.module.ipd.events.factory.impl; + +import org.openmrs.module.ipd.events.model.IPDEventType; +import org.openmrs.module.ipd.events.factory.IPDEventFactory; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.events.handler.impl.PatientAdmitEventHandler; +import org.openmrs.module.ipd.events.handler.impl.RolloverTaskEventHandler; +import org.openmrs.module.ipd.events.handler.impl.ShiftStartTaskEventHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IPDEventFactoryImpl implements IPDEventFactory { + + @Autowired + PatientAdmitEventHandler patientAdmitEventHandler; + + @Autowired + ShiftStartTaskEventHandler shiftStartTaskEventHandler; + + @Autowired + RolloverTaskEventHandler rolloverTaskEventHandler; + + @Override + public IPDEventHandler createEventHandler(IPDEventType eventType) { + switch (eventType) { + case PATIENT_ADMIT: + return patientAdmitEventHandler; + case SHIFT_START_TASK: + return shiftStartTaskEventHandler; + case ROLLOVER_TASK: + return rolloverTaskEventHandler; + default: + throw new IllegalArgumentException("Unsupported event type: " + eventType); + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java new file mode 100644 index 0000000..27b1cca --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java @@ -0,0 +1,7 @@ +package org.openmrs.module.ipd.events.handler; + +import org.openmrs.module.ipd.events.model.IPDEvent; + +public interface IPDEventHandler { + void handleEvent(IPDEvent event); +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java new file mode 100644 index 0000000..e9717da --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java @@ -0,0 +1,52 @@ +package org.openmrs.module.ipd.events.handler.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openmrs.module.fhirExtension.model.Task; +import org.openmrs.module.fhirExtension.service.TaskService; +import org.openmrs.module.fhirExtension.web.contract.TaskRequest; +import org.openmrs.module.fhirExtension.web.mapper.TaskMapper; +import org.openmrs.module.ipd.events.ConfigLoader; +import org.openmrs.module.ipd.events.IPDEventUtils; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.events.model.ConfigDetail; +import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.events.model.TaskDetail; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class PatientAdmitEventHandler implements IPDEventHandler { + + private final Log log = LogFactory.getLog(this.getClass()); + + @Autowired + ConfigLoader configLoader; + + @Autowired + private TaskMapper taskMapper; + + @Autowired + private TaskService taskService; + + @Override + public void handleEvent(IPDEvent event) { + List configList = configLoader.getConfigs(); + ConfigDetail eventConfig = configList.stream() + .filter(config -> config.getType().equals(event.getIpdEventType().name())) + .findFirst() + .orElse(null); + if (eventConfig != null) { + for(TaskDetail taskDetail : eventConfig.getTasks()) { + TaskRequest taskRequest = IPDEventUtils.createNonMedicationTaskRequest(event, taskDetail.getName(), "nursing_activity_system"); + Task task = taskMapper.fromRequest(taskRequest); + taskService.saveTask(task); + log.info("Task created " + taskDetail.getName()); + } + } + + + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java new file mode 100644 index 0000000..71f0def --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java @@ -0,0 +1,29 @@ +package org.openmrs.module.ipd.events.handler.impl; + +import org.openmrs.module.ipd.events.ConfigLoader; +import org.openmrs.module.ipd.events.model.ConfigDetail; +import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class RolloverTaskEventHandler implements IPDEventHandler { + + @Autowired + ConfigLoader configLoader; + + @Override + public void handleEvent(IPDEvent event) { + List configList = configLoader.getConfigs(); + ConfigDetail eventConfig = configList.stream() + .filter(config -> config.getType().equals(event.getIpdEventType().name())) + .findFirst() + .orElse(null); + System.out.println("eventConfig type RolloverTaskEventHandler " + eventConfig.getType()); + System.out.println("eventConfig tasks RolloverTaskEventHandler " + eventConfig.getTasks() + " size --- " + eventConfig.getTasks().size()); + //create task based on configuration + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java new file mode 100644 index 0000000..603e59a --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java @@ -0,0 +1,28 @@ +package org.openmrs.module.ipd.events.handler.impl; + +import org.openmrs.module.ipd.events.ConfigLoader; +import org.openmrs.module.ipd.events.model.ConfigDetail; +import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class ShiftStartTaskEventHandler implements IPDEventHandler { + + @Autowired + ConfigLoader configLoader; + + @Override + public void handleEvent(IPDEvent event) { + List configList = configLoader.getConfigs(); + ConfigDetail eventConfig = configList.stream() + .filter(config -> config.getType().equals(event.getIpdEventType().name())) + .findFirst() + .orElse(null); + + //create task based on configuration + } +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java b/omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java new file mode 100644 index 0000000..8eae262 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java @@ -0,0 +1,19 @@ +package org.openmrs.module.ipd.events.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ConfigDetail { + private String type; + private List tasks; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java b/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java new file mode 100644 index 0000000..e812c49 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java @@ -0,0 +1,18 @@ +package org.openmrs.module.ipd.events.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class IPDEvent { + private String encounterUuid; + private String patientUuid; + private IPDEventType ipdEventType; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java b/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java new file mode 100644 index 0000000..52196f0 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java @@ -0,0 +1,7 @@ +package org.openmrs.module.ipd.events.model; + +public enum IPDEventType { + PATIENT_ADMIT, + SHIFT_START_TASK, + ROLLOVER_TASK; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java b/omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java new file mode 100644 index 0000000..e5de905 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java @@ -0,0 +1,16 @@ +package org.openmrs.module.ipd.events.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class TaskDetail { + private String name; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java index 81c74aa..82c9825 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java +++ b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java @@ -3,9 +3,12 @@ import org.openmrs.Encounter; import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.emrapi.encounter.postprocessor.EncounterTransactionHandler; +import org.openmrs.module.ipd.events.model.IPDEvent; import org.openmrs.module.ipd.service.IPDScheduleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.openmrs.module.ipd.events.model.IPDEventType; +import org.openmrs.module.ipd.events.IPDEventManager; @Component public class IPDTransactionHandler implements EncounterTransactionHandler { @@ -13,6 +16,9 @@ public class IPDTransactionHandler implements EncounterTransactionHandler { @Autowired IPDScheduleService ipdScheduleService; + @Autowired + IPDEventManager eventManager; + @Override public void forRead(Encounter encounter, EncounterTransaction encounterTransaction) { // No Implementation needed as of now @@ -20,6 +26,11 @@ public void forRead(Encounter encounter, EncounterTransaction encounterTransacti @Override public void forSave(Encounter encounter, EncounterTransaction encounterTransaction) { + IPDEventType eventType = eventManager.getEventTypeForEncounter(encounter.getEncounterType().getName()); + if (eventType != null) { + IPDEvent ipdEvent = new IPDEvent(encounter.getUuid(), encounter.getPatient().getUuid(), eventType); + eventManager.processEvent(ipdEvent); + } ipdScheduleService.handlePostProcessEncounterTransaction(encounter,encounterTransaction); } } diff --git a/omod/src/main/resources/application.properties b/omod/src/main/resources/application.properties new file mode 100644 index 0000000..ed16b69 --- /dev/null +++ b/omod/src/main/resources/application.properties @@ -0,0 +1,3 @@ + +# Route definitions +config-file.path=/etc/bahmni_config/openmrs/apps/ipdDashboard/eventsConfig.json \ No newline at end of file diff --git a/omod/src/main/resources/config.xml b/omod/src/main/resources/config.xml index 7c18b69..6a691b1 100644 --- a/omod/src/main/resources/config.xml +++ b/omod/src/main/resources/config.xml @@ -14,6 +14,7 @@ org.bahmni.module.bahmnicore org.openmrs.module.bedmanagement org.bahmni.module.medication-administration + org.bahmni.module.fhir2Extension org.openmrs.module.ipd.api.IPDActivator diff --git a/omod/src/main/resources/webModuleApplicationContext.xml b/omod/src/main/resources/webModuleApplicationContext.xml index 82e84de..a12d5d4 100644 --- a/omod/src/main/resources/webModuleApplicationContext.xml +++ b/omod/src/main/resources/webModuleApplicationContext.xml @@ -8,4 +8,5 @@ + diff --git a/pom.xml b/pom.xml index 1a8a3be..65aaef0 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,8 @@ -Xmx1024m 0.7.9 1.18.26 - 1.11.0 + 2.0.0-SNAPSHOT + 1.3.0.ipd-SNAPSHOT 0.94-SNAPSHOT 1.32.0 @@ -197,6 +198,21 @@ provided + + org.bahmni.module + fhir2Extension-api + ${fhir2ExtensionVersion} + provided + + + + + org.bahmni.module + fhir2Extension-omod + ${fhir2ExtensionVersion} + provided + + org.bahmni.module medication-administration-api From d478f15e31ad3227b8ca777fe22cde3752685384 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:45:55 +0530 Subject: [PATCH 62/75] Add scheduler, liquibase and handleEvent for shift start task --- .../ipd/api/dao/impl/HibernateWardDAO.java | 8 +++- .../module/ipd/api/service/WardService.java | 2 + .../ipd/api/service/impl/WardServiceImpl.java | 4 ++ api/src/main/resources/liquibase.xml | 16 +++++++ omod/pom.xml | 5 +++ .../impl/ShiftStartTaskEventHandler.java | 45 ++++++++++++++++++- .../module/ipd/scheduler/ShiftStartTasks.java | 22 +++++++++ 7 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index ffecf28..ebe2a19 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -61,8 +61,12 @@ public List getAdmittedPatients(Location location, Provider pro "LEFT JOIN careTeam.participants ctp ON ctp.voided = 0 " + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + "LEFT JOIN Slot s on s.order = o " + - "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location "; - + "where assignment.endDatetime is null and v.stopDatetime is null "; + + if(location != null){ + queryString += "and l.parentLocation = :location "; + } + if (provider != null) { queryString += "and ctp.provider = :provider "; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java index e358643..070999a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -15,4 +15,6 @@ public interface WardService { List searchWardPatients(String wardUuid, List searchKeys, String searchValue, String sortBy); List getPatientsByWardAndProvider(String wardUuid, String providerUuid, String sortBy); + + List getAdmittedPatients(); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java index f91506d..72dc5dd 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -55,4 +55,8 @@ public List searchWardPatients(String wardUuid, List se return wardDAO.searchAdmittedPatients(location,searchKeys,searchValue,sortBy); } + @Override + public List getAdmittedPatients() { + return wardDAO.getAdmittedPatients(null,null, null, null); + } } diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index dd87526..6f73d85 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -404,4 +404,20 @@ + + + + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Mark Slots As Missed"; + + + + INSERT INTO + scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, + start_on_startup, created_by, date_created, uuid) + VALUES + ('Shift Start Tasks', 'Shift Start Tasks', 'org.openmrs.module.ipd.scheduler.ShiftStartTasks', + TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 120, false, 1, NOW(), UUID()); + + + diff --git a/omod/pom.xml b/omod/pom.xml index 11a3f26..156e1d2 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -181,6 +181,11 @@ 2.1 compile + + ${project.parent.groupId} + ${project.parent.artifactId}-api + ${project.parent.version} + \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java index 603e59a..c829f74 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java +++ b/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java @@ -1,28 +1,69 @@ package org.openmrs.module.ipd.events.handler.impl; +import org.openmrs.api.EncounterService; +import org.openmrs.api.context.Context; +import org.openmrs.module.emrapi.encounter.ActiveEncounterParameters; +import org.openmrs.module.emrapi.encounter.EmrEncounterService; +import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; +import org.openmrs.module.fhirExtension.model.Task; +import org.openmrs.module.fhirExtension.web.contract.TaskRequest; +import org.openmrs.module.fhirExtension.web.mapper.TaskMapper; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.service.WardService; import org.openmrs.module.ipd.events.ConfigLoader; +import org.openmrs.module.ipd.events.IPDEventUtils; +import org.openmrs.module.ipd.events.handler.IPDEventHandler; import org.openmrs.module.ipd.events.model.ConfigDetail; import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.events.model.TaskDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.List; @Component public class ShiftStartTaskEventHandler implements IPDEventHandler { + private static final String CONSULTATION_ENCOUNTER_TYPE = "Consultation"; @Autowired ConfigLoader configLoader; + private EncounterService encounterService; + private EmrEncounterService emrEncounterService; + + @Autowired + private TaskMapper taskMapper; @Override public void handleEvent(IPDEvent event) { + + WardService wardService = Context.getService(WardService.class); + // - getAdmit - wardDAO.getAdmittedPatients + List admittedPatients = wardService.getAdmittedPatients(); + +// encounterService.setEncounterType(); + List configList = configLoader.getConfigs(); ConfigDetail eventConfig = configList.stream() .filter(config -> config.getType().equals(event.getIpdEventType().name())) .findFirst() .orElse(null); - //create task based on configuration + List tasks = new ArrayList(); + for(AdmittedPatient admittedPatient: admittedPatients){ + ActiveEncounterParameters activeEncounterParameters = new ActiveEncounterParameters(); + String patientUuid = admittedPatient.getBedPatientAssignment().getPatient().getUuid(); + activeEncounterParameters.setPatientUuid(patientUuid); + activeEncounterParameters.setEncounterTypeUuid(encounterService.getEncounterType(CONSULTATION_ENCOUNTER_TYPE).getUuid()); + EncounterTransaction encounterTransaction = emrEncounterService.getActiveEncounter(activeEncounterParameters); + IPDEvent ipdEvent = new IPDEvent(encounterTransaction.getEncounterUuid(), patientUuid, event.getIpdEventType()); + for(TaskDetail taskDetail : eventConfig.getTasks()) { + TaskRequest taskRequest = IPDEventUtils.createNonMedicationTaskRequest(ipdEvent, taskDetail.getName(), "nursing_activity_system"); + Task task = taskMapper.fromRequest(taskRequest); + tasks.add(task); + } + } + +// bulkSaveTasks(List tasks); } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java b/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java new file mode 100644 index 0000000..2276d4e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java @@ -0,0 +1,22 @@ +package org.openmrs.module.ipd.scheduler; + +import org.openmrs.module.ipd.events.IPDEventManager; +import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.events.model.IPDEventType; +import org.openmrs.scheduler.tasks.AbstractTask; +import org.springframework.beans.factory.annotation.Autowired; + +public class ShiftStartTasks extends AbstractTask { + + @Autowired + private IPDEventManager eventManager; + + @Override + public void execute() { + IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.SHIFT_START_TASK)); + if (eventType != null) { + IPDEvent ipdEvent = new IPDEvent(null, null, eventType); + eventManager.processEvent(ipdEvent); + } + } +} From 78f9673f2f84930c53298079144f2c6c31a0b6e8 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:37:49 +0530 Subject: [PATCH 63/75] Move Events to api, refactor and include shift start task scheduler --- .../module/ipd/api}/events/ConfigLoader.java | 4 +-- .../ipd/api}/events/IPDEventManager.java | 10 +++--- .../module/ipd/api}/events/IPDEventUtils.java | 4 +-- .../api/events/factory/IPDEventFactory.java | 8 +++++ .../factory/impl/IPDEventFactoryImpl.java | 14 ++++---- .../api/events/handler/IPDEventHandler.java | 7 ++++ .../impl/PatientAdmitEventHandler.java | 14 ++++---- .../impl/RolloverTaskEventHandler.java | 10 +++--- .../impl/ShiftStartTaskEventHandler.java | 28 ++++++++++------ .../ipd/api}/events/model/ConfigDetail.java | 2 +- .../ipd/api}/events/model/IPDEvent.java | 2 +- .../ipd/api}/events/model/IPDEventType.java | 2 +- .../ipd/api}/events/model/TaskDetail.java | 2 +- .../api/scheduler/tasks/ShiftStartTasks.java | 32 +++++++++++++++++++ api/src/main/resources/liquibase.xml | 4 +-- .../ipd/events/factory/IPDEventFactory.java | 8 ----- .../ipd/events/handler/IPDEventHandler.java | 7 ---- .../postprocessor/IPDTransactionHandler.java | 6 ++-- .../module/ipd/scheduler/ShiftStartTasks.java | 22 ------------- 19 files changed, 102 insertions(+), 84 deletions(-) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/ConfigLoader.java (92%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/IPDEventManager.java (74%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/IPDEventUtils.java (88%) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/events/factory/IPDEventFactory.java rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/factory/impl/IPDEventFactoryImpl.java (64%) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/events/handler/IPDEventHandler.java rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/handler/impl/PatientAdmitEventHandler.java (79%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/handler/impl/RolloverTaskEventHandler.java (75%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/handler/impl/ShiftStartTaskEventHandler.java (75%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/model/ConfigDetail.java (90%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/model/IPDEvent.java (91%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/model/IPDEventType.java (64%) rename {omod/src/main/java/org/openmrs/module/ipd => api/src/main/java/org/openmrs/module/ipd/api}/events/model/TaskDetail.java (89%) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java delete mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java delete mode 100644 omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java delete mode 100644 omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java b/api/src/main/java/org/openmrs/module/ipd/api/events/ConfigLoader.java similarity index 92% rename from omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/ConfigLoader.java index 3b390fa..fc58629 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/ConfigLoader.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/ConfigLoader.java @@ -1,9 +1,9 @@ -package org.openmrs.module.ipd.events; +package org.openmrs.module.ipd.api.events; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.openmrs.module.ipd.events.model.ConfigDetail; +import org.openmrs.module.ipd.api.events.model.ConfigDetail; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.FileSystemResource; import org.springframework.stereotype.Component; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventManager.java similarity index 74% rename from omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventManager.java index 7614774..d98f77e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventManager.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventManager.java @@ -1,9 +1,9 @@ -package org.openmrs.module.ipd.events; +package org.openmrs.module.ipd.api.events; -import org.openmrs.module.ipd.events.factory.IPDEventFactory; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; -import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.model.IPDEventType; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.factory.IPDEventFactory; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.api.events.model.IPDEventType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java similarity index 88% rename from omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java index 42abc30..b9da7ab 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/IPDEventUtils.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java @@ -1,8 +1,8 @@ -package org.openmrs.module.ipd.events; +package org.openmrs.module.ipd.api.events; import org.openmrs.module.fhir2.model.FhirTask; import org.openmrs.module.fhirExtension.web.contract.TaskRequest; -import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.IPDEvent; import java.util.Date; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/factory/IPDEventFactory.java b/api/src/main/java/org/openmrs/module/ipd/api/events/factory/IPDEventFactory.java new file mode 100644 index 0000000..125fe81 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/factory/IPDEventFactory.java @@ -0,0 +1,8 @@ +package org.openmrs.module.ipd.api.events.factory; + +import org.openmrs.module.ipd.api.events.model.IPDEventType; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; + +public interface IPDEventFactory { + IPDEventHandler createEventHandler(IPDEventType eventType); +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/events/factory/impl/IPDEventFactoryImpl.java similarity index 64% rename from omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/factory/impl/IPDEventFactoryImpl.java index faf7ddb..cb13de8 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/factory/impl/IPDEventFactoryImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/factory/impl/IPDEventFactoryImpl.java @@ -1,11 +1,11 @@ -package org.openmrs.module.ipd.events.factory.impl; +package org.openmrs.module.ipd.api.events.factory.impl; -import org.openmrs.module.ipd.events.model.IPDEventType; -import org.openmrs.module.ipd.events.factory.IPDEventFactory; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; -import org.openmrs.module.ipd.events.handler.impl.PatientAdmitEventHandler; -import org.openmrs.module.ipd.events.handler.impl.RolloverTaskEventHandler; -import org.openmrs.module.ipd.events.handler.impl.ShiftStartTaskEventHandler; +import org.openmrs.module.ipd.api.events.handler.impl.ShiftStartTaskEventHandler; +import org.openmrs.module.ipd.api.events.model.IPDEventType; +import org.openmrs.module.ipd.api.events.factory.IPDEventFactory; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.api.events.handler.impl.PatientAdmitEventHandler; +import org.openmrs.module.ipd.api.events.handler.impl.RolloverTaskEventHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/IPDEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/IPDEventHandler.java new file mode 100644 index 0000000..4c75fdf --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/IPDEventHandler.java @@ -0,0 +1,7 @@ +package org.openmrs.module.ipd.api.events.handler; + +import org.openmrs.module.ipd.api.events.model.IPDEvent; + +public interface IPDEventHandler { + void handleEvent(IPDEvent event); +} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/PatientAdmitEventHandler.java similarity index 79% rename from omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/PatientAdmitEventHandler.java index e9717da..9828da5 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/PatientAdmitEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/PatientAdmitEventHandler.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.handler.impl; +package org.openmrs.module.ipd.api.events.handler.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -6,12 +6,12 @@ import org.openmrs.module.fhirExtension.service.TaskService; import org.openmrs.module.fhirExtension.web.contract.TaskRequest; import org.openmrs.module.fhirExtension.web.mapper.TaskMapper; -import org.openmrs.module.ipd.events.ConfigLoader; -import org.openmrs.module.ipd.events.IPDEventUtils; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; -import org.openmrs.module.ipd.events.model.ConfigDetail; -import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.model.TaskDetail; +import org.openmrs.module.ipd.api.events.ConfigLoader; +import org.openmrs.module.ipd.api.events.IPDEventUtils; +import org.openmrs.module.ipd.api.events.model.ConfigDetail; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.TaskDetail; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java similarity index 75% rename from omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java index 71f0def..de89020 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/RolloverTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java @@ -1,9 +1,9 @@ -package org.openmrs.module.ipd.events.handler.impl; +package org.openmrs.module.ipd.api.events.handler.impl; -import org.openmrs.module.ipd.events.ConfigLoader; -import org.openmrs.module.ipd.events.model.ConfigDetail; -import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.api.events.model.ConfigDetail; +import org.openmrs.module.ipd.api.events.ConfigLoader; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java similarity index 75% rename from omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java index c829f74..930fb1c 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/handler/impl/ShiftStartTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.handler.impl; +package org.openmrs.module.ipd.api.events.handler.impl; import org.openmrs.api.EncounterService; import org.openmrs.api.context.Context; @@ -6,16 +6,17 @@ import org.openmrs.module.emrapi.encounter.EmrEncounterService; import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.fhirExtension.model.Task; +import org.openmrs.module.fhirExtension.service.TaskService; import org.openmrs.module.fhirExtension.web.contract.TaskRequest; import org.openmrs.module.fhirExtension.web.mapper.TaskMapper; +import org.openmrs.module.ipd.api.events.ConfigLoader; +import org.openmrs.module.ipd.api.events.IPDEventUtils; +import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.api.events.model.ConfigDetail; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.TaskDetail; import org.openmrs.module.ipd.api.model.AdmittedPatient; import org.openmrs.module.ipd.api.service.WardService; -import org.openmrs.module.ipd.events.ConfigLoader; -import org.openmrs.module.ipd.events.IPDEventUtils; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; -import org.openmrs.module.ipd.events.model.ConfigDetail; -import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.model.TaskDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,10 +34,13 @@ public class ShiftStartTaskEventHandler implements IPDEventHandler { @Autowired private TaskMapper taskMapper; + @Autowired + private TaskService taskService; + @Override public void handleEvent(IPDEvent event) { - + System.out.println("Inside HandleEvent"); WardService wardService = Context.getService(WardService.class); // - getAdmit - wardDAO.getAdmittedPatients List admittedPatients = wardService.getAdmittedPatients(); @@ -56,6 +60,8 @@ public void handleEvent(IPDEvent event) { activeEncounterParameters.setPatientUuid(patientUuid); activeEncounterParameters.setEncounterTypeUuid(encounterService.getEncounterType(CONSULTATION_ENCOUNTER_TYPE).getUuid()); EncounterTransaction encounterTransaction = emrEncounterService.getActiveEncounter(activeEncounterParameters); + System.out.println("encounterTransaction "+encounterTransaction+ " - "+ encounterTransaction.getEncounterUuid()); + System.out.println("patientUuid "+ patientUuid); IPDEvent ipdEvent = new IPDEvent(encounterTransaction.getEncounterUuid(), patientUuid, event.getIpdEventType()); for(TaskDetail taskDetail : eventConfig.getTasks()) { TaskRequest taskRequest = IPDEventUtils.createNonMedicationTaskRequest(ipdEvent, taskDetail.getName(), "nursing_activity_system"); @@ -63,7 +69,9 @@ public void handleEvent(IPDEvent event) { tasks.add(task); } } - -// bulkSaveTasks(List tasks); + System.out.println("tasks --> "+tasks.size()); + if(tasks.size() > 0){ + taskService.bulkSaveTasks(tasks); + } } } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/ConfigDetail.java similarity index 90% rename from omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/model/ConfigDetail.java index 8eae262..284f2a5 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/model/ConfigDetail.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/ConfigDetail.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.model; +package org.openmrs.module.ipd.api.events.model; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java similarity index 91% rename from omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java index e812c49..dc5cf9b 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEvent.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.model; +package org.openmrs.module.ipd.api.events.model; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEventType.java similarity index 64% rename from omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEventType.java index 52196f0..e74030c 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/model/IPDEventType.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEventType.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.model; +package org.openmrs.module.ipd.api.events.model; public enum IPDEventType { PATIENT_ADMIT, diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/TaskDetail.java similarity index 89% rename from omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java rename to api/src/main/java/org/openmrs/module/ipd/api/events/model/TaskDetail.java index e5de905..7b1426f 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/events/model/TaskDetail.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/TaskDetail.java @@ -1,4 +1,4 @@ -package org.openmrs.module.ipd.events.model; +package org.openmrs.module.ipd.api.events.model; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java new file mode 100644 index 0000000..1e421d1 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java @@ -0,0 +1,32 @@ +package org.openmrs.module.ipd.api.scheduler.tasks; + +import org.openmrs.module.ipd.api.events.IPDEventManager; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.IPDEventType; +import org.openmrs.module.ipd.api.service.SlotService; +import org.openmrs.scheduler.tasks.AbstractTask; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +public class ShiftStartTasks extends AbstractTask implements ApplicationContextAware { + + private ApplicationContext context; +// IPDEventManager eventManager; + @Override + public void execute() { + IPDEventManager eventManager = context.getBean(IPDEventManager.class); + System.out.println("Started Shift Schedule"); + System.out.println("Shift Start Task"+IPDEventType.SHIFT_START_TASK); + IPDEventType eventType = eventManager.getEventTypeForEncounter("SHIFT_START_TASK"); + System.out.println("eventType"+ eventType); + if (eventType != null) { + IPDEvent ipdEvent = new IPDEvent(null, null, eventType); + eventManager.processEvent(ipdEvent); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.context = applicationContext; + } +} diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 6f73d85..c40e067 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -407,7 +407,7 @@ - SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Mark Slots As Missed"; + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Start Tasks"; @@ -415,7 +415,7 @@ scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, start_on_startup, created_by, date_created, uuid) VALUES - ('Shift Start Tasks', 'Shift Start Tasks', 'org.openmrs.module.ipd.scheduler.ShiftStartTasks', + ('Shift Start Tasks', 'Shift Start Tasks', 'org.openmrs.module.ipd.api.scheduler.tasks.ShiftStartTasks', TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 120, false, 1, NOW(), UUID()); diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java b/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java deleted file mode 100644 index 690a467..0000000 --- a/omod/src/main/java/org/openmrs/module/ipd/events/factory/IPDEventFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.openmrs.module.ipd.events.factory; - -import org.openmrs.module.ipd.events.model.IPDEventType; -import org.openmrs.module.ipd.events.handler.IPDEventHandler; - -public interface IPDEventFactory { - IPDEventHandler createEventHandler(IPDEventType eventType); -} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java b/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java deleted file mode 100644 index 27b1cca..0000000 --- a/omod/src/main/java/org/openmrs/module/ipd/events/handler/IPDEventHandler.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.openmrs.module.ipd.events.handler; - -import org.openmrs.module.ipd.events.model.IPDEvent; - -public interface IPDEventHandler { - void handleEvent(IPDEvent event); -} \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java index 82c9825..d12737e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java +++ b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java @@ -3,12 +3,12 @@ import org.openmrs.Encounter; import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.emrapi.encounter.postprocessor.EncounterTransactionHandler; -import org.openmrs.module.ipd.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.IPDEvent; import org.openmrs.module.ipd.service.IPDScheduleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.openmrs.module.ipd.events.model.IPDEventType; -import org.openmrs.module.ipd.events.IPDEventManager; +import org.openmrs.module.ipd.api.events.model.IPDEventType; +import org.openmrs.module.ipd.api.events.IPDEventManager; @Component public class IPDTransactionHandler implements EncounterTransactionHandler { diff --git a/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java b/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java deleted file mode 100644 index 2276d4e..0000000 --- a/omod/src/main/java/org/openmrs/module/ipd/scheduler/ShiftStartTasks.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.openmrs.module.ipd.scheduler; - -import org.openmrs.module.ipd.events.IPDEventManager; -import org.openmrs.module.ipd.events.model.IPDEvent; -import org.openmrs.module.ipd.events.model.IPDEventType; -import org.openmrs.scheduler.tasks.AbstractTask; -import org.springframework.beans.factory.annotation.Autowired; - -public class ShiftStartTasks extends AbstractTask { - - @Autowired - private IPDEventManager eventManager; - - @Override - public void execute() { - IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.SHIFT_START_TASK)); - if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(null, null, eventType); - eventManager.processEvent(ipdEvent); - } - } -} From 98c8cf279abf7d873711407a1ef70a7dedc6b973 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:53:16 +0530 Subject: [PATCH 64/75] Update api pom.xml --- api/pom.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/pom.xml b/api/pom.xml index cc20907..b4d1465 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -163,7 +163,6 @@ provided - org.openmrs.module webservices.rest-omod-common @@ -213,6 +212,11 @@ test + + org.openmrs.module + emrapi-api + provided + From 71af6caa771b71190a6f1789c97b48b6aea20ae4 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 9 Apr 2024 18:51:46 +0530 Subject: [PATCH 65/75] Add scheduler task for rollover medication tasks --- .../tasks/RollOverNonMedicationTasks.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java new file mode 100644 index 0000000..f7796c2 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.api.scheduler.tasks; + +import org.openmrs.module.ipd.api.events.IPDEventManager; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.ipd.api.events.model.IPDEventType; +import org.openmrs.scheduler.tasks.AbstractTask; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +@Component +public class RollOverNonMedicationTasks extends AbstractTask { + + private ApplicationContext context; + + @Override + public void execute() { + IPDEventManager eventManager = context.getBean(IPDEventManager.class); + IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.ROLLOVER_TASK)); + if (eventType != null) { + IPDEvent ipdEvent = new IPDEvent(null, null, eventType); + eventManager.processEvent(ipdEvent); + } + } +} From 66b96deab3fd88c148877df6ca97276e0229b2b2 Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 9 Apr 2024 18:52:23 +0530 Subject: [PATCH 66/75] Gets rollover tasks from fhir task service using task names and status --- .../impl/RolloverTaskEventHandler.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java index de89020..a17d17b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java @@ -1,13 +1,17 @@ package org.openmrs.module.ipd.api.events.handler.impl; -import org.openmrs.module.ipd.api.events.model.ConfigDetail; +import org.openmrs.module.fhirExtension.service.TaskService; import org.openmrs.module.ipd.api.events.ConfigLoader; -import org.openmrs.module.ipd.api.events.model.IPDEvent; import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; +import org.openmrs.module.ipd.api.events.model.ConfigDetail; +import org.openmrs.module.ipd.api.events.model.TaskDetail; +import org.openmrs.module.ipd.api.events.model.IPDEvent; +import org.openmrs.module.fhirExtension.model.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; +import java.util.stream.Collectors; @Component public class RolloverTaskEventHandler implements IPDEventHandler { @@ -15,6 +19,10 @@ public class RolloverTaskEventHandler implements IPDEventHandler { @Autowired ConfigLoader configLoader; + private TaskService taskService; + + private static final String TASK_STATUS = "REQUESTED"; + @Override public void handleEvent(IPDEvent event) { List configList = configLoader.getConfigs(); @@ -24,6 +32,16 @@ public void handleEvent(IPDEvent event) { .orElse(null); System.out.println("eventConfig type RolloverTaskEventHandler " + eventConfig.getType()); System.out.println("eventConfig tasks RolloverTaskEventHandler " + eventConfig.getTasks() + " size --- " + eventConfig.getTasks().size()); - //create task based on configuration + + List taskNames = eventConfig.getTasks().stream() + .map(TaskDetail::getName) + .collect(Collectors.toList()); + + List rolloverTasks = taskService.getTasksByNameAndStatus(taskNames, TASK_STATUS); + + for (Task task : rolloverTasks) { + System.out.println("Task : " + task.getFhirTask()); + + } } } \ No newline at end of file From c354016cf4d4dc5d2226c4d7359a99aba8ded65c Mon Sep 17 00:00:00 2001 From: Umair Fayaz Date: Tue, 9 Apr 2024 18:53:24 +0530 Subject: [PATCH 67/75] Add migration top add scheduler for rollover tasks --- api/src/main/resources/liquibase.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index c40e067..08fc186 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -420,4 +420,20 @@ + + + + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks"; + + + + INSERT INTO + scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, + start_on_startup, created_by, date_created, uuid) + VALUES + ('Rollover Tasks', 'Rollover Tasks', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', + TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 120, false, 1, NOW(), UUID()); + + + From f852beccc848a4ed4d7d251066d6b04d376295f3 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:24:32 +0530 Subject: [PATCH 68/75] Create start shift scheduler and roll over tasks --- .../ipd/api/dao/impl/HibernateWardDAO.java | 4 +- .../module/ipd/api/events/IPDEventUtils.java | 1 + .../impl/RolloverTaskEventHandler.java | 27 +++++++---- .../impl/ShiftStartTaskEventHandler.java | 45 +++++++---------- .../module/ipd/api/events/model/IPDEvent.java | 1 + .../tasks/RollOverNonMedicationTasks.java | 13 +++-- .../api/scheduler/tasks/ShiftStartTasks.java | 13 ++--- api/src/main/resources/liquibase.xml | 48 +++++++++++++++---- .../postprocessor/IPDTransactionHandler.java | 2 +- 9 files changed, 96 insertions(+), 58 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index ebe2a19..f161726 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -83,7 +83,9 @@ public List getAdmittedPatients(Location location, Provider pro Query query = session.createQuery(finalQuery); - query.setParameter("location", location); + if(location != null) { + query.setParameter("location", location); + } if (provider != null) { query.setParameter("provider", provider); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java index b9da7ab..1825821 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java @@ -14,6 +14,7 @@ public static TaskRequest createNonMedicationTaskRequest(IPDEvent ipdEvent, Stri taskRequest.setTaskType(taskType); taskRequest.setEncounterUuid(ipdEvent.getEncounterUuid()); taskRequest.setPatientUuid(ipdEvent.getPatientUuid()); + taskRequest.setVisitUuid(ipdEvent.getVisitUuid()); taskRequest.setRequestedStartTime(new Date()); taskRequest.setIntent(FhirTask.TaskIntent.ORDER); taskRequest.setStatus(FhirTask.TaskStatus.REQUESTED); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java index a17d17b..978e8c7 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java @@ -1,15 +1,20 @@ package org.openmrs.module.ipd.api.events.handler.impl; +import org.openmrs.module.fhir2.model.FhirTask; +import org.openmrs.module.fhirExtension.dao.TaskRequestedPeriodDao; +import org.openmrs.module.fhirExtension.model.FhirTaskRequestedPeriod; +import org.openmrs.module.fhirExtension.model.Task; import org.openmrs.module.fhirExtension.service.TaskService; import org.openmrs.module.ipd.api.events.ConfigLoader; import org.openmrs.module.ipd.api.events.handler.IPDEventHandler; import org.openmrs.module.ipd.api.events.model.ConfigDetail; -import org.openmrs.module.ipd.api.events.model.TaskDetail; import org.openmrs.module.ipd.api.events.model.IPDEvent; -import org.openmrs.module.fhirExtension.model.Task; +import org.openmrs.module.ipd.api.events.model.TaskDetail; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -18,9 +23,10 @@ public class RolloverTaskEventHandler implements IPDEventHandler { @Autowired ConfigLoader configLoader; - + @Autowired private TaskService taskService; - + @Autowired + private TaskRequestedPeriodDao taskRequestedPeriodDao; private static final String TASK_STATUS = "REQUESTED"; @Override @@ -30,8 +36,6 @@ public void handleEvent(IPDEvent event) { .filter(config -> config.getType().equals(event.getIpdEventType().name())) .findFirst() .orElse(null); - System.out.println("eventConfig type RolloverTaskEventHandler " + eventConfig.getType()); - System.out.println("eventConfig tasks RolloverTaskEventHandler " + eventConfig.getTasks() + " size --- " + eventConfig.getTasks().size()); List taskNames = eventConfig.getTasks().stream() .map(TaskDetail::getName) @@ -39,9 +43,16 @@ public void handleEvent(IPDEvent event) { List rolloverTasks = taskService.getTasksByNameAndStatus(taskNames, TASK_STATUS); + List fhirTaskRequestedPeriods = new ArrayList(); for (Task task : rolloverTasks) { - System.out.println("Task : " + task.getFhirTask()); - + if (task.getFhirTaskRequestedPeriod() != null) { + FhirTaskRequestedPeriod fhirTaskRequestedPeriod = task.getFhirTaskRequestedPeriod(); + if(task.getFhirTask().getStatus() == FhirTask.TaskStatus.REQUESTED){ + fhirTaskRequestedPeriod.setRequestedStartTime(new Date()); + fhirTaskRequestedPeriods.add(fhirTaskRequestedPeriod); + } + } } + taskRequestedPeriodDao.bulkSave(fhirTaskRequestedPeriods); } } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java index 930fb1c..f230d06 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java @@ -1,10 +1,5 @@ package org.openmrs.module.ipd.api.events.handler.impl; -import org.openmrs.api.EncounterService; -import org.openmrs.api.context.Context; -import org.openmrs.module.emrapi.encounter.ActiveEncounterParameters; -import org.openmrs.module.emrapi.encounter.EmrEncounterService; -import org.openmrs.module.emrapi.encounter.domain.EncounterTransaction; import org.openmrs.module.fhirExtension.model.Task; import org.openmrs.module.fhirExtension.service.TaskService; import org.openmrs.module.fhirExtension.web.contract.TaskRequest; @@ -26,52 +21,46 @@ @Component public class ShiftStartTaskEventHandler implements IPDEventHandler { - private static final String CONSULTATION_ENCOUNTER_TYPE = "Consultation"; @Autowired ConfigLoader configLoader; - private EncounterService encounterService; - private EmrEncounterService emrEncounterService; - @Autowired private TaskMapper taskMapper; @Autowired private TaskService taskService; - + @Autowired + private WardService wardService; @Override public void handleEvent(IPDEvent event) { - System.out.println("Inside HandleEvent"); - WardService wardService = Context.getService(WardService.class); - // - getAdmit - wardDAO.getAdmittedPatients List admittedPatients = wardService.getAdmittedPatients(); -// encounterService.setEncounterType(); - - List configList = configLoader.getConfigs(); - ConfigDetail eventConfig = configList.stream() - .filter(config -> config.getType().equals(event.getIpdEventType().name())) - .findFirst() - .orElse(null); + ConfigDetail eventConfig = getEventConfig(event); List tasks = new ArrayList(); for(AdmittedPatient admittedPatient: admittedPatients){ - ActiveEncounterParameters activeEncounterParameters = new ActiveEncounterParameters(); String patientUuid = admittedPatient.getBedPatientAssignment().getPatient().getUuid(); - activeEncounterParameters.setPatientUuid(patientUuid); - activeEncounterParameters.setEncounterTypeUuid(encounterService.getEncounterType(CONSULTATION_ENCOUNTER_TYPE).getUuid()); - EncounterTransaction encounterTransaction = emrEncounterService.getActiveEncounter(activeEncounterParameters); - System.out.println("encounterTransaction "+encounterTransaction+ " - "+ encounterTransaction.getEncounterUuid()); - System.out.println("patientUuid "+ patientUuid); - IPDEvent ipdEvent = new IPDEvent(encounterTransaction.getEncounterUuid(), patientUuid, event.getIpdEventType()); + String visituuid = admittedPatient.getBedPatientAssignment().getEncounter().getVisit().getUuid(); + + IPDEvent ipdEvent = new IPDEvent(null, patientUuid, visituuid, event.getIpdEventType()); for(TaskDetail taskDetail : eventConfig.getTasks()) { TaskRequest taskRequest = IPDEventUtils.createNonMedicationTaskRequest(ipdEvent, taskDetail.getName(), "nursing_activity_system"); Task task = taskMapper.fromRequest(taskRequest); tasks.add(task); } } - System.out.println("tasks --> "+tasks.size()); if(tasks.size() > 0){ taskService.bulkSaveTasks(tasks); } } + + private ConfigDetail getEventConfig(IPDEvent event){ + List configList = configLoader.getConfigs(); + ConfigDetail eventConfig = configList.stream() + .filter(config -> config.getType().equals(event.getIpdEventType().name())) + .findFirst() + .orElse(null); + return eventConfig; + } + + } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java index dc5cf9b..42dc8e8 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java @@ -14,5 +14,6 @@ public class IPDEvent { private String encounterUuid; private String patientUuid; + private String visitUuid; private IPDEventType ipdEventType; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java index f7796c2..1a30c75 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java @@ -4,22 +4,27 @@ import org.openmrs.module.ipd.api.events.model.IPDEvent; import org.openmrs.module.ipd.api.events.model.IPDEventType; import org.openmrs.scheduler.tasks.AbstractTask; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component -public class RollOverNonMedicationTasks extends AbstractTask { +public class RollOverNonMedicationTasks extends AbstractTask implements ApplicationContextAware { - private ApplicationContext context; + private static ApplicationContext context; @Override public void execute() { IPDEventManager eventManager = context.getBean(IPDEventManager.class); IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.ROLLOVER_TASK)); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(null, null, eventType); + IPDEvent ipdEvent = new IPDEvent(null, null, null, eventType); eventManager.processEvent(ipdEvent); } } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.context = applicationContext; + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java index 1e421d1..b363cb6 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java @@ -3,24 +3,21 @@ import org.openmrs.module.ipd.api.events.IPDEventManager; import org.openmrs.module.ipd.api.events.model.IPDEvent; import org.openmrs.module.ipd.api.events.model.IPDEventType; -import org.openmrs.module.ipd.api.service.SlotService; import org.openmrs.scheduler.tasks.AbstractTask; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +@Component public class ShiftStartTasks extends AbstractTask implements ApplicationContextAware { - private ApplicationContext context; -// IPDEventManager eventManager; + private static ApplicationContext context; @Override public void execute() { IPDEventManager eventManager = context.getBean(IPDEventManager.class); - System.out.println("Started Shift Schedule"); - System.out.println("Shift Start Task"+IPDEventType.SHIFT_START_TASK); - IPDEventType eventType = eventManager.getEventTypeForEncounter("SHIFT_START_TASK"); - System.out.println("eventType"+ eventType); + IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.SHIFT_START_TASK)); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(null, null, eventType); + IPDEvent ipdEvent = new IPDEvent(null, null, null, eventType); eventManager.processEvent(ipdEvent); } } diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 08fc186..ce25f1d 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -404,10 +404,10 @@ - + - SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Start Tasks"; + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Start Tasks First"; @@ -415,15 +415,15 @@ scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, start_on_startup, created_by, date_created, uuid) VALUES - ('Shift Start Tasks', 'Shift Start Tasks', 'org.openmrs.module.ipd.api.scheduler.tasks.ShiftStartTasks', - TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 120, false, 1, NOW(), UUID()); + ('Shift Start Tasks First', 'Shift start tasks first shift', 'org.openmrs.module.ipd.api.scheduler.tasks.ShiftStartTasks', + '2024-04-11 08:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); - + - SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks"; + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Start Tasks Second"; @@ -431,8 +431,40 @@ scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, start_on_startup, created_by, date_created, uuid) VALUES - ('Rollover Tasks', 'Rollover Tasks', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', - TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 120, false, 1, NOW(), UUID()); + ('Shift Start Tasks Second', 'Shift start tasks second shift', 'org.openmrs.module.ipd.api.scheduler.tasks.ShiftStartTasks', + '2024-04-11 19:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); + + + + + + + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks First"; + + + + INSERT INTO + scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, + start_on_startup, created_by, date_created, uuid) + VALUES + ('Rollover Tasks First', 'Rollover tasks first shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', + '2024-04-11 08:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); + + + + + + + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks Second"; + + + + INSERT INTO + scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, + start_on_startup, created_by, date_created, uuid) + VALUES + ('Rollover Tasks Second', 'Rollover tasks second shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', + '2024-04-11 19:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); diff --git a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java index d12737e..e2494ef 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java +++ b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java @@ -28,7 +28,7 @@ public void forRead(Encounter encounter, EncounterTransaction encounterTransacti public void forSave(Encounter encounter, EncounterTransaction encounterTransaction) { IPDEventType eventType = eventManager.getEventTypeForEncounter(encounter.getEncounterType().getName()); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(encounter.getUuid(), encounter.getPatient().getUuid(), eventType); + IPDEvent ipdEvent = new IPDEvent(encounter.getUuid(), encounter.getPatient().getUuid(), encounter.getVisit().getUuid(), eventType); eventManager.processEvent(ipdEvent); } ipdScheduleService.handlePostProcessEncounterTransaction(encounter,encounterTransaction); From 9d8e1662427a2875d773623100e4de20c66af614 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Sun, 14 Apr 2024 00:42:11 +0530 Subject: [PATCH 69/75] Update and Refactor the rollover and shift start task --- .../openmrs/module/ipd/api/events/IPDEventUtils.java | 1 - .../handler/impl/RolloverTaskEventHandler.java | 12 ++++-------- .../handler/impl/ShiftStartTaskEventHandler.java | 8 +------- .../module/ipd/api/events/model/IPDEvent.java | 1 - .../scheduler/tasks/RollOverNonMedicationTasks.java | 2 +- .../ipd/api/scheduler/tasks/ShiftStartTasks.java | 2 +- .../ipd/postprocessor/IPDTransactionHandler.java | 2 +- 7 files changed, 8 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java index 1825821..b9da7ab 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/IPDEventUtils.java @@ -14,7 +14,6 @@ public static TaskRequest createNonMedicationTaskRequest(IPDEvent ipdEvent, Stri taskRequest.setTaskType(taskType); taskRequest.setEncounterUuid(ipdEvent.getEncounterUuid()); taskRequest.setPatientUuid(ipdEvent.getPatientUuid()); - taskRequest.setVisitUuid(ipdEvent.getVisitUuid()); taskRequest.setRequestedStartTime(new Date()); taskRequest.setIntent(FhirTask.TaskIntent.ORDER); taskRequest.setStatus(FhirTask.TaskStatus.REQUESTED); diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java index 978e8c7..59e59e3 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java @@ -40,19 +40,15 @@ public void handleEvent(IPDEvent event) { List taskNames = eventConfig.getTasks().stream() .map(TaskDetail::getName) .collect(Collectors.toList()); - - List rolloverTasks = taskService.getTasksByNameAndStatus(taskNames, TASK_STATUS); - + List rolloverTasks = taskService.getTasksByNameAndStatus(taskNames, FhirTask.TaskStatus.REQUESTED); List fhirTaskRequestedPeriods = new ArrayList(); for (Task task : rolloverTasks) { if (task.getFhirTaskRequestedPeriod() != null) { FhirTaskRequestedPeriod fhirTaskRequestedPeriod = task.getFhirTaskRequestedPeriod(); - if(task.getFhirTask().getStatus() == FhirTask.TaskStatus.REQUESTED){ - fhirTaskRequestedPeriod.setRequestedStartTime(new Date()); - fhirTaskRequestedPeriods.add(fhirTaskRequestedPeriod); - } + fhirTaskRequestedPeriod.setRequestedStartTime(new Date()); + fhirTaskRequestedPeriods.add(fhirTaskRequestedPeriod); } } - taskRequestedPeriodDao.bulkSave(fhirTaskRequestedPeriods); + taskRequestedPeriodDao.bulkUpdate(fhirTaskRequestedPeriods); } } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java index f230d06..12d1960 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java @@ -33,15 +33,11 @@ public class ShiftStartTaskEventHandler implements IPDEventHandler { @Override public void handleEvent(IPDEvent event) { List admittedPatients = wardService.getAdmittedPatients(); - ConfigDetail eventConfig = getEventConfig(event); - List tasks = new ArrayList(); for(AdmittedPatient admittedPatient: admittedPatients){ String patientUuid = admittedPatient.getBedPatientAssignment().getPatient().getUuid(); - String visituuid = admittedPatient.getBedPatientAssignment().getEncounter().getVisit().getUuid(); - - IPDEvent ipdEvent = new IPDEvent(null, patientUuid, visituuid, event.getIpdEventType()); + IPDEvent ipdEvent = new IPDEvent(null, patientUuid, event.getIpdEventType()); for(TaskDetail taskDetail : eventConfig.getTasks()) { TaskRequest taskRequest = IPDEventUtils.createNonMedicationTaskRequest(ipdEvent, taskDetail.getName(), "nursing_activity_system"); Task task = taskMapper.fromRequest(taskRequest); @@ -61,6 +57,4 @@ private ConfigDetail getEventConfig(IPDEvent event){ .orElse(null); return eventConfig; } - - } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java index 42dc8e8..dc5cf9b 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/model/IPDEvent.java @@ -14,6 +14,5 @@ public class IPDEvent { private String encounterUuid; private String patientUuid; - private String visitUuid; private IPDEventType ipdEventType; } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java index 1a30c75..4f2615e 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/RollOverNonMedicationTasks.java @@ -18,7 +18,7 @@ public void execute() { IPDEventManager eventManager = context.getBean(IPDEventManager.class); IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.ROLLOVER_TASK)); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(null, null, null, eventType); + IPDEvent ipdEvent = new IPDEvent(null, null, eventType); eventManager.processEvent(ipdEvent); } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java index b363cb6..59ce500 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/scheduler/tasks/ShiftStartTasks.java @@ -17,7 +17,7 @@ public void execute() { IPDEventManager eventManager = context.getBean(IPDEventManager.class); IPDEventType eventType = eventManager.getEventTypeForEncounter(String.valueOf(IPDEventType.SHIFT_START_TASK)); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(null, null, null, eventType); + IPDEvent ipdEvent = new IPDEvent(null, null, eventType); eventManager.processEvent(ipdEvent); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java index e2494ef..d12737e 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java +++ b/omod/src/main/java/org/openmrs/module/ipd/postprocessor/IPDTransactionHandler.java @@ -28,7 +28,7 @@ public void forRead(Encounter encounter, EncounterTransaction encounterTransacti public void forSave(Encounter encounter, EncounterTransaction encounterTransaction) { IPDEventType eventType = eventManager.getEventTypeForEncounter(encounter.getEncounterType().getName()); if (eventType != null) { - IPDEvent ipdEvent = new IPDEvent(encounter.getUuid(), encounter.getPatient().getUuid(), encounter.getVisit().getUuid(), eventType); + IPDEvent ipdEvent = new IPDEvent(encounter.getUuid(), encounter.getPatient().getUuid(), eventType); eventManager.processEvent(ipdEvent); } ipdScheduleService.handlePostProcessEncounterTransaction(encounter,encounterTransaction); From 1324ca484b670a05b699e11ed1ba1ab5b3c3fa0c Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Sun, 14 Apr 2024 01:16:20 +0530 Subject: [PATCH 70/75] Remove the emrapi dependency --- api/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index b4d1465..ecc0868 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -212,11 +212,6 @@ test - - org.openmrs.module - emrapi-api - provided - From cff31ac67140188758b51884e90953e339aa3d6b Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:47:12 +0530 Subject: [PATCH 71/75] Refactor the method names --- .../ipd/api/events/handler/impl/RolloverTaskEventHandler.java | 4 ++-- .../api/events/handler/impl/ShiftStartTaskEventHandler.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java index 59e59e3..9dc34a3 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/RolloverTaskEventHandler.java @@ -40,7 +40,7 @@ public void handleEvent(IPDEvent event) { List taskNames = eventConfig.getTasks().stream() .map(TaskDetail::getName) .collect(Collectors.toList()); - List rolloverTasks = taskService.getTasksByNameAndStatus(taskNames, FhirTask.TaskStatus.REQUESTED); + List rolloverTasks = taskService.searchTasks(taskNames, FhirTask.TaskStatus.REQUESTED); List fhirTaskRequestedPeriods = new ArrayList(); for (Task task : rolloverTasks) { if (task.getFhirTaskRequestedPeriod() != null) { @@ -49,6 +49,6 @@ public void handleEvent(IPDEvent event) { fhirTaskRequestedPeriods.add(fhirTaskRequestedPeriod); } } - taskRequestedPeriodDao.bulkUpdate(fhirTaskRequestedPeriods); + taskRequestedPeriodDao.update(fhirTaskRequestedPeriods); } } \ No newline at end of file diff --git a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java index 12d1960..e97d620 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/events/handler/impl/ShiftStartTaskEventHandler.java @@ -45,7 +45,7 @@ public void handleEvent(IPDEvent event) { } } if(tasks.size() > 0){ - taskService.bulkSaveTasks(tasks); + taskService.saveTask(tasks); } } From f02745ebf2e3556c0c0ae5895ea6c33318860b99 Mon Sep 17 00:00:00 2001 From: Soorya Kumaran C <90232857+SooryaKumaranC-tw@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:38:23 +0530 Subject: [PATCH 72/75] Rename the scheduler name --- api/src/main/resources/liquibase.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index ce25f1d..d9927a4 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -439,7 +439,7 @@ - SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks First"; + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Rollover Tasks First"; @@ -447,7 +447,7 @@ scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, start_on_startup, created_by, date_created, uuid) VALUES - ('Rollover Tasks First', 'Rollover tasks first shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', + ('Shift Rollover Tasks First', 'Shift Rollover tasks first shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', '2024-04-11 08:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); @@ -455,7 +455,7 @@ - SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Rollover Tasks Second"; + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Shift Rollover Tasks Second"; @@ -463,7 +463,7 @@ scheduler_task_config(name, description, schedulable_class, start_time, start_time_pattern, repeat_interval, start_on_startup, created_by, date_created, uuid) VALUES - ('Rollover Tasks Second', 'Rollover tasks second shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', + ('Shift Rollover Tasks Second', 'Shift Rollover tasks second shift', 'org.openmrs.module.ipd.api.scheduler.tasks.RollOverNonMedicationTasks', '2024-04-11 19:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); From c04364ac5e566dbe9d8f7ce4678e23d57f3c3a82 Mon Sep 17 00:00:00 2001 From: kalai-tw <104360355+kalai-tw@users.noreply.github.com> Date: Thu, 18 Apr 2024 23:50:44 +0530 Subject: [PATCH 73/75] Add filters on drugorder while showing count (#51) --- .../org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java | 2 +- api/src/main/resources/liquibase.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java index f161726..599ffa3 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -59,7 +59,7 @@ public List getAdmittedPatients(Location location, Provider pro "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + "JOIN org.openmrs.Location l on locmap.location = l " + "LEFT JOIN careTeam.participants ctp ON ctp.voided = 0 " + - "LEFT JOIN org.openmrs.Order o on o.encounter = e " + + "LEFT JOIN org.openmrs.Order o on o.encounter = e and o.dateStopped is null and o.action!='DISCONTINUE' and o.careSetting.careSettingId = 2 " + "LEFT JOIN Slot s on s.order = o " + "where assignment.endDatetime is null and v.stopDatetime is null "; diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index d9927a4..648ac33 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -388,7 +388,7 @@ - + SELECT COUNT(*) FROM scheduler_task_config WHERE name = "Mark Slots As Missed"; @@ -400,7 +400,7 @@ start_on_startup, created_by, date_created, uuid) VALUES ('Mark Slots As Missed', 'Mark Slots As Missed', 'org.openmrs.module.ipd.api.scheduler.tasks.MarkSlotsAsMissed', - TIMESTAMP(CURDATE()), 'MM/dd/yyyy HH:mm:ss', 86340, false, 1, NOW(), UUID()); + TIMESTAMP(CURDATE(), "23:59"), 'MM/dd/yyyy HH:mm:ss', 86400, false, 1, NOW(), UUID()); From 2a1883bb4b55b8a8d7d8190067172dcf9973a4da Mon Sep 17 00:00:00 2001 From: AshishkurianTw Date: Thu, 25 Apr 2024 13:18:22 +0530 Subject: [PATCH 74/75] [Ashish]Add. Two new frequencies are added to medications --- .../module/ipd/service/impl/SlotTimeCreationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java index 4d25cbb..01263cc 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/SlotTimeCreationService.java @@ -22,7 +22,7 @@ @Component public class SlotTimeCreationService extends BaseOpenmrsService { - public static final List START_TIME_FREQUENCIES= Arrays.asList(new String[]{"Every Hour", "Every 2 hours", "Every 3 hours", "Every 4 hours", "Every 6 hours", "Every 8 hours", "Every 12 hours", "Once a day", "Nocte (At Night)", "Every 30 minutes", "STAT (Immediately)"}); + public static final List START_TIME_FREQUENCIES= Arrays.asList(new String[]{"Every Hour", "Every 2 hours", "Every 3 hours", "Every 4 hours", "Every 6 hours", "Every 8 hours", "Every 12 hours", "Once a day", "Nocte (At Night)", "Every 30 minutes", "STAT (Immediately)", "In Afternoon", "In Morning"}); public List createSlotsStartTimeFrom(ScheduleMedicationRequest request, DrugOrder order) { if (request.getSlotStartTimeAsLocaltime() != null && request.getMedicationFrequency() == START_TIME_DURATION_FREQUENCY) { From d4f6636e085614b68751c4457946f02c167728b8 Mon Sep 17 00:00:00 2001 From: Abinaya U <77735030+abinaya-u@users.noreply.github.com> Date: Fri, 10 May 2024 15:53:51 +0530 Subject: [PATCH 75/75] Abi | add. privilege checks for endpoints (#54) --- .../ipd/api/util/PrivilegeConstants.java | 13 ---- api/src/main/resources/liquibase.xml | 61 ++++++++++++++++++- ...IPDMedicationAdministrationController.java | 11 +++- .../ipd/controller/IPDScheduleController.java | 17 ++++++ .../ipd/controller/IPDVisitController.java | 29 ++++++--- .../module/ipd/util/PrivilegeConstants.java | 19 ++++++ 6 files changed, 124 insertions(+), 26 deletions(-) delete mode 100644 api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/util/PrivilegeConstants.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java b/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java deleted file mode 100644 index ede0449..0000000 --- a/api/src/main/java/org/openmrs/module/ipd/api/util/PrivilegeConstants.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openmrs.module.ipd.api.util; - -import org.openmrs.annotation.AddOnStartup; - -public class PrivilegeConstants { - - @AddOnStartup(description = "Able to save ipd schedules") - public static final String EDIT_IPD_SCHEDULES = "Edit IPD Schedules"; - - @AddOnStartup(description = "Able to save ipd slots") - public static final String EDIT_IPD_SLOTS = "Edit IPD Slots"; - -} diff --git a/api/src/main/resources/liquibase.xml b/api/src/main/resources/liquibase.xml index 648ac33..df5fc2f 100644 --- a/api/src/main/resources/liquibase.xml +++ b/api/src/main/resources/liquibase.xml @@ -467,5 +467,64 @@ '2024-04-11 19:00:00', 'MM/dd/yyyy HH:mm:ss', 86400, true, 1, NOW(), UUID()); - + + + select count(*) from privilege where privilege = 'Edit Medication Tasks' + + + + + + + + + + select count(*) from privilege where privilege = 'Delete Medication Tasks' + + + + + + + + + + select count(*) from privilege where privilege = 'Edit adhoc medication tasks' + + + + + + + + + + select count(*) from privilege where privilege = 'Edit Medication Administration' + + + + + + + + + + select count(*) from privilege where privilege = 'Get Medication Administration' + + + + + + + + + + select count(*) from privilege where privilege = 'Get Medication Tasks' + + + + + + + diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java index 2e8f9d6..d22cd8a 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDMedicationAdministrationController.java @@ -2,12 +2,14 @@ import lombok.extern.slf4j.Slf4j; import org.hl7.fhir.r4.model.MedicationAdministration; +import org.openmrs.api.context.Context; import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao; import org.openmrs.module.ipd.api.service.SlotService; import org.openmrs.module.ipd.contract.MedicationAdministrationRequest; import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; import org.openmrs.module.ipd.factory.MedicationAdministrationFactory; import org.openmrs.module.ipd.service.IPDMedicationAdministrationService; +import org.openmrs.module.ipd.util.PrivilegeConstants; import org.openmrs.module.webservices.rest.web.RestConstants; import org.openmrs.module.webservices.rest.web.RestUtil; import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; @@ -19,8 +21,7 @@ import java.util.ArrayList; import java.util.List; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.OK; +import static org.springframework.http.HttpStatus.*; @Controller @RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd") @@ -43,6 +44,9 @@ public IPDMedicationAdministrationController(IPDMedicationAdministrationService @ResponseBody public ResponseEntity createScheduledMedicationAdministration(@RequestBody List medicationAdministrationRequestList) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.EDIT_MEDICATION_ADMINISTRATION)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege " + PrivilegeConstants.EDIT_MEDICATION_ADMINISTRATION), FORBIDDEN); + } List medicationAdministrationResponseList = new ArrayList<>(); for (MedicationAdministrationRequest medicationAdministrationRequest : medicationAdministrationRequestList) { MedicationAdministration medicationAdministration = ipdMedicationAdministrationService.saveScheduledMedicationAdministration(medicationAdministrationRequest); @@ -59,6 +63,9 @@ public ResponseEntity createScheduledMedicationAdministration(@RequestBo @ResponseBody public ResponseEntity createAdhocMedicationAdministration(@RequestBody MedicationAdministrationRequest medicationAdministrationRequest) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.EDIT_ADHOC_MEDICATION_TASKS) || !Context.getUserContext().hasPrivilege(PrivilegeConstants.EDIT_MEDICATION_ADMINISTRATION)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege(s) " + PrivilegeConstants.EDIT_MEDICATION_TASKS + ", "+PrivilegeConstants.EDIT_MEDICATION_ADMINISTRATION), FORBIDDEN); + } MedicationAdministration medicationAdministration = ipdMedicationAdministrationService.saveAdhocMedicationAdministration(medicationAdministrationRequest); MedicationAdministrationResponse medicationAdministrationResponse = medicationAdministrationFactory.mapMedicationAdministrationToResponse(medicationAdministration); return new ResponseEntity<>(medicationAdministrationResponse, OK); diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index d98a1d5..09f3604 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -2,10 +2,12 @@ import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; +import org.bahmni.module.bahmnicore.util.WebUtils; import org.openmrs.Patient; import org.openmrs.Visit; import org.openmrs.api.PatientService; import org.openmrs.api.VisitService; +import org.openmrs.api.context.Context; import org.openmrs.module.ipd.api.model.Schedule; import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; @@ -18,10 +20,12 @@ import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; import org.openmrs.module.ipd.model.PatientMedicationSummary; import org.openmrs.module.ipd.service.IPDScheduleService; +import org.openmrs.module.ipd.util.PrivilegeConstants; import org.openmrs.module.webservices.rest.web.RestConstants; import org.openmrs.module.webservices.rest.web.RestUtil; import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -36,6 +40,7 @@ import static org.openmrs.module.ipd.contract.MedicationScheduleResponse.createFrom; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.OK; +import static org.springframework.http.HttpStatus.FORBIDDEN; @Controller @RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd/schedule") @@ -59,6 +64,9 @@ public IPDScheduleController(IPDScheduleService ipdScheduleService, VisitService @ResponseBody public ResponseEntity createMedicationSchedule(@RequestBody ScheduleMedicationRequest scheduleMedicationRequest) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.EDIT_MEDICATION_TASKS)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege " + PrivilegeConstants.EDIT_MEDICATION_TASKS), FORBIDDEN); + } Schedule schedule = ipdScheduleService.saveMedicationSchedule(scheduleMedicationRequest); return new ResponseEntity<>(ScheduleMedicationResponse.constructFrom(schedule), OK); } catch (Exception e) { @@ -71,6 +79,9 @@ public ResponseEntity createMedicationSchedule(@RequestBody ScheduleMedi @ResponseBody public ResponseEntity updateMedicationSchedule(@RequestBody ScheduleMedicationRequest scheduleMedicationRequest) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.EDIT_MEDICATION_TASKS)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege " + PrivilegeConstants.EDIT_MEDICATION_TASKS), FORBIDDEN); + } Schedule schedule = ipdScheduleService.updateMedicationSchedule(scheduleMedicationRequest); return new ResponseEntity<>(ScheduleMedicationResponse.constructFrom(schedule), OK); } catch (Exception e) { @@ -86,6 +97,9 @@ public ResponseEntity getMedicationSlotsByDate(@RequestParam(value = "pa @RequestParam(value = "visitUuid",required = false) String visitUuid, @RequestParam(value = "view", required = false) String view) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_ADMINISTRATION) || !Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_TASKS)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege(s) " + PrivilegeConstants.EDIT_MEDICATION_TASKS+", "+PrivilegeConstants.GET_MEDICATION_TASKS), FORBIDDEN); + } ; if (startTime != null && endTime != null) { LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); @@ -108,6 +122,9 @@ public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value @RequestParam(value = "serviceType", required = false) ServiceType serviceType, @RequestParam(value = "orderUuids", required = false) List orderUuids) { try { + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_ADMINISTRATION) || !Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_TASKS)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege(s) " + PrivilegeConstants.EDIT_MEDICATION_TASKS+" "+PrivilegeConstants.GET_MEDICATION_TASKS), FORBIDDEN); + } List slots; if (orderUuids == null || orderUuids.isEmpty()) { slots = diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java index d6857e6..975d4cf 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDVisitController.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.controller; import lombok.extern.slf4j.Slf4j; +import org.openmrs.api.context.Context; import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.contract.IPDDrugOrderResponse; @@ -8,9 +9,12 @@ import org.openmrs.module.ipd.contract.MedicationAdministrationResponse; import org.openmrs.module.ipd.model.IPDDrugOrder; import org.openmrs.module.ipd.service.IPDVisitService; +import org.openmrs.module.ipd.util.PrivilegeConstants; import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @@ -18,6 +22,9 @@ import java.util.*; import java.util.stream.Collectors; +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.OK; + @Controller @RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipdVisit/{visitUuid}") @Slf4j @@ -32,17 +39,19 @@ public IPDVisitController(IPDVisitService ipdVisitService) { @RequestMapping(value = "/medication", method = RequestMethod.GET) @ResponseBody - public IPDTreatmentsResponse getVisitWiseMedications ( + public ResponseEntity getVisitWiseMedications ( @PathVariable("visitUuid") String visitUuid, @RequestParam(value = "includes", required = false) List includes) throws ParseException { - - List prescribedOrders = ipdVisitService.getPrescribedOrders(visitUuid, true, null, null, null, false); - List prescribedOrderResponse = prescribedOrders.stream().map(IPDDrugOrderResponse::createFrom).collect(Collectors.toList()); - List emergencyMedications = null; - if (includes != null && includes.contains("emergencyMedications")) { - List emergencyMedicationSlots = ipdVisitService.getMedicationSlots(visitUuid, ServiceType.EMERGENCY_MEDICATION_REQUEST); - emergencyMedications = emergencyMedicationSlots.stream().map(slot -> MedicationAdministrationResponse.createFrom(slot.getMedicationAdministration())).collect(Collectors.toList()); - } - return IPDTreatmentsResponse.createFrom(prescribedOrderResponse, emergencyMedications); + if (!Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_ADMINISTRATION) || !Context.getUserContext().hasPrivilege(PrivilegeConstants.GET_MEDICATION_TASKS)) { + return new ResponseEntity<>(RestUtil.wrapErrorResponse(new Exception(), "User doesn't have the following privilege(s) " + PrivilegeConstants.EDIT_MEDICATION_TASKS + ", " + PrivilegeConstants.GET_MEDICATION_TASKS), FORBIDDEN); + } + List prescribedOrders = ipdVisitService.getPrescribedOrders(visitUuid, true, null, null, null, false); + List prescribedOrderResponse = prescribedOrders.stream().map(IPDDrugOrderResponse::createFrom).collect(Collectors.toList()); + List emergencyMedications = null; + if (includes != null && includes.contains("emergencyMedications")) { + List emergencyMedicationSlots = ipdVisitService.getMedicationSlots(visitUuid, ServiceType.EMERGENCY_MEDICATION_REQUEST); + emergencyMedications = emergencyMedicationSlots.stream().map(slot -> MedicationAdministrationResponse.createFrom(slot.getMedicationAdministration())).collect(Collectors.toList()); + } + return new ResponseEntity(IPDTreatmentsResponse.createFrom(prescribedOrderResponse, emergencyMedications), OK); } } diff --git a/omod/src/main/java/org/openmrs/module/ipd/util/PrivilegeConstants.java b/omod/src/main/java/org/openmrs/module/ipd/util/PrivilegeConstants.java new file mode 100644 index 0000000..2fdb09a --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/util/PrivilegeConstants.java @@ -0,0 +1,19 @@ +package org.openmrs.module.ipd.util; + +import org.openmrs.annotation.AddOnStartup; + +public class PrivilegeConstants { + + @AddOnStartup(description = "Edit Medication Tasks description") + public static final String EDIT_MEDICATION_TASKS = "Edit Medication Tasks"; + @AddOnStartup(description = "Delete Medication Tasks description") + public static final String DELETE_MEDICATION_TASKS = "Delete Medication Tasks"; + @AddOnStartup(description = "Edit adhoc medication tasks description") + public static final String EDIT_ADHOC_MEDICATION_TASKS = "Edit adhoc medication tasks"; + @AddOnStartup(description = "Edit Medication Administration description") + public static final String EDIT_MEDICATION_ADMINISTRATION = "Edit Medication Administration"; + @AddOnStartup(description = "Get Medication Administration description") + public static final String GET_MEDICATION_ADMINISTRATION = "Get Medication Administration"; + @AddOnStartup(description = "Get Medication Tasks description") + public static final String GET_MEDICATION_TASKS = "Get Medication Tasks"; +}