diff --git a/.github/workflows/publish-frontend-dev.yml b/.github/workflows/publish-frontend-dev.yml index a12f89ec3f..e7bc479d78 100644 --- a/.github/workflows/publish-frontend-dev.yml +++ b/.github/workflows/publish-frontend-dev.yml @@ -12,8 +12,10 @@ on: env: - REGISTRY: ghcr.io + REGISTRY: docker.io IMAGE_NAME: ${{ github.repository }}-frontend-dev + DOCKER_NAME: ${{ vars.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}-frontend-dev + jobs: build-and-push-image: @@ -26,23 +28,33 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Log in to the Container registry - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@v5 with: context: ./frontend push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{github.repository}}:latest + cache-to: type=inline diff --git a/.github/workflows/publish-frontend.yml b/.github/workflows/publish-frontend.yml index e27474cf97..d179639ca5 100644 --- a/.github/workflows/publish-frontend.yml +++ b/.github/workflows/publish-frontend.yml @@ -14,8 +14,9 @@ on: env: - REGISTRY: ghcr.io + REGISTRY: docker.io IMAGE_NAME: ${{ github.repository }}-frontend + DOCKER_NAME: ${{ vars.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}-frontend jobs: build-and-push-image: @@ -28,24 +29,34 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to the Container registry - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@v5 with: context: ./frontend file: ./frontend/Dockerfile.prod push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{github.repository}}:latest + cache-to: type=inline diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 023def28a6..53bb343800 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,8 +14,9 @@ on: env: - REGISTRY: ghcr.io + REGISTRY: docker.io IMAGE_NAME: ${{ github.repository }} + DOCKER_NAME: ${{ vars.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }} jobs: build-and-push-image: @@ -28,23 +29,34 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Log in to the Container registry - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.DOCKER_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{github.repository}}:latest + cache-to: type=inline diff --git a/README.md b/README.md index 0eb28459e3..ddb604d3ff 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ You can find more information on how to set up OpenELIS at our [docs page](http: #### Building the docker images directly from source code docker-compose -f build.docker-compose.yml up -d --build -#### Running docker containers With locally compiled Artifacts (ie the War file and local frontend Source files) +#### Running docker containers With locally compiled Artifacts (ie the War file) 1. Clone the Repository - git clone https://github.com/I-TECH-UW/OpenELIS-Global-2.git -b 2.8 + git clone https://github.com/I-TECH-UW/OpenELIS-Global-2.git 2. innitialize and build sub modules diff --git a/build.docker-compose.yml b/build.docker-compose.yml index 063f966e2b..4172d12905 100644 --- a/build.docker-compose.yml +++ b/build.docker-compose.yml @@ -2,7 +2,7 @@ version: '3.3' services: certs: container_name: oe-certs - image: ghcr.io/i-tech-uw/certgen:main + image: itechuw/certgen:main restart: always environment: - KEYSTORE_PW="kspass" @@ -13,26 +13,27 @@ services: - key_trust-store-volume:/etc/openelis-global - keys-vol:/etc/ssl/private/ - certs-vol:/etc/ssl/certs/ + database: - container_name: openelisglobal-database - image: postgres:9.5 - ports: - - "15432:5432" - restart: always - env_file: - - ./volume/database/database.env - volumes: - # preserves the database between containers - - db-data:/var/lib/postgresql/data - # files here will run on install - - ./volume/database/dbInit:/docker-entrypoint-initdb.d - networks: - - default - healthcheck: - test: [ "CMD", "pg_isready", "-q", "-d", "clinlims", "-U", "clinlims" ] - timeout: 45s - interval: 10s - retries: 10 + container_name: openelisglobal-database + image: postgres:9.5 + ports: + - "15432:5432" + restart: always + env_file: + - ./volume/database/database.env + volumes: + # preserves the database between containers + - db-data:/var/lib/postgresql/data + # files here will run on install + - ./volume/database/dbInit:/docker-entrypoint-initdb.d + networks: + - default + healthcheck: + test: [ "CMD", "pg_isready", "-q", "-d", "clinlims", "-U", "clinlims" ] + timeout: 45s + interval: 10s + retries: 10 oe.openelis.org: build: @@ -72,8 +73,11 @@ services: - default restart: always environment: + spring.datasource.url : jdbc:postgresql://database:5432/clinlims?currentSchema=clinlims + spring.datasource.username : clinlims + spring.datasource.password : clinlims + spring.datasource.driverClassName: org.postgresql.Driver TZ: Africa/Nairobi - JAVA_OPTS: "-Djavax.net.ssl.trustStore=/etc/openelis-global/truststore -Djavax.net.ssl.trustStorePassword=tspass -Djavax.net.ssl.trustStoreType=pkcs12 diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index 95f7245364..a19a52ad96 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -2,7 +2,7 @@ version: '3.3' services: certs: container_name: oe-certs - image: ghcr.io/i-tech-uw/certgen:main + image: itechuw/certgen:main restart: always environment: - KEYSTORE_PW="kspass" @@ -37,7 +37,7 @@ services: oe.openelis.org: container_name: openelisglobal-webapp - image: ghcr.io/i-tech-uw/openelis-global-2:2.8 + image: itechuw/openelis-global-2:2.8 depends_on: - database ports: @@ -72,6 +72,10 @@ services: - default restart: always environment: + spring.datasource.url : jdbc:postgresql://database:5432/clinlims?currentSchema=clinlims + spring.datasource.username : clinlims + spring.datasource.password : clinlims + spring.datasource.driverClassName: org.postgresql.Driver TZ: Africa/Nairobi JAVA_OPTS: "-Djavax.net.ssl.trustStore=/etc/openelis-global/truststore @@ -87,7 +91,7 @@ services: frontend.openelis.org: - image: ghcr.io/i-tech-uw/openelis-global-2-frontend-dev:2.8 + image: itechuw/openelis-global-2-frontend-dev:2.8 container_name: openelisglobal-front-end networks: - default diff --git a/docker-compose.yml b/docker-compose.yml index e301958047..14e0b56384 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.3' services: certs: container_name: oe-certs - image: ghcr.io/i-tech-uw/certgen:main + image: itechuw/certgen:main restart: always environment: - KEYSTORE_PW="kspass" @@ -37,7 +37,7 @@ services: oe.openelis.org: container_name: openelisglobal-webapp - image: ghcr.io/i-tech-uw/openelis-global-2:2.8 + image: itechuw/openelis-global-2:2.8 depends_on: - database ports: @@ -57,6 +57,8 @@ services: - key_trust-store-volume:/etc/openelis-global - ./volume/plugins/:/var/lib/openelis-global/plugins - ./volume/tomcat/oe_server.xml:/usr/local/tomcat/conf/server.xml + #Runing the OpenELIS with the locally compiled war file + #- ./target/OpenELIS-Global.war:/usr/local/tomcat/webapps/OpenELIS-Global.war secrets: - source: datasource.password - source: common.properties @@ -71,6 +73,10 @@ services: - default restart: always environment: + spring.datasource.url : jdbc:postgresql://database:5432/clinlims?currentSchema=clinlims + spring.datasource.username : clinlims + spring.datasource.password : clinlims + spring.datasource.driverClassName: org.postgresql.Driver TZ: Africa/Nairobi JAVA_OPTS: "-Djavax.net.ssl.trustStore=/etc/openelis-global/truststore @@ -86,7 +92,7 @@ services: frontend.openelis.org: - image: ghcr.io/i-tech-uw/openelis-global-2-frontend:2.8 + image: itechuw/openelis-global-2-frontend:2.8 container_name: openelisglobal-front-end networks: - default diff --git a/docs/.readthedocs.yaml b/docs/.readthedocs.yaml new file mode 100644 index 0000000000..f3aa1f5af0 --- /dev/null +++ b/docs/.readthedocs.yaml @@ -0,0 +1,22 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +# python: +# install: +# - requirements: docs/requirements.txt diff --git a/docs/about.md b/docs/about.md index 8b4e2792ca..884bbe1558 100644 --- a/docs/about.md +++ b/docs/about.md @@ -8,7 +8,7 @@ The software serves as both an effective laboratory software solution and busine ##A Global LIS Laboratory Information System for Global Health -The global health version of [OpenELIS Global](http://openelisglobal.org) builds on the foundation provided by the original US Public Health Lab version of OpenELIS Global. Our challenge is to provide the flexibility demanded by different laboratories while maintaining a common code base. Some examples: +The global health version of [OpenELIS Global](https://openelis-global.org) builds on the foundation provided by the original US Public Health Lab version of OpenELIS Global. Our challenge is to provide the flexibility demanded by different laboratories while maintaining a common code base. Some examples: Some laboratories refer to the number attached to the sample as an accession number while others refer to it as a laboratory number. @@ -21,4 +21,4 @@ Some laboratories refer to the number attached to the sample as an accession num Our goal in meeting these challenges is to ensure that the code does not become fractured by each variation in requirements. We have so far been successful and all of the implementations differ only by configuration files. Designed to support quality laboratory services and test results from high volume clinical and reference laboratories. -The work is done in partnership with International Training and Education Center for Health (I-TECH). They provide a wide perspective on the background, goals and collaborators of the work being done worldwide. For specifics of I-TECH’s work in two countries where OpenELIS Global is being implemented: [I-TECH in Haiti](https://www.go2itech.org/where-we-work/haiti/), [I-TECH in Côte d’Ivoire](https://www.go2itech.org/where-we-work/cote-divoire/). \ No newline at end of file +The work is done in partnership with International Training and Education Center for Health (I-TECH). They provide a wide perspective on the background, goals and collaborators of the work being done worldwide. For specifics of I-TECH’s work in two countries where OpenELIS Global is being implemented: [I-TECH in Haiti](https://www.go2itech.org/where-we-work/haiti/), [I-TECH in Côte d’Ivoire](https://www.go2itech.org/where-we-work/cote-divoire/). diff --git a/docs/gsoc.md b/docs/gsoc.md new file mode 100644 index 0000000000..a9923b8ff3 --- /dev/null +++ b/docs/gsoc.md @@ -0,0 +1,64 @@ + + gsoc + +[**OpenELIS**](https://openelis-global.org/) is hoping to be a mentoring organization for [Google Summer of Code](https://summerofcode.withgoogle.com/) 2024 for the first Time. We're extremely excited about the projects and mentorship opportunities available this year. Coding for **OpenELIS** is a great way to practice your coding skills and, at the same time help making a positive impact on the world through empowering labs with the best tools and support to deliver quality health care to clients. + +If you are new to **OpenELIS**, we recommend starting with our [Installation](install.md) and [Developer](dev_setup.md) Instructions + +||Page Outline | +|--|--| + |1|[GSoC 2024 Program Administrators](#gsoc-2024-program-administrators)| + |2| [Selected Projects for GSoC 2024](#selected-projects-for-gsoc-2024)| + |3 |[Program Timeline](#program-timeline)| + |4 |[Guidelines](#guidelines)| + + +## GSoC 2024 Program Administrators +1. Mutesasira Moses +1. Casey Iiams-Hauser +1. Herbert Yiga + +## Selected Projects for GSoC 2024 + |Project Name|Project Rating|Project Description|Required Skills |Selected Contributor | Mentors| + |--|--|--|--|--|--| + |Improve Responsiveness for OpenELIS3| Medium |Making OE3 Resposnsive|React , Typescript , Javascript| `TBD`| Mutesasira Moses| + |Improve OpenELIS Search Operations|Medium| Integrate a Search Engine library for OpenELIS Search |Java , Spring |`TBD`| `TBD`| + |Improve Integration Tests Coverage | Medium| Improve Integration Tests Coverage for the backend Service layer |Java , Spring ,J-Unit|`TBD`| `TBD`| + |Improve E2E Tests Coverage| Medium| Improve end to end ui Tests Coverage for the new React Frontend |react , cypress |`TBD`| `TBD`| + +## Program Timeline +| Date | Status | Activity | +|------|--------|----------| +| | ✅ | GSoC 2024 preparations | +| | ⌛ | Mentoring organizations can begin submitting applications to Google | +| | ⌛ | Mentoring organization application deadline | +| | ⌛ | List of accepted mentoring organizations announced | +| | ⌛ | March 19: Potential GSoC contributors discuss application ideas with mentoring organizations | +| | ⌛ | GSoC contributor application period begins | +| | ⌛ | GSoC contributor application deadline | +| | ⌛ | GSoC contributor proposal rankings due from Org Admins | +| | ⌛ | Accepted GSoC contributor projects announced | +| | ⌛ | Community Bonding Period. Students get to know mentors, read documentation, prepare for work on their projects | +| | ⌛ | Coding officially begins | +| | ⌛ | Coding Period for Medium project | +| | ⌛ | Coding Period for Advanced project | +| | ⌛ | Mentors and GSoC contributors can begin submitting midterm evaluations | +| | ⌛ | Midterm evaluation deadline (standard coding period) | +| | ⌛ | Work Period. GSoC contributors work on their project with guidance from Mentors | +| | ⌛ | Final week. GSoC contributors submit their final work product and their final mentor evaluation (coding period) | +| | ⌛ | Mentors submit final GSoC contributor evaluations (standard coding period) for medium size project. | +| | ⌛ | Initial results of Google Summer of Code 2023 announced | +| | ⌛ | GSoC contributors with extended timelines continue coding | +| | ⌛ | Final date for all GSoC contributors to submit their final work product and final evaluation | +| | ⌛ | Final date for mentors to submit evaluations for GSoC contributor projects with extended deadlines | + + +## Guidelines +### Student's guidelines +* [GSoC - Guidelines for Students](gsocstudentguide.md) +### Mentor's guidelines +* GSoC - Guidelines for Mentors + +!!! tip + Please Ensure to Follow the Students Guidelines Above + diff --git a/docs/gsocstudentguide.md b/docs/gsocstudentguide.md new file mode 100644 index 0000000000..9a8e85e6d7 --- /dev/null +++ b/docs/gsocstudentguide.md @@ -0,0 +1,43 @@ +Welcome! Are you interested in working on a Google Summer of Code project with *OpenELIS*? We' want you to be a successful GSoC developer in our community so we've put together a few guidelines to answer some of your initial questions and help you understand what is expected of students before submitting a proposal, after being accepted, and during the coding period. + +!!! caution + Only Students who meet both Google's Contributor [Eligibility Requirements](GSoC Contributors) and also follow our Guidelines will be Selected + +|Page OutLine| +|--| +|[Before the Application](#before-the-application)| +|[Proposal Template](#proposal-template)| +|[After being accepted](#after-being-accepted)| +|[During the coding period](#during-the-coding-period)| +|[After GSoC](#after-gsoc)| + +## Before the Application + 1. Sign Up at [OpenELIS Talk](https://talk.openelis-global.org/) and get an ID + 1. Introduce yourself on OpenELIS Talk on the [community introduction page](https://talk.openelis-global.org/t/welcome-please-introduce-yourself/155/8) + 1. Become familiar with **OpenELIS** + See our [Installation](https://docs.openelis-global.org/en/latest/install/) and [Developer](https://docs.openelis-global.org/en/latest/dev_setup/) Instructions + 1. Review project ideas & ask questions [here ](https://github.com/I-TECH-UW/OpenELIS-Global-2/wiki/Google-Summer-of-Code-(GSOC)#selected-projects-for-gsoc-2024) +1. Work on [Introductory Issues](https://github.com/orgs/I-TECH-UW/projects/6) to get Familiar with the Project + +## Proposal Template + 1. Use this [GSOC Template](https://docs.google.com/document/d/1nPcu-UMaibHuASPU6sLnG18sf0ZRoh0fEjzeGZvHcYQ/edit#heading=h.3tq62aycf5sk) to create your Application and Proposal write up. + 1. Complete all the mandatory Fields for your application to be accepted + 1. Submit your application through Google’s website. See Google's GSOC Get Started page [here](https://summerofcode.withgoogle.com/get-started/) + +## After being accepted +1. Set up a blog for your Project on OpenELIS Talk where you will be posting Updates weekly +1. Contact your mentor immediately. Make a plan to communicate with them regularly. +1. Review any [Issues ](https://github.com/orgs/I-TECH-UW/projects/3) related to your project +1. Prepare a detailed project plan together with your mentor. + +## During the coding period +1. Complete a short required "progress report" each week so we can make sure things are on track and there are no problems with your project. Contact organization admins any time if you have concerns about working with your mentor(s). +1. Write at least one blog post every week to help stay on schedule and to share your work publicly. +1. Commit early. Commit often. This is an important value in our open source community +1. Prepare mid-term & final project presentation videos about your project's status, progress, and any questions you have for the community. + +## After GSoC +1. Write a final blog post summarizing your overall experience! If you like, talk to the org admins for consideration to cross-post this article to the Google Open Source Blog. +1. Stay involved with your project or other projects as your schedule permits! There is always plenty of development work needed for OpenELIS volunteers like you. + + diff --git a/docs/img/oe_full_logo.png b/docs/img/oe_full_logo.png new file mode 100644 index 0000000000..6e7fb6763b Binary files /dev/null and b/docs/img/oe_full_logo.png differ diff --git a/docs/img/openelis_logo.png b/docs/img/openelis_logo.png new file mode 100644 index 0000000000..fffc9fedd5 Binary files /dev/null and b/docs/img/openelis_logo.png differ diff --git a/docs/index.md b/docs/index.md index 067aab9547..06be245969 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ # Welcome to The OpenELIS Global 2.0 Documentation -For more OpenELIS Information, please visit [openelisglobal.org](http://openelisglobal.org). +For more OpenELIS Information, please visit [openelisglobal.org](https://openelis-global.org). This Documentation is broken down into broad catagories, with links at the top, information for Software Developers (this is mostly information about how to write the code for OpenELIS, how to contribute to the code case, ETC) and Information for those deploying OpenELIS Global (this contains SOPs focused on how to deploy, installation of software, setup of a bulid server, etc) diff --git a/docs/install.md b/docs/install.md index 466d7472de..14ad626789 100644 --- a/docs/install.md +++ b/docs/install.md @@ -38,14 +38,68 @@ This updates the system from the sources in the sources list. It updates what ne 3. Install Python sudo apt install python3 - -### Create and Load SSL Certificates + +### Options for installing OpenELIS Global software + +You can choose to install OpenELIS in an online mode for servers with fast internet connections, and offline, using less internet connectivity by providing a local copy of the images to be loaded. + +### Online OpenELIS installation with Docker-Compose +This Option can be used where there is fast internet connectivity + +#### Prerequisites for OpenELIS Online Setup +1. Install [Docker](https://linuxize.com/post/how-to-install-and-use-docker-on-ubuntu-20-04/) and [Docker Compose](https://linuxize.com/post/how-to-install-and-use-docker-compose-on-ubuntu-20-04/) + +2. Install [git](https://github.com/git-guides/install-git) + +#### Steps to Run Online Setup +1. Clone the [OpenELIS-Global docker](https://github.com/I-TECH-UW/openelis-docker) repository. + + git clone https://github.com/I-TECH-UW/openelis-docker.git + +1. Move to the Project directory + + cd openelis-docker + +##### Running OpenELIS Global 3x in Docker + docker-compose up -d + +###### The Instaces can be accesed at + +| Instance | URL | credentials (user : password)| +|---------- |:-------------:|------: | +| Legacy UI | https://localhost/api/OpenELIS-Global/  | admin: adminADMIN! | +| New React UI | https://localhost/ | admin: adminADMIN! + +##### Running OpenELIS Global 2x in Docker + docker-compose -f docker-compose-2x.yml up -d + +###### The Instaces can be accesed at + +| Instance | URL | credentials (user : password)| +|---------- |:-------------:|------: | +| OpenElis | https://localhost:8443/OpenELIS-Global/  | admin: adminADMIN! | + +##### Running OpenELIS-Global2 from source code in docker + 1. Clone the [OpenELIS Global](https://github.com/I-TECH-UW/OpenELIS-Global-2) repository. + + git clone https://github.com/I-TECH-UW/OpenELIS-Global-2.git + + 1. Build and Run the docker images from source code + + docker-compose -f build.docker-compose.yml up -d --build + + +### Downloaded Installer Offline Setup +This Option can be used where there is a slow/unstable internet connectivity +#### Prerequisites for the OpenELIS Offline Setup + +##### Create and Load SSL Certificates OpenELIS uses SSL certificates to securely communicate with other software or consolidated lab data servers. For a test or temporary instance, use a self-signed certificate, and for a production instance create a proper signed certifcate. **You must have a cert and key created and in the keystore and truststore for the installer to run** I will include 2 paths, one for generating your own self-signed cert, this is good for just starting out or experimenting, and for using your real certs, which is appropriate for production servers. If you have real certificates skip down to [Use a real certificate, best for production uses](#Use-a-real-certificate-best-for-production-uses) -#### Use a self signed certificate. +##### Use a self signed certificate. ##### Generate a .crt and .key file for the domain you want to use. @@ -68,7 +122,7 @@ and then **Be sure to remember your keystore password, you will need it later ** -#### Create truststore with OpenELIS-Global's cert (or a CA that signs OE certs) +##### Create truststore with OpenELIS-Global's cert (or a CA that signs OE certs) **Choose ONE of the two methods below to create your truststore** @@ -91,7 +145,7 @@ and then openssl pkcs12 -export -nokeys -in /etc/ssl/certs/apache-selfsigned.crt -out /etc/openelis-global/truststore -#### Use a real certificate, best for production uses +##### Use a real certificate, best for production uses ##### Create keystore from key and cert Make the directories for the keystore @@ -132,32 +186,16 @@ and then openssl pkcs12 -export -nokeys -in path/to/your/cert -out /etc/openelis-global/truststore -#### Ensure keystore/truststore permissions are all correct +##### Ensure keystore/truststore permissions are all correct Ensure all keystores have global read permission sudo chmod 644 /etc/openelis-global/keystore /etc/openelis-global/truststore /etc/openelis-global/client_facing_keystore -## Options for installing OpenELIS Global software - -You can choose to install OpenELIS in an online mode for servers with fast internet connections, and offline, using less internet connectivity by providing a local copy of the images to be loaded. -### Online OpenELIS installation with Docker -#### Running with published docker images - docker-compose up -d +#### DownLoad and Unzip the Installation Files for Offline Setup -#### Building the docker images from source code - docker-compose -f build.docker-compose.yml up -d --build - -#### The Instaces can be accesed at - -| Instance | URL | credentials (user : password)| -|---------- |:-------------:|------: | -| OpenElis | https://localhost:8443/OpenELIS-Global/  | admin: adminADMIN! | - -### Downloaded Installer Offline Setup - -1. Install OpenELIS Global +1. Download OpenELIS Global2 Installer a. [Download latest installer package Here:](https://www.dropbox.com/sh/47lagjht4ynpcg8/AABORyLmkpVTtRReeD6wSnJra?dl=0) @@ -184,7 +222,7 @@ You can choose to install OpenELIS in an online mode for servers with fast inter sudo python3 setup_OpenELIS.py -### Install OpenELIS Global ### +#### Install OpenELIS Global2 **OpenELIS Global uses the following file to set things like the consolidated server address, it is not overwritten by the installer. /var/lib/openelisglobal/secrets/extra.properties** @@ -206,7 +244,6 @@ OpenELIS uses FHIR for much of its internal and external communication, if you d 1. The Consolidated Sevrer is a central server which collects lab data for reporting, serves as a master facility list, etc. - Wait while install procedure completes @@ -224,27 +261,4 @@ Follow the SOP at: [Backup Configuration](../backups) To set the identifier for this particular instance, use the /var/lib/openelisglobal/secrets/extra.properties file, and set the organization value to the same identifier as is set in the consolidated server FHIR location object. EG: `org.openelisglobal.remote.source.identifier=Organization/8136bd30-901c-4d47-b133-72de813404ee` -### Run OpenELIS Global 2 With Docker Compose - -1. Install [Docker](https://linuxize.com/post/how-to-install-and-use-docker-on-ubuntu-20-04/) and [Docker Compose](https://linuxize.com/post/how-to-install-and-use-docker-compose-on-ubuntu-20-04/) - -1. Clone the OpenELIS Global repository. - For Open Elis Global 2.7.x - - git clone https://github.com/I-TECH-UW/OpenELIS-Global-2.git - - For the Open Elis Global 2.8.x - - git clone https://github.com/I-TECH-UW/OpenELIS-Global-2.git -b 2.8 - -1. Move to the Project directory - - cd OpenELIS-Global-2 - -1. Start the containers - - docker-compose up -d - - For OpenELIS Global 2.7.x ,you should acces the Instance at https://localhost:8443/OpenELIS-Global/ - For OpenELIS Global 2.8.x , you should acces the instances at https://localhost/ for the new UI and https://localhost/api/OpenELIS-Global/ for the Old UI diff --git a/frontend/src/components/Login.js b/frontend/src/components/Login.js index 62d5692fe7..0930a4a966 100644 --- a/frontend/src/components/Login.js +++ b/frontend/src/components/Login.js @@ -75,7 +75,7 @@ function Login(props) { } else { setNotificationBody({ title: , - message: , + message: , kind: NotificationKinds.error, }); setNotificationVisible(true); @@ -157,10 +157,12 @@ function Login(props) { /> - {submitting && ( - - )} )} diff --git a/frontend/src/components/Style.css b/frontend/src/components/Style.css index 3b00ae81ca..fc15ec5416 100644 --- a/frontend/src/components/Style.css +++ b/frontend/src/components/Style.css @@ -389,3 +389,10 @@ button { margin: 10px !important; } +.cds--date-picker__input{ + max-width: 200px; +} + +.hidden { + visibility: hidden; +} diff --git a/frontend/src/components/addOrder/AddOrder.js b/frontend/src/components/addOrder/AddOrder.js index 8e4a032331..a5670ecb59 100644 --- a/frontend/src/components/addOrder/AddOrder.js +++ b/frontend/src/components/addOrder/AddOrder.js @@ -8,6 +8,7 @@ import { TextInput, TimePicker, } from "@carbon/react"; +import CustomLabNumberInput from "../common/CustomLabNumberInput"; import CustomDatePicker from "../common/CustomDatePicker"; import { getFromOpenElisServer } from "../utils/Utils"; import { NotificationContext } from "../layout/Layout"; @@ -165,7 +166,9 @@ const AddOrder = (props) => { } const handleLabNoGeneration = (e) => { - e.preventDefault(); + if (e) { + e.preventDefault(); + } getFromOpenElisServer( "/rest/SampleEntryGenerateScanProvider", fetchGeneratedAccessionNo, @@ -249,12 +252,12 @@ const AddOrder = (props) => { setDepartments(data); }; - function handleLabNo(e) { + function handleLabNo(e, rawVal) { setOrderFormValues({ ...orderFormValues, sampleOrderItems: { ...orderFormValues.sampleOrderItems, - labNo: e.target.value, + labNo: rawVal ? rawVal : e.target.value, }, }); setNotificationVisible(false); @@ -375,6 +378,12 @@ const AddOrder = (props) => { } }; + const handleKeyPress = (event) => { + if (event.key === "Enter") { + handleLabNoGeneration(event); + } + }; + useEffect(() => { getFromOpenElisServer("/rest/SamplePatientEntry", getSampleEntryPreform); window.scrollTo(0, 0); @@ -392,11 +401,12 @@ const AddOrder = (props) => {
- handleLabNo(e)} + onChange={handleLabNo} + onKeyPress={handleKeyPress} labelText={} id="labNo" className="inputText" @@ -404,7 +414,7 @@ const AddOrder = (props) => {
{" "} handleLabNoGeneration(e)}> - +
@@ -603,15 +613,16 @@ const AddOrder = (props) => { required > - {paymentOptions.map((option) => { - return ( - - ); - })} + {paymentOptions && + paymentOptions.map((option) => { + return ( + + ); + })}
diff --git a/frontend/src/components/addOrder/add-order.scss b/frontend/src/components/addOrder/add-order.scss index c20d6d50c0..573d228600 100644 --- a/frontend/src/components/addOrder/add-order.scss +++ b/frontend/src/components/addOrder/add-order.scss @@ -44,7 +44,7 @@ background-color: #FFFFFF; border-radius: 5px; margin: 2%; - padding: 4%; + padding: 2%; } .ProgressIndicator { diff --git a/frontend/src/components/admin/calculatedValue/CalculatedValueForm.tsx b/frontend/src/components/admin/calculatedValue/CalculatedValueForm.tsx index 3b6e8b1568..ca954fa147 100644 --- a/frontend/src/components/admin/calculatedValue/CalculatedValueForm.tsx +++ b/frontend/src/components/admin/calculatedValue/CalculatedValueForm.tsx @@ -11,9 +11,11 @@ import { Toggle, Loading, Checkbox, - RadioButtonGroup, - RadioButton, ModalWrapper, + Grid, + Column, + Section, + Heading } from "@carbon/react"; import AutoComplete from "../../common/AutoComplete.js"; import { Add, Subtract, Save } from "@carbon/react/icons"; @@ -583,6 +585,17 @@ const CalculatedValue: React.FC = () => { return (
+ + +
+
+ + + +
+
+
+
{notificationVisible === true ? : ""} {loading && } {calculationList.map((calculation, index) => ( diff --git a/frontend/src/components/admin/labNumber/LabNumberManagement.js b/frontend/src/components/admin/labNumber/LabNumberManagement.js index f6306ddc5e..3f7cdeed2e 100644 --- a/frontend/src/components/admin/labNumber/LabNumberManagement.js +++ b/frontend/src/components/admin/labNumber/LabNumberManagement.js @@ -9,6 +9,9 @@ import { SelectItem, Button, Loading, + Grid, + Column, + Section, } from "@carbon/react"; import LabNumberFormValues from "./LabNumberFormValues"; import { @@ -163,12 +166,18 @@ function LabNumberManagement() { {notificationVisible === true ? : ""} {loading && }
+ + +
+
+ + + +
+
+
+
- - - - -
+ + +
+
+ + + +
+
+
+
diff --git a/frontend/src/components/common/CustomLabNumberInput.js b/frontend/src/components/common/CustomLabNumberInput.js new file mode 100644 index 0000000000..a1b914a4d2 --- /dev/null +++ b/frontend/src/components/common/CustomLabNumberInput.js @@ -0,0 +1,55 @@ +import React, { useState, useContext, useRef, useEffect } from "react"; +import { TextInput } from "@carbon/react"; +import { convertAlphaNumLabNumForDisplay } from "../utils/Utils"; +import { ConfigurationContext } from "../layout/Layout"; + +const CustomLabNumberInput = (props) => { + const componentMounted = useRef(true); + + const { configurationProperties } = useContext(ConfigurationContext); + + const [rawInput, setRawInput] = useState([]); + const [formattedInput, setFormattedInput] = useState(""); + + useEffect(() => { + setRawInput(props.value); + if ( + configurationProperties.AccessionFormat === "ALPHANUM" && + props.value.length < 13 + ) { + const formatted = convertAlphaNumLabNumForDisplay(props.value); // use your own format function here + setFormattedInput(formatted); + } else { + setFormattedInput(props.value); + } + }, [props.value]); + + if (configurationProperties.AccessionFormat !== "ALPHANUM") { + return ( + <> + + + ); + } else { + return ( + <> + + { + const val = e.target.value.replace(/-/g, ""); + setRawInput(val); + if (typeof props.onChange === "function") { + props.onChange(e, val); + } + }} + labelText={props.labelText} + id={"display_" + props.id} + value={formattedInput} + name={"display_" + props.name} + /> + + ); + } +}; +export default CustomLabNumberInput; diff --git a/frontend/src/components/cytology/CytologyDashBoard.js b/frontend/src/components/cytology/CytologyDashBoard.js index 43955497fe..fea1c27393 100644 --- a/frontend/src/components/cytology/CytologyDashBoard.js +++ b/frontend/src/components/cytology/CytologyDashBoard.js @@ -18,6 +18,7 @@ import { TableCell, Tile, Loading, + Pagination, } from "@carbon/react"; import UserSessionDetailsContext from "../../UserSessionDetailsContext"; import { Search } from "@carbon/react"; @@ -49,6 +50,8 @@ function CytologyDashboard() { complete: 0, }); const [loading, setLoading] = useState(true); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); const setStatusList = (statusList) => { if (componentMounted.current) { @@ -72,6 +75,15 @@ function CytologyDashboard() { refreshItems, ); }; + const handlePageChange = (pageInfo) => { + if (page != pageInfo.page) { + setPage(pageInfo.page); + } + + if (pageSize != pageInfo.pageSize) { + setPageSize(pageInfo.pageSize); + } + }; const renderCell = (cell, row) => { var status = row.cells.find((e) => e.info.header === "status").value; @@ -86,7 +98,7 @@ function CytologyDashboard() { assignCurrentUserAsTechnician(e, pathologySampleId); }} > - + ); @@ -105,7 +117,7 @@ function CytologyDashboard() { assignCurrentUserAsPathologist(e, pathologySampleId); }} > - + ); @@ -249,122 +261,134 @@ function CytologyDashboard() { ))}
- - - - setFilters({ ...filters, searchTerm: e.target.value }) - } - placeholder="Search by LabNo or Family Name" - labelText="Search by LabNo or Family Name" - /> - - -
-
Filters:
- + + + - setFilters({ ...filters, myCases: e.target.checked }) + setFilters({ ...filters, searchTerm: e.target.value }) } + placeholder="Search by LabNo or Family Name" + labelText="Search by LabNo or Family Name" /> - -
-
+ + +
+
Filters:
+ + setFilters({ ...filters, myCases: e.target.checked }) + } + /> + +
+
- - - {({ rows, headers, getHeaderProps, getTableProps }) => ( - - - - - {headers.map((header) => ( - - {header.header} - - ))} - - - - <> - {rows.map((row) => ( - { - openCaseView(row.id); - }} - > - {row.cells.map((cell) => renderCell(cell, row))} - - ))} - - -
-
- )} -
-
-
+ + + {({ rows, headers, getHeaderProps, getTableProps }) => ( + + + + + {headers.map((header) => ( + + {header.header} + + ))} + + + + <> + {rows.map((row) => ( + { + openCaseView(row.id); + }} + > + {row.cells.map((cell) => renderCell(cell, row))} + + ))} + + +
+
+ )} +
+ +
+ +
); } diff --git a/frontend/src/components/immunohistochemistry/ImmunohistochemistryCaseView.js b/frontend/src/components/immunohistochemistry/ImmunohistochemistryCaseView.js index 2dae8baa49..fddcc332f7 100644 --- a/frontend/src/components/immunohistochemistry/ImmunohistochemistryCaseView.js +++ b/frontend/src/components/immunohistochemistry/ImmunohistochemistryCaseView.js @@ -224,6 +224,7 @@ function ImmunohistochemistryCaseView() { id={"erPercent_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.erPercent} onChange={(e) => { var params = { ...reportParams }; @@ -243,6 +244,7 @@ function ImmunohistochemistryCaseView() { id={"erIntensity_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.erIntensity} onChange={(e) => { var params = { ...reportParams }; @@ -262,6 +264,7 @@ function ImmunohistochemistryCaseView() { id={"erScore_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.erScore} onChange={(e) => { var params = { ...reportParams }; @@ -288,6 +291,7 @@ function ImmunohistochemistryCaseView() { id={"prPercent_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.prPercent} onChange={(e) => { var params = { ...reportParams }; @@ -307,6 +311,7 @@ function ImmunohistochemistryCaseView() { id={"erIntensity_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.prIntensity} onChange={(e) => { var params = { ...reportParams }; @@ -326,6 +331,7 @@ function ImmunohistochemistryCaseView() { id={"erScore_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.prScore} onChange={(e) => { var params = { ...reportParams }; @@ -353,6 +359,7 @@ function ImmunohistochemistryCaseView() { id={"mib_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.mib} onChange={(e) => { var params = { ...reportParams }; @@ -422,6 +429,7 @@ function ImmunohistochemistryCaseView() { id={"herScore_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.herScore} onChange={(e) => { var params = { ...reportParams }; @@ -495,6 +503,7 @@ function ImmunohistochemistryCaseView() { id={"nuclei_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.numberOfcancerNuclei} onChange={(e) => { var params = { ...reportParams }; @@ -517,6 +526,7 @@ function ImmunohistochemistryCaseView() { id={"her_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.averageHer2} onChange={(e) => { var params = { ...reportParams }; @@ -550,6 +560,7 @@ function ImmunohistochemistryCaseView() { id={"her_" + index} labelText="" hideLabel={true} + type="number" value={reportParams[index]?.averageChrom} onChange={(e) => { var params = { ...reportParams }; diff --git a/frontend/src/components/immunohistochemistry/ImmunohistochemistryDashboard.js b/frontend/src/components/immunohistochemistry/ImmunohistochemistryDashboard.js index 02696bc4f0..1895882c97 100644 --- a/frontend/src/components/immunohistochemistry/ImmunohistochemistryDashboard.js +++ b/frontend/src/components/immunohistochemistry/ImmunohistochemistryDashboard.js @@ -18,6 +18,7 @@ import { TableBody, TableCell, Section, + Pagination, } from "@carbon/react"; import { Search } from "@carbon/react"; import { @@ -50,6 +51,8 @@ function ImmunohistochemistryDashboard() { }); const { userSessionDetails } = useContext(UserSessionDetailsContext); const [loading, setLoading] = useState(true); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); function formatDateToDDMMYYYY(date) { var day = date.getDate(); @@ -79,7 +82,15 @@ function ImmunohistochemistryDashboard() { formatDateToDDMMYYYY(currentDate) ); }; + const handlePageChange = (pageInfo) => { + if (page != pageInfo.page) { + setPage(pageInfo.page); + } + if (pageSize != pageInfo.pageSize) { + setPageSize(pageInfo.pageSize); + } + }; const tileList = [ { title: "Cases in Progress", count: counts.inProgress }, { @@ -132,7 +143,7 @@ function ImmunohistochemistryDashboard() { assignCurrentUserAsTechnician(e, immunohistochemistrySampleId); }} > - + ); @@ -151,7 +162,7 @@ function ImmunohistochemistryDashboard() { assignCurrentUserAsPathologist(e, immunohistochemistrySampleId); }} > - + ); @@ -264,122 +275,134 @@ function ImmunohistochemistryDashboard() { ))}
- - - - setFilters({ ...filters, searchTerm: e.target.value }) - } - placeholder="Search by LabNo or Family Name" - labelText="Search by LabNo or Family Name" - /> - - -
-
Filters:
- + + + - setFilters({ ...filters, myCases: e.target.checked }) + setFilters({ ...filters, searchTerm: e.target.value }) } + placeholder="Search by LabNo or Family Name" + labelText="Search by LabNo or Family Name" /> - -
-
+ + +
+
Filters:
+ + setFilters({ ...filters, myCases: e.target.checked }) + } + /> + +
+
- - - {({ rows, headers, getHeaderProps, getTableProps }) => ( - - - - - {headers.map((header) => ( - - {header.header} - - ))} - - - - <> - {rows.map((row) => ( - { - openCaseView(row.id); - }} - > - {row.cells.map((cell) => renderCell(cell, row))} - - ))} - - -
-
- )} -
-
-
+ + + {({ rows, headers, getHeaderProps, getTableProps }) => ( + + + + + {headers.map((header) => ( + + {header.header} + + ))} + + + + <> + {rows.map((row) => ( + { + openCaseView(row.id); + }} + > + {row.cells.map((cell) => renderCell(cell, row))} + + ))} + + +
+
+ )} +
+ +
+ +
); } diff --git a/frontend/src/components/layout/Header.js b/frontend/src/components/layout/Header.js index ac758409c0..f2d1c6de9c 100644 --- a/frontend/src/components/layout/Header.js +++ b/frontend/src/components/layout/Header.js @@ -221,40 +221,48 @@ function OEHeader(props) { - - - - - - - - - - + + + + + + + + )} + {configurationProperties.nonConformityTab == "true" && ( + - - - - - - - - - + + + + + + + + + + + )} @@ -322,14 +330,17 @@ function OEHeader(props) { - - - + {configurationProperties.studyManagementTab == + "true" && ( + + + + )} diff --git a/frontend/src/components/modifyOrder/EditOrder.js b/frontend/src/components/modifyOrder/EditOrder.js index 160ef57337..43d6af4c58 100644 --- a/frontend/src/components/modifyOrder/EditOrder.js +++ b/frontend/src/components/modifyOrder/EditOrder.js @@ -8,6 +8,7 @@ import { TextInput, TimePicker, } from "@carbon/react"; +import CustomLabNumberInput from "../common/CustomLabNumberInput"; import CustomDatePicker from "../common/CustomDatePicker"; import { getFromOpenElisServer } from "../utils/Utils"; import { NotificationContext } from "../layout/Layout"; @@ -369,6 +370,12 @@ const AddOrder = (props) => { } }; + const handleKeyPress = (event) => { + if (event.key === "Enter") { + handleLabNoGeneration(event); + } + }; + useEffect(() => { getFromOpenElisServer("/rest/SamplePatientEntry", getSampleEntryPreform); window.scrollTo(0, 0); @@ -391,11 +398,12 @@ const AddOrder = (props) => {
- handleLabNo(e)} + onChange={handleLabNo} + onKeyPress={handleKeyPress} labelText={} id="labNo" className="inputText" @@ -403,7 +411,7 @@ const AddOrder = (props) => {
{" "} handleLabNoGeneration(e)}> - +
diff --git a/frontend/src/components/pathology/PathologyDashboard.js b/frontend/src/components/pathology/PathologyDashboard.js index 5f81f6121d..4d05c28c97 100644 --- a/frontend/src/components/pathology/PathologyDashboard.js +++ b/frontend/src/components/pathology/PathologyDashboard.js @@ -18,6 +18,7 @@ import { TableCell, Tile, Loading, + Pagination, } from "@carbon/react"; import UserSessionDetailsContext from "../../UserSessionDetailsContext"; import { Search } from "@carbon/react"; @@ -38,6 +39,8 @@ function PathologyDashboard() { const { userSessionDetails } = useContext(UserSessionDetailsContext); const [statuses, setStatuses] = useState([]); const [pathologyEntries, setPathologyEntries] = useState([]); + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); const [filters, setFilters] = useState({ searchTerm: "", myCases: false, @@ -74,6 +77,16 @@ function PathologyDashboard() { ); }; + const handlePageChange = (pageInfo) => { + if (page != pageInfo.page) { + setPage(pageInfo.page); + } + + if (pageSize != pageInfo.pageSize) { + setPageSize(pageInfo.pageSize); + } + }; + const renderCell = (cell, row) => { var status = row.cells.find((e) => e.info.header === "status").value; var pathologySampleId = row.id; @@ -254,122 +267,134 @@ function PathologyDashboard() { ))}
- - - - setFilters({ ...filters, searchTerm: e.target.value }) - } - placeholder="Search by LabNo or Family Name" - labelText="Search by LabNo or Family Name" - /> - - -
-
Filters:
- + + + - setFilters({ ...filters, myCases: e.target.checked }) + setFilters({ ...filters, searchTerm: e.target.value }) } + placeholder="Search by LabNo or Family Name" + labelText="Search by LabNo or Family Name" /> - -
-
+ + +
+
Filters:
+ + setFilters({ ...filters, myCases: e.target.checked }) + } + /> + +
+
- - - {({ rows, headers, getHeaderProps, getTableProps }) => ( - - - - - {headers.map((header) => ( - - {header.header} - - ))} - - - - <> - {rows.map((row) => ( - { - openCaseView(row.id); - }} - > - {row.cells.map((cell) => renderCell(cell, row))} - - ))} - - -
-
- )} -
-
-
+ + + {({ rows, headers, getHeaderProps, getTableProps }) => ( + + + + + {headers.map((header) => ( + + {header.header} + + ))} + + + + <> + {rows.map((row) => ( + { + openCaseView(row.id); + }} + > + {row.cells.map((cell) => renderCell(cell, row))} + + ))} + + +
+
+ )} +
+ +
+ + ); } diff --git a/frontend/src/components/patient/CreatePatientForm.js b/frontend/src/components/patient/CreatePatientForm.js index dadbe194aa..caa1311d32 100644 --- a/frontend/src/components/patient/CreatePatientForm.js +++ b/frontend/src/components/patient/CreatePatientForm.js @@ -41,7 +41,11 @@ function CreatePatientForm(props) { const [formAction, setFormAction] = useState("ADD"); const componentMounted = useRef(false); const intl = useIntl(); - const [dateOfBirthFormatter,setDateOfBirthFormatter] = useState({"years": "", "months": "", "days": ""}) + const [dateOfBirthFormatter, setDateOfBirthFormatter] = useState({ + years: "", + months: "", + days: "", + }); const handleDatePickerChange = (values, ...e) => { var patient = values; patient.birthDateForDisplay = e[1]; @@ -236,6 +240,15 @@ function CreatePatientForm(props) { }; const handleSubmit = (values) => { + if ("years" in values) { + delete values.years; + } + if ("months" in values) { + delete values.months; + } + if ("days" in values) { + delete values.days; + } console.log(JSON.stringify(values)); postToOpenElisServer( "/rest/patient-management", @@ -377,78 +390,6 @@ function CreatePatientForm(props) { )} - - -
- - {({ field }) => ( - - )} - - - {({ field }) => ( - - )} - -
-
- - {({ field }) => ( - - )} - - - {({ field }) => ( - - )} - -
- -
-
-
-
-
@@ -456,7 +397,13 @@ function CreatePatientForm(props) { @@ -471,8 +418,16 @@ function CreatePatientForm(props) { className="inputText" id="create_patient_gender" > - - + + )} @@ -505,7 +460,7 @@ function CreatePatientForm(props) { value={dateOfBirthFormatter.years} name="years" labelText={intl.formatMessage({ - id: "patient.female", + id: "patient.age.years", })} id="years" type="number" @@ -526,7 +481,8 @@ function CreatePatientForm(props) { handleDaysChange(e, values)} labelText={intl.formatMessage({ id: "patient.age.days" })} id="days" className="inputText" @@ -537,26 +493,122 @@ function CreatePatientForm(props) {
-
+ - + +
+ + {({ field }) => ( + + )} + + + {({ field }) => ( + + )} + +
+
+ + {({ field }) => ( + + )} + + + {({ field }) => ( + + )} + +
+ +
+
+
+
+
{({ field }) => ( )} + /> + )} {({ field }) => ( @@ -567,7 +619,9 @@ function CreatePatientForm(props) { @@ -581,7 +635,9 @@ function CreatePatientForm(props) { id="health_region" value={values.healthRegion} name={field.name} - labelText={intl.formatMessage({id: "patient.address.healthregion",})} + labelText={intl.formatMessage({ + id: "patient.address.healthregion", + })} className="inputText" onChange={(e) => handleRegionSelection(e, values)} > @@ -602,7 +658,9 @@ function CreatePatientForm(props) { id="health_district" value={values.healthDistrict} name={field.name} - labelText={intl.formatMessage({id: "patient.address.healthdistrict",})} + labelText={intl.formatMessage({ + id: "patient.address.healthdistrict", + })} className="inputText" onChange={() => {}} > @@ -625,7 +683,9 @@ function CreatePatientForm(props) { id="education" value={values.education} name={field.name} - labelText={intl.formatMessage({id: "pateint.eduction",})} + labelText={intl.formatMessage({ + id: "pateint.eduction", + })} className="inputText" onChange={() => {}} > @@ -646,7 +706,9 @@ function CreatePatientForm(props) { id="maritialStatus" value={values.maritialStatus} name={field.name} - labelText={intl.formatMessage({id: "patient.maritalstatus",})} + labelText={intl.formatMessage({ + id: "patient.maritalstatus", + })} className="inputText" onChange={() => {}} > @@ -669,7 +731,9 @@ function CreatePatientForm(props) { id="nationality" value={values.nationality} name={field.name} - labelText={intl.formatMessage({id: "patient.nationality",})} + labelText={intl.formatMessage({ + id: "patient.nationality", + })} className="inputText" onChange={() => {}} > @@ -689,7 +753,9 @@ function CreatePatientForm(props) { diff --git a/frontend/src/components/patient/SearchPatientForm.js b/frontend/src/components/patient/SearchPatientForm.js index 2b2ab613b0..ff4134bea5 100644 --- a/frontend/src/components/patient/SearchPatientForm.js +++ b/frontend/src/components/patient/SearchPatientForm.js @@ -1,5 +1,5 @@ import React, { useContext, useState } from "react"; -import { FormattedMessage, injectIntl ,useIntl} from "react-intl"; +import { FormattedMessage, injectIntl, useIntl } from "react-intl"; import "../Style.css"; import { getFromOpenElisServer } from "../utils/Utils"; import { @@ -20,8 +20,9 @@ import { TableBody, TableCell, Pagination, - Loading + Loading, } from "@carbon/react"; +import CustomLabNumberInput from "../common/CustomLabNumberInput"; import { patientSearchHeaderData } from "../data/PatientResultsTableHeaders"; import { Formik, Field } from "formik"; import SearchPatientFormValues from "../formModel/innitialValues/SearchPatientFormValues"; @@ -74,7 +75,7 @@ function SearchPatientForm(props) { }); setNotificationVisible(true); } - setLoading(false) + setLoading(false); }; const fetchPatientDetails = (patientDetails) => { @@ -106,7 +107,7 @@ function SearchPatientForm(props) { return ( <> - {loading && } + {loading && } ( )} - {({ field }) => ( - ( + { + setFieldValue(rawValue); + }} /> )} @@ -153,7 +163,10 @@ function SearchPatientForm(props) { {({ field }) => ( @@ -163,7 +176,10 @@ function SearchPatientForm(props) { {({ field }) => ( @@ -184,7 +200,10 @@ function SearchPatientForm(props) { @@ -196,18 +215,27 @@ function SearchPatientForm(props) { @@ -217,7 +245,10 @@ function SearchPatientForm(props) {
@@ -602,6 +711,8 @@ export function SearchResults(props) { case "Result": switch (row.resultType) { + case "M": + case "C": case "D": return ( validateResults(e, row.id)} - value={row.resultValue} - > - {/* {...updateShadowResult(e, this, param.rowId)} */} - - {row.dictionaryResults.map( - (dictionaryResult, dictionaryResult_index) => ( - - ), - )} - - ); - - case "N": - return ( - handleChange(e, row.id)} - /> - ); - - case "R": - return ( - -
+ + {row.nonconforming && ( + + nonconforming + + )} ); @@ -221,7 +231,6 @@ const Validation = (props) => { +
+ + ); + case "Result": switch (row.resultType) { + case "M": + case "C": case "D": return ( handleChange(e, data.id)} - value={data.method} - > - - {methods.map((method, method_index) => ( - - ))} - - - - -
- -
+ + return ( + <> + {props.results?.resultList?.length > 0 && ( + + + + nonconforming + + + {" "} + + -
- -
+ { + const nomalResults = props.results.resultList?.filter( + (result) => result.normal == true, + ); + nomalResults.forEach((result) => { + const checkbox = document.getElementById( + "resultList" + result.id + ".isAccepted", + ); + checkbox.checked = e.target.checked; + handleAutomatedCheck(e.target.checked, checkbox.name); + }); + }} + />
-
- -
+ { + const nomalResults = props.results.resultList; + nomalResults.forEach((result) => { + const checkbox = document.getElementById( + "resultList" + result.id + ".isAccepted", + ); + checkbox.checked = e.target.checked; + handleAutomatedCheck(e.target.checked, checkbox.name); + }); + }} + />
- handleDatePickerChange(date, data.id)} - > - - + { + const nomalResults = props.results.resultList; + nomalResults.forEach((result) => { + const checkbox = document.getElementById( + "resultList" + result.id + ".isRejected", + ); + checkbox.checked = e.target.checked; + handleAutomatedCheck(e.target.checked, checkbox.name); + }); + }} + />
- - ); - }; - return ( - <> + )} - {({ - values, - errors, - touched, - handleChange, - //handleBlur, - handleSubmit, - }) => ( - + {({ values, errors, touched, handleChange }) => ( + -
- -
- - - = {testsList.length} -       - nonconforming = -
-
-
-
- - - <> - - - - - - - {type === "test" &&  } - - - - {subjectOnWorkplan.toLowerCase() === "true" && ( +
+ + + + + + {testsList.length !== 0 && ( + <> +
+
+ + + + + +
+ + + = {testsList.length} +       + nonconforming = +
+
+
+
+ + + <> +
+ + - + - )} - {nextVisitOnWorkplan.toLowerCase() === "true" && ( + {type === "test" &&  } - + - )} - {type !== "test" &&  } - {type !== "test" && ( + {subjectOnWorkplan.toLowerCase() === "true" && ( + + + + )} + {nextVisitOnWorkplan.toLowerCase() === "true" && ( + + + + )} + {type !== "test" &&  } + {type !== "test" && ( + + {configurationName === "Haiti LNSP" ? ( + }} + /> + ) : ( + + )} + + )} - {configurationName === "Haiti LNSP" ? ( - }} - /> - ) : ( - - )} + - )} - - - - - - - {testsList.map((row, index) => { - if (!(row.accessionNumber === currentAccessionNumber)) { - showAccessionNumber = true; - currentAccessionNumber = row.accessionNumber; - rowColorIndex++; - } else { - showAccessionNumber = false; - } - return ( - + + + {testsList + .slice((page - 1) * pageSize, page * pageSize) + .map((row, index) => { + if ( + !(row.accessionNumber === currentAccessionNumber) + ) { + showAccessionNumber = true; + currentAccessionNumber = row.accessionNumber; + rowColorIndex++; + } else { + showAccessionNumber = false; } - > - {!row.servingAsTestGroupIdentifier && ( - - - disableEnableTest(e.target, index) - } - /> - - )} - {type === "test" && ( - - {row.nonconforming && ( - nonconforming + return ( + + {!row.servingAsTestGroupIdentifier && ( + + + disableEnableTest(e.target, index) + } + /> + )} - - )} - - {showAccessionNumber && ( - - {row.accessionNumber} - - )} - - {subjectOnWorkplan.toLowerCase() === "true" && ( - - {showAccessionNumber && row.patientInfo} - - )} - {nextVisitOnWorkplan.toLowerCase() === "true" && ( - - {showAccessionNumber && row.nextVisitDate} - - )} - {type !== "test" && ( - - {row.nonconforming && ( - nonconforming + {type === "test" && ( + + {row.nonconforming && ( + nonconforming + )} + )} - - )} - {type !== "test" && ( - {row.testName} - )} - {row.receivedDate} - - ); - })} - -
- -
-
-
-
- - - - - - - )} - {selectedValue && testsList.length === 0 && ( -

- -

- )} + + {showAccessionNumber && ( + + + {convertAlphaNumLabNumForDisplay( + row.accessionNumber, + )} + + + )} + + {subjectOnWorkplan.toLowerCase() === "true" && ( + + {showAccessionNumber && row.patientInfo} + + )} + {nextVisitOnWorkplan.toLowerCase() === "true" && ( + + {showAccessionNumber && row.nextVisitDate} + + )} + {type !== "test" && ( + + {row.nonconforming && ( + nonconforming + )} + + )} + {type !== "test" && ( + {row.testName} + )} + {row.receivedDate} + + ); + })} + + + + + +
+ +
+ + + + + + + )} + {selectedValue && testsList.length === 0 && ( +

+ + + + + +

+ )} + ); } diff --git a/frontend/src/languages/en.json b/frontend/src/languages/en.json index 49d809a776..ee13c348c1 100644 --- a/frontend/src/languages/en.json +++ b/frontend/src/languages/en.json @@ -208,8 +208,8 @@ "sidenav.label.results.testdate" : "By Test Date" , "sidenav.label.results.byrange" : "By Range of Order numbers" , "sidenav.label.validation" : "Validation" , - "sidenav.label.validation.routine" : "Search By Routine", - "sidenav.label.validation.study" : "Search By Study", + "sidenav.label.validation.routine" : "Routine", + "sidenav.label.validation.study" : "Study", "sidenav.label.validation.order" : "Search By Order" , "sidenav.label.validation.testdate" : "Search By Test Date" , "sidenav.label.reports" : "Reports" , @@ -217,8 +217,8 @@ "sidenav.label.reports.study" : "Study" , "sidenav.label.admin" : "Admin" , "sidenav.label.admin.testmgt" : "Test Management" , - "sidenav.label.admin.testmgt.reflex" : "Manage Reflex tests" , - "sidenav.label.admin.testmgt.calculated" : "Manage Calculated Value tests" , + "sidenav.label.admin.testmgt.reflex" : "Reflex Tests Management" , + "sidenav.label.admin.testmgt.calculated" : "Calculated Value Tests Management" , "sidenav.label.admin.program" : "Program Entry" , "sidenav.label.admin.organizationmgt" : "Organization Management" , "sidenav.label.admin.usermgt" : "User Management", @@ -229,6 +229,7 @@ "patient.label.nopatientid" : "Patient Id Doest Exist" , "sample.label.orderdate" : "Oder Date" , "sample.label.labnumber" : "Lab Number" , + "sample.label.labnumber.generate": "Generate", "sample.label.facility" : "Referring Facility", "sample.label.requester" : "Requester" , "sample.label.dept" : "Ward/Dept/Unit" , @@ -368,6 +369,7 @@ "search.label.sample" : "Select Sample Status" , "pathology.label.report" : "Pathology Report", "patient.natioanalid":"National ID", + "patient.label.additionalInfo": "Additional Information" , "sample.label.orderpanel":"Order Panels", "sample.label.noorder":"Order Doesnt Exist", "sample.label.labnumber.new" : "New Lab Number" , @@ -403,5 +405,6 @@ "labNumber.usePrefix": "Use Prefix", "labNumber.prefix": "Prefix", "labNumber.format.new": "New Format", - "labNumber.format.current": "Current Format" + "labNumber.format.current": "Current Format" , + "validation.label.nonconform" : "= Sample or Order is nonconforming or Test has been rejected" } diff --git a/frontend/src/languages/fr.json b/frontend/src/languages/fr.json index b496135eff..21d2238940 100644 --- a/frontend/src/languages/fr.json +++ b/frontend/src/languages/fr.json @@ -213,8 +213,8 @@ "sidenav.label.results.testdate" : "Par Date de Test", "sidenav.label.results.byrange" : "Par plage de numéros de commande", "sidenav.label.validation" : "Validation", - "sidenav.label.validation.routine" : "Recherche Par Routine", - "sidenav.label.validation.study" : "Recherche Par Étude", + "sidenav.label.validation.routine" : "Routine", + "sidenav.label.validation.study" : "Étude", "sidenav.label.validation.order" : "Recherche Par Commande", "sidenav.label.validation.testdate" : "Recherche Par Date de Test", "sidenav.label.reports" : "Rapports", @@ -222,8 +222,8 @@ "sidenav.label.reports.study" : "Étude", "sidenav.label.admin" : "Administration", "sidenav.label.admin.testmgt" : "Gestion des Tests", - "sidenav.label.admin.testmgt.reflex" : "Gérer les Tests de Réflexe", - "sidenav.label.admin.testmgt.calculated" : "Gérer les Tests de Valeur Calculée", + "sidenav.label.admin.testmgt.reflex": "Gestion des tests de réflexes", + "sidenav.label.admin.testmgt.calculated": "Gestion des tests de valeur calculée", "sidenav.label.admin.program" : "Entrée du Programme", "sidenav.label.admin.organizationmgt" : "Gestion de l'Organisation", "sidenav.label.admin.usermgt" : "Gestion des Utilisateurs", @@ -234,6 +234,7 @@ "patient.label.nopatientid" : "Identifiant du Patient N'existe Pas", "sample.label.orderdate" : "Date de Commande", "sample.label.labnumber" : "Numéro de Laboratoire", + "sample.label.labnumber.generate": "Générer", "sample.label.facility" : "Établissement Référant", "sample.label.requester" : "Demandeur", "sample.label.dept" : "Service/Département/Unité", @@ -341,6 +342,7 @@ "patient.label.contactphone": "Téléphone de contact : {PHONE_FORMAT}", "patient.lable.primaryphone": "Téléphone principal : {PHONE_FORMAT}", "patient.gender": "Genre", + "patient.label.additionalInfo": "Informations Complémentaires" , "emergencyContactInfo.title":"Informations de contact d'urgence", "label.button.select.status": "Sélectionner l'état", "label.button.select.technician": "Sélectionner le technicien", @@ -398,5 +400,6 @@ "labNumber.usePrefix": "Utiliser le préfixe", "labNumber.prefix": "Préfixe", "labNumber.format.new": "Nouveau format", - "labNumber.format.current": "Format actuel" + "labNumber.format.current": "Format actuel" , + "validation.label.nonconform": "= L'échantillon ou la commande est non conforme ou le test a été rejeté" } diff --git a/mkdocs.yml b/mkdocs.yml index 5672a576b1..f590a2bfed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,14 @@ site_name: OpenELIS Global Documentation +site_description: "Technical documentation for the OpenELIS Global2" +site_author: "I‐TECH (DIGI) - University Of Washington" +site_url: "https://openelis-global.org/" + +# Repository +repo_name: "OpenELIS-Global-2" +repo_url: "https://github.com/I-TECH-UW/OpenELIS-Global-2" + +# Copyright +copyright: "Copyright © 2023 I‐TECH (DIGI) - University Of Washington" nav: - Home: index.md - About: about.md @@ -26,16 +36,23 @@ nav: - Database Profiles Mass facility and test catalog updates: dbprofiles.md - Entity Relation Diagram: entity relation diagram.md - Troubleshooting: troubleshooting.md + - Google Summer of Code : + - GSoC 2024: gsoc.md + - GSoC ‐ Guidelines for Students : gsocstudentguide.md - Website: http://openelis-global.org -theme: readthedocs -markdown_extensions: +# Theme +theme: + name: "material" + logo: img/openelis_logo.png - # Python Markdown - - toc: - permalink: true - - tables markdown_extensions: - - tables + - admonition + - codehilite: + guess_lang: false + - toc: + toc_depth : "3" + - footnotes + diff --git a/pom.xml b/pom.xml index 53f0cbad7a..bdf6f5ab79 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 2 8 1 - 8 + 11 UTF-8 ${project.basedir}/liquibase/liquibase.properties 1.4.1 diff --git a/readthedocs.yml b/readthedocs.yml index 94a04e61bd..4a9a54eb94 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -17,7 +17,11 @@ mkdocs: #formats: all # Optionally set the version of Python and requirements required to build your docs -#python: -# version: 3.7 -# install: -# - requirements: docs/requirements.txt \ No newline at end of file +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" +python: + install: + - requirements: requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..fcd284a368 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +mkdocs-versioning==0.4.0 +mkdocs-material==8.1.11 diff --git a/src/main/java/org/openelisglobal/analyzerresults/action/beanitems/AnalyzerResultItem.java b/src/main/java/org/openelisglobal/analyzerresults/action/beanitems/AnalyzerResultItem.java index 1d02c6aa5d..e3c5839f1a 100644 --- a/src/main/java/org/openelisglobal/analyzerresults/action/beanitems/AnalyzerResultItem.java +++ b/src/main/java/org/openelisglobal/analyzerresults/action/beanitems/AnalyzerResultItem.java @@ -40,7 +40,7 @@ public class AnalyzerResultItem implements Serializable { // TODO move all accession number to the same format so they can be validated // properly // @ValidAccessionNumber(groups = { AnalyzerResultsForm.AnalyzerResuts.class }) - @Pattern(regexp = "^[0-9a-zA-Z -]*$", groups = { AnalyzerResultsForm.AnalyzerResuts.class }) + @Pattern(regexp = "^[0-9a-zA-Z -:]*$", groups = { AnalyzerResultsForm.AnalyzerResuts.class }) private String accessionNumber; @SafeHtml(level = SafeHtml.SafeListLevel.NONE, groups = { AnalyzerResultsForm.AnalyzerResuts.class }) diff --git a/src/main/java/org/openelisglobal/barcode/BarcodeLabelMaker.java b/src/main/java/org/openelisglobal/barcode/BarcodeLabelMaker.java index dc0f507e06..214c53f155 100644 --- a/src/main/java/org/openelisglobal/barcode/BarcodeLabelMaker.java +++ b/src/main/java/org/openelisglobal/barcode/BarcodeLabelMaker.java @@ -403,6 +403,7 @@ private PdfPCell create128Barcode(Label label, PdfWriter writer, int colspan) Barcode128 barcode = new Barcode128(); barcode.setCodeType(Barcode.CODE128); barcode.setCode(label.getCode()); + barcode.setAltText(label.getCodeLabel()); // shrink bar code height inversely with number of text rows barcode.setBarHeight((10 - (label.getNumTextRowsBefore() + label.getNumTextRowsAfter())) * 30 / 10); PdfPCell cell = new PdfPCell(barcode.createImageWithBarcode(writer.getDirectContent(), null, null), true); diff --git a/src/main/java/org/openelisglobal/barcode/labeltype/Label.java b/src/main/java/org/openelisglobal/barcode/labeltype/Label.java index daf0f22581..b6431d317b 100644 --- a/src/main/java/org/openelisglobal/barcode/labeltype/Label.java +++ b/src/main/java/org/openelisglobal/barcode/labeltype/Label.java @@ -48,6 +48,7 @@ public abstract class Label { protected ArrayList aboveFields; protected ArrayList belowFields; private String code; + private String codeLabel; // information stored in/for database private BarcodeLabelInfo labelInfo; @@ -210,6 +211,14 @@ public void setCode(String code) { this.code = code; } + public String getCodeLabel() { + return codeLabel == null ? code : codeLabel; + } + + public void setCodeLabel(String codeLabel) { + this.codeLabel = codeLabel; + } + /** * Get number of labels to attempt to print * diff --git a/src/main/java/org/openelisglobal/barcode/labeltype/OrderLabel.java b/src/main/java/org/openelisglobal/barcode/labeltype/OrderLabel.java index fdacf55163..c4667da39f 100644 --- a/src/main/java/org/openelisglobal/barcode/labeltype/OrderLabel.java +++ b/src/main/java/org/openelisglobal/barcode/labeltype/OrderLabel.java @@ -5,6 +5,8 @@ import org.apache.commons.lang.StringUtils; import org.openelisglobal.barcode.LabelField; import org.openelisglobal.common.log.LogEvent; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.SampleOrderService; import org.openelisglobal.common.util.ConfigurationProperties; import org.openelisglobal.common.util.ConfigurationProperties.Property; @@ -54,13 +56,20 @@ public OrderLabel(String labNo, String facility) { aboveFields.add(siteField); // adding bar code + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + setCodeLabel(AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(labNo)); + } setCode(labNo); } /** - * @param patient Who to include on order label - * @param sample What to include on order label - * @param labNo Code to include in bar code + * @param patient + * Who to include on order label + * @param sample + * What to include on order label + * @param labNo + * Code to include in bar code */ public OrderLabel(Patient patient, Sample sample, String labNo) { // set dimensions @@ -91,13 +100,18 @@ public OrderLabel(Patient patient, Sample sample, String labNo) { aboveFields.add(siteField); // adding bar code + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + setCodeLabel(AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(labNo)); + } setCode(labNo); } /** * Get first available id to identify a patient (Subject Number > National Id) * - * @param patient Who to find identification for + * @param patient + * Who to find identification for * @return label field containing patient id */ private LabelField getAvailableIdField(Patient patient) { diff --git a/src/main/java/org/openelisglobal/common/provider/query/SampleItemTestProvider.java b/src/main/java/org/openelisglobal/common/provider/query/SampleItemTestProvider.java index a5e56e97a3..cdafc0a169 100644 --- a/src/main/java/org/openelisglobal/common/provider/query/SampleItemTestProvider.java +++ b/src/main/java/org/openelisglobal/common/provider/query/SampleItemTestProvider.java @@ -32,6 +32,7 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.service.AnalysisService; import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.log.LogEvent; import org.openelisglobal.sample.form.ProjectData; import org.openelisglobal.sample.util.CI.BaseProjectFormMapper.TypeOfSampleTests; import org.openelisglobal.sample.util.CI.IProjectFormMapper; @@ -50,123 +51,131 @@ */ public class SampleItemTestProvider extends BaseQueryProvider { - protected static AnalysisService analysisService = SpringContext.getBean(AnalysisService.class); - protected SampleItemService sampleItemService = SpringContext.getBean(SampleItemService.class); - - /** - * @see org.openelisglobal.common.provider.query.BaseQueryProvider#processRequest(javax.servlet.http.HttpServletRequest, - * javax.servlet.http.HttpServletResponse) - */ - @Override - public void processRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - /** - * The primary Key for a sample - */ - String sampleKey = request.getParameter("sampleKey"); - /** - * the particular project form we are trying to fill validate. - */ - String projectFormName = request.getParameter("projectFormName"); - - /** - * the name (something derived from html form id) of the check box for the - * relevant sample item type - */ - String sampleItemTypeTag = request.getParameter("sampleItemTypeTag"); - - /** - * the name (something derived from html form id) - */ - String testTag = request.getParameter("testTag"); - - StringBuilder xml = new StringBuilder(); - String result = VALID; - - boolean isChecked; - if (GenericValidator.isBlankOrNull(testTag)) { - isChecked = wasSampleTypeSelected(sampleKey, projectFormName, sampleItemTypeTag); - } else { - try { - isChecked = wasTestSelected(sampleKey, projectFormName, sampleItemTypeTag, testTag); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - throw new ServletException(e); - } - } - - xml.append(isChecked); - - ajaxServlet.sendData(xml.toString(), result, request, response); - } - - /** - * Figure out if the given "test" (actually something of a test panel) Ask the - * project form mapper - * - */ - private boolean wasTestSelected(String sampleKey, String projectFormName, String sampleItemType, String testTag) - throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - ProjectData projectData = new ProjectData(); - Map miniForm = new HashMap<>(); - miniForm.put(sampleItemType + "Taken", Boolean.TRUE); - miniForm.put(testTag, Boolean.TRUE); - PropertyUtils.copyProperties(projectData, miniForm); - - List analysis = findAnalysis(sampleKey, projectFormName, projectData); - return analysis.size() != 0; - } - - /*** - * Fill in one (or more?) sampleType fields of project data and one (or more?) - * *Test fields, e.g. transaminaseTest and you'll get back a list Analysis which - * where submitted because of that selection. - * - * @param sampleKey - PK of a sample - * @param projectFormName particular study we are working on - * @param projectData the data with two flags set. - * @return List of analysis - */ - // TODO PAHill - refactor - needs to be moved to some type of a utility - // class. - public static List findAnalysis(String sampleKey, String projectFormName, ProjectData projectData) { - IProjectFormMapper projectFormMapper = new ProjectFormMapperFactory().getProjectInitializer(projectFormName, - null); - projectFormMapper.setProjectData(projectData); - List typeOfSampleTestsList = projectFormMapper.getTypeOfSampleTests(); - if (typeOfSampleTestsList.size() == 0) { - throw new IllegalArgumentException("The combination of sampleItem type and test (panel) is not valid."); - } - TypeOfSampleTests sampleTests = typeOfSampleTestsList.get(0); - List tests = sampleTests.tests; - - List testIds = new ArrayList<>(); - for (Test test : tests) { - testIds.add(Integer.valueOf(test.getId())); - } - return analysisService.getAnalysisBySampleAndTestIds(sampleKey, testIds); - - } - - private boolean wasSampleTypeSelected(String sampleId, String projectFormName, String sampleItemType) { - String sampleItemDesc = changeUIIdToDescription(sampleItemType); - IProjectFormMapper projectFormMapper = new ProjectFormMapperFactory().getProjectInitializer(projectFormName, - null); - TypeOfSample typeOfSample = projectFormMapper.getTypeOfSample(sampleItemDesc); - List sampleItems = sampleItemService.getSampleItemsBySampleId(sampleId); - for (SampleItem sampleItem : sampleItems) { - if (sampleItem.getTypeOfSampleId().equals(typeOfSample.getId())) { - return true; - } - } - return false; - } - - private String changeUIIdToDescription(String sampleTypeId) { - String description = sampleTypeId; - int i = sampleTypeId.indexOf("Tube"); - if (i != -1) { - description = sampleTypeId.substring(0, i) + " Tube"; - } - return description; - } + protected static AnalysisService analysisService = SpringContext.getBean(AnalysisService.class); + protected SampleItemService sampleItemService = SpringContext.getBean(SampleItemService.class); + + /** + * @see org.openelisglobal.common.provider.query.BaseQueryProvider#processRequest(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse) + */ + @Override + public void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + /** + * The primary Key for a sample + */ + String sampleKey = request.getParameter("sampleKey"); + /** + * the particular project form we are trying to fill validate. + */ + String projectFormName = request.getParameter("projectFormName"); + + /** + * the name (something derived from html form id) of the check box for the + * relevant sample item type + */ + String sampleItemTypeTag = request.getParameter("sampleItemTypeTag"); + if (sampleItemTypeTag.endsWith("vl")) { + sampleItemTypeTag = sampleItemTypeTag.substring(0, sampleItemTypeTag.length() - 2); + } + + /** + * the name (something derived from html form id) + */ + String testTag = request.getParameter("testTag"); + + StringBuilder xml = new StringBuilder(); + String result = VALID; + + boolean isChecked; + if (GenericValidator.isBlankOrNull(testTag)) { + isChecked = wasSampleTypeSelected(sampleKey, projectFormName, sampleItemTypeTag); + } else { + try { + isChecked = wasTestSelected(sampleKey, projectFormName, sampleItemTypeTag, testTag); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new ServletException(e); + } + } + + xml.append(isChecked); + + ajaxServlet.sendData(xml.toString(), result, request, response); + } + + /** + * Figure out if the given "test" (actually something of a test panel) Ask the + * project form mapper + * + */ + private boolean wasTestSelected(String sampleKey, String projectFormName, String sampleItemType, String testTag) + throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { + ProjectData projectData = new ProjectData(); + Map miniForm = new HashMap<>(); + miniForm.put(sampleItemType + "Taken", Boolean.TRUE); + miniForm.put(testTag, Boolean.TRUE); + PropertyUtils.copyProperties(projectData, miniForm); + + List analysis = findAnalysis(sampleKey, projectFormName, projectData); + return analysis.size() != 0; + } + + /*** + * Fill in one (or more?) sampleType fields of project data and one (or more?) + * *Test fields, e.g. transaminaseTest and you'll get back a list Analysis which + * where submitted because of that selection. + * + * @param sampleKey - PK of a sample + * @param projectFormName particular study we are working on + * @param projectData the data with two flags set. + * @return List of analysis + */ + // TODO PAHill - refactor - needs to be moved to some type of a utility + // class. + public static List findAnalysis(String sampleKey, String projectFormName, ProjectData projectData) { + IProjectFormMapper projectFormMapper = new ProjectFormMapperFactory().getProjectInitializer(projectFormName, + null); + projectFormMapper.setProjectData(projectData); + List typeOfSampleTestsList = projectFormMapper.getTypeOfSampleTests(); + if (typeOfSampleTestsList.size() == 0) { + throw new IllegalArgumentException("The combination of sampleItem type and test (panel) is not valid."); + } + TypeOfSampleTests sampleTests = typeOfSampleTestsList.get(0); + List tests = sampleTests.tests; + + List testIds = new ArrayList<>(); + for (Test test : tests) { + testIds.add(Integer.valueOf(test.getId())); + } + return analysisService.getAnalysisBySampleAndTestIds(sampleKey, testIds); + + } + + private boolean wasSampleTypeSelected(String sampleId, String projectFormName, String sampleItemType) { + try { + String sampleItemDesc = changeUIIdToDescription(sampleItemType); + IProjectFormMapper projectFormMapper = new ProjectFormMapperFactory().getProjectInitializer(projectFormName, + null); + TypeOfSample typeOfSample = projectFormMapper.getTypeOfSample(sampleItemDesc); + List sampleItems = sampleItemService.getSampleItemsBySampleId(sampleId); + for (SampleItem sampleItem : sampleItems) { + if (sampleItem.getTypeOfSampleId().equals(typeOfSample.getId())) { + return true; + } + } + return false; + } catch (Exception e) { + LogEvent.logError(e); + return false; + } + } + + private String changeUIIdToDescription(String sampleTypeId) { + String description = sampleTypeId; + int i = sampleTypeId.indexOf("Tube"); + if (i != -1) { + description = sampleTypeId.substring(0, i) + " Tube"; + } + return description; + } } diff --git a/src/main/java/org/openelisglobal/common/provider/validation/AccessionNumberValidatorFactory.java b/src/main/java/org/openelisglobal/common/provider/validation/AccessionNumberValidatorFactory.java index c44c0d57ec..b972863658 100644 --- a/src/main/java/org/openelisglobal/common/provider/validation/AccessionNumberValidatorFactory.java +++ b/src/main/java/org/openelisglobal/common/provider/validation/AccessionNumberValidatorFactory.java @@ -158,7 +158,7 @@ private IAccessionNumberGenerator getYearNumValidator(int length, Character sepa } private IAccessionNumberGenerator getAlphanumValidator() { - return new Base27AccessionValidator(); + return new AlphanumAccessionValidator(); } private IAccessionNumberGenerator getSiteYearValidator() { diff --git a/src/main/java/org/openelisglobal/common/provider/validation/Base27AccessionValidator.java b/src/main/java/org/openelisglobal/common/provider/validation/AlphanumAccessionValidator.java similarity index 98% rename from src/main/java/org/openelisglobal/common/provider/validation/Base27AccessionValidator.java rename to src/main/java/org/openelisglobal/common/provider/validation/AlphanumAccessionValidator.java index b7b4913a7d..477f35be4f 100644 --- a/src/main/java/org/openelisglobal/common/provider/validation/Base27AccessionValidator.java +++ b/src/main/java/org/openelisglobal/common/provider/validation/AlphanumAccessionValidator.java @@ -19,7 +19,7 @@ import org.openelisglobal.sample.util.AccessionNumberUtil; import org.openelisglobal.spring.util.SpringContext; -public class Base27AccessionValidator implements IAccessionNumberGenerator { +public class AlphanumAccessionValidator implements IAccessionNumberGenerator { protected SampleService sampleService = SpringContext.getBean(SampleService.class); protected AccessionService accessionService = SpringContext.getBean(AccessionService.class); @@ -123,7 +123,7 @@ public ValidationResults validFormat(String accessionNumber, boolean checkDate) } try { - Long.parseLong(accessionNumber.substring(getIncrementStartIndex())); + IntegerUtil.parseIntBase27(accessionNumber.substring(getIncrementStartIndex())); } catch (NumberFormatException e) { return ValidationResults.FORMAT_FAIL; } diff --git a/src/main/java/org/openelisglobal/common/rest/DisplayListController.java b/src/main/java/org/openelisglobal/common/rest/DisplayListController.java index 94df0b2aa1..ae13b8e493 100644 --- a/src/main/java/org/openelisglobal/common/rest/DisplayListController.java +++ b/src/main/java/org/openelisglobal/common/rest/DisplayListController.java @@ -31,6 +31,8 @@ import org.openelisglobal.provider.service.ProviderService; import org.openelisglobal.provider.valueholder.Provider; import org.openelisglobal.role.service.RoleService; +import org.openelisglobal.siteinformation.service.SiteInformationService; +import org.openelisglobal.siteinformation.valueholder.SiteInformation; import org.openelisglobal.spring.util.SpringContext; import org.openelisglobal.systemuser.service.UserService; import org.openelisglobal.test.service.TestService; @@ -74,6 +76,9 @@ public class DisplayListController extends BaseRestController{ @Autowired private OrganizationService organizationService; + @Autowired + private SiteInformationService siteInformationService; + private static boolean HAS_NFS_PANEL = false; static { @@ -254,7 +259,12 @@ private List getSiteNameList() { @ResponseBody private Map getConfigurationProperties() { Map configs = getOpenConfigurationProperties(); + + configs.put(Property.allowResultRejection.toString() ,ConfigurationProperties.getInstance().getPropertyValue( + Property.allowResultRejection)); + configs.put(Property.AccessionFormat.toString(), ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat)); + return configs; } @@ -281,6 +291,12 @@ private Map getOpenConfigurationProperties() { configs.put("currentTimeAsText",DateUtil.getCurrentTimeAsText()); configs.put(Property.BANNER_TEXT.toString(), localizationService .getLocalizedValueById(ConfigurationProperties.getInstance().getPropertyValue(Property.BANNER_TEXT))); + SiteInformation patientManagementTab = siteInformationService.getSiteInformationByName("Patient management tab"); + SiteInformation studyManagementTab = siteInformationService.getSiteInformationByName("Study Management tab"); + SiteInformation nonConformityTab = siteInformationService.getSiteInformationByName("Non Conformity tab"); + configs.put("patientManagementTab", patientManagementTab != null ? patientManagementTab.getValue() : "false"); + configs.put("studyManagementTab", studyManagementTab != null ? studyManagementTab.getValue() : "false"); + configs.put("nonConformityTab", nonConformityTab != null ? nonConformityTab.getValue() : "false"); return configs; } diff --git a/src/main/java/org/openelisglobal/common/service/servlet/reports/LogoUploadServiceImpl.java b/src/main/java/org/openelisglobal/common/service/servlet/reports/LogoUploadServiceImpl.java index cc5db51066..4946f84c0c 100644 --- a/src/main/java/org/openelisglobal/common/service/servlet/reports/LogoUploadServiceImpl.java +++ b/src/main/java/org/openelisglobal/common/service/servlet/reports/LogoUploadServiceImpl.java @@ -34,7 +34,7 @@ public void saveImage(Image image, boolean newImage, String imageId, SiteInforma image.setId(imageId); imageService.delete(image); } - Image savedImage = imageService.save(image); + Image savedImage = imageService.save(image); logoInformation.setValue(savedImage.getId()); logoInformation.setSysUserId("1"); diff --git a/src/main/java/org/openelisglobal/common/services/DisplayListService.java b/src/main/java/org/openelisglobal/common/services/DisplayListService.java index 46d279ba18..52749fb962 100644 --- a/src/main/java/org/openelisglobal/common/services/DisplayListService.java +++ b/src/main/java/org/openelisglobal/common/services/DisplayListService.java @@ -41,6 +41,7 @@ import org.openelisglobal.method.service.MethodService; import org.openelisglobal.method.valueholder.Method; import org.openelisglobal.organization.service.OrganizationService; +import org.openelisglobal.organization.util.OrganizationTypeList; import org.openelisglobal.organization.valueholder.Organization; import org.openelisglobal.panel.service.PanelService; import org.openelisglobal.panel.valueholder.Panel; @@ -98,7 +99,9 @@ public enum ListType { PATHOLOGIST_CONCLUSIONS ,IMMUNOHISTOCHEMISTRY_REPORT_TYPES ,IMMUNOHISTOCHEMISTRY_MARKERS_TESTS ,CYTOLOGY_STATUS, CYTOLOGY_SATISFACTORY_FOR_EVALUATION ,CYTOLOGY_UN_SATISFACTORY_FOR_EVALUATION ,CYTOLOGY_REPORT_TYPES, CYTOLOGY_DIAGNOSIS_RESULT_EPITHELIAL_CELL_SQUAMOUS ,CYTOLOGY_DIAGNOSIS_RESULT_EPITHELIAL_CELL_GLANDULAR ,CYTOLOGY_DIAGNOSIS_RESULT_NON_NEO_PLASTIC_CELLULAR, - CYTOLOGY_DIAGNOSIS_RESULT_REACTIVE_CELLULAR ,CYTOLOGY_DIAGNOSIS_RESULT_ORGANISMS , CYTOLOGY_DIAGNOSIS_RESULT_OTHER ; + CYTOLOGY_DIAGNOSIS_RESULT_REACTIVE_CELLULAR ,CYTOLOGY_DIAGNOSIS_RESULT_ORGANISMS , CYTOLOGY_DIAGNOSIS_RESULT_OTHER, + TB_ORDER_REASONS, TB_DIAGNOSTIC_REASONS, TB_FOLLOWUP_REASONS, TB_ANALYSIS_METHODS, TB_SAMPLE_ASPECTS, + TB_FOLLOWUP_LINE1, TB_FOLLOWUP_LINE2, ARV_ORG_LIST ; } private static Map> typeToListMap; @@ -153,7 +156,7 @@ private List createDictionaryTestResults() { List testResults = createFromDictionaryCategoryLocalizedSort("CG"); testResults.addAll(createFromDictionaryCategoryLocalizedSort("HL")); testResults.addAll(createFromDictionaryCategoryLocalizedSort("KL")); - testResults.addAll(createFromDictionaryCategoryLocalizedSort("Test Reslt")); + testResults.addAll(createFromDictionaryCategoryLocalizedSort("Test Result")); testResults.addAll(createFromDictionaryCategoryLocalizedSort("HIV1NInd")); testResults.addAll(createFromDictionaryCategoryLocalizedSort("PosNegIndInv")); testResults.addAll(createFromDictionaryCategoryLocalizedSort("HIVResult")); @@ -234,6 +237,14 @@ public void localeChanged(String locale) { typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_REACTIVE_CELLULAR, createDictionaryListForCategory("cytology_reactive_cellular_changes")); typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_ORGANISMS, createDictionaryListForCategory("cytology_diagnosis_organisms")); typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_OTHER, createDictionaryListForCategory("cytology_diagnosis_other")); + typeToListMap.put(ListType.TB_ORDER_REASONS, createDictionaryListForCategory("TB Order Reasons")); + typeToListMap.put(ListType.TB_DIAGNOSTIC_REASONS, createDictionaryListForCategory("TB Diagnostic Reasons")); + typeToListMap.put(ListType.TB_FOLLOWUP_REASONS, createDictionaryListForCategory("TB Followup Reasons")); + typeToListMap.put(ListType.TB_ANALYSIS_METHODS, createDictionaryListForCategory("TB Analysis Methods")); + typeToListMap.put(ListType.TB_SAMPLE_ASPECTS, createDictionaryListForCategory("TB Sample Aspects")); + typeToListMap.put(ListType.TB_FOLLOWUP_LINE1, createTBFollowupLine1List()); + typeToListMap.put(ListType.TB_FOLLOWUP_LINE2, createTBFollowupLine2List()); + typeToListMap.put(ListType.ARV_ORG_LIST, createArvOrgList()); } private List createPathologyStatusList() { @@ -475,6 +486,14 @@ public synchronized void refreshLists() { typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_REACTIVE_CELLULAR, createDictionaryListForCategory("cytology_reactive_cellular_changes")); typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_ORGANISMS, createDictionaryListForCategory("cytology_diagnosis_organisms")); typeToListMap.put(ListType.CYTOLOGY_DIAGNOSIS_RESULT_OTHER, createDictionaryListForCategory("cytology_diagnosis_other")); + typeToListMap.put(ListType.TB_ORDER_REASONS, createDictionaryListForCategory("TB Order Reasons")); + typeToListMap.put(ListType.TB_DIAGNOSTIC_REASONS, createDictionaryListForCategory("TB Diagnostic Reasons")); + typeToListMap.put(ListType.TB_FOLLOWUP_REASONS, createDictionaryListForCategory("TB Followup Reasons")); + typeToListMap.put(ListType.TB_ANALYSIS_METHODS, createDictionaryListForCategory("TB Analysis Methods")); + typeToListMap.put(ListType.TB_SAMPLE_ASPECTS, createDictionaryListForCategory("TB Sample Aspects")); + typeToListMap.put(ListType.TB_FOLLOWUP_LINE1, createTBFollowupLine1List()); + typeToListMap.put(ListType.TB_FOLLOWUP_LINE2, createTBFollowupLine2List()); + typeToListMap.put(ListType.ARV_ORG_LIST, createArvOrgList()); } public void refreshList(ListType listType) { @@ -570,6 +589,9 @@ public void refreshList(ListType listType) { case DICTIONARY_TEST_RESULTS: { typeToListMap.put(ListType.DICTIONARY_TEST_RESULTS, createDictionaryTestResults()); } + case ARV_ORG_LIST: { + typeToListMap.put(ListType.ARV_ORG_LIST, createArvOrgList()); + } } } @@ -610,6 +632,26 @@ private List createReferringClinicList() { return requesterList; } + private List createArvOrgList() { + List requesterList = new ArrayList<>(); + + List orgList = OrganizationTypeList.ARV_ORGS.getList(); + orgList.sort((e, f) -> { + return e.getOrganizationName().compareTo(f.getOrganizationName()); + }); + + for (Organization organization : orgList) { + if (GenericValidator.isBlankOrNull(organization.getShortName())) { + requesterList.add(new IdValuePair(organization.getId(), organization.getOrganizationName())); + } else { + requesterList.add(new IdValuePair(organization.getId(), + organization.getShortName() + " - " + organization.getOrganizationName())); + } + } + + return requesterList; + } + private List createGenderList() { List genders = new ArrayList<>(); @@ -843,163 +885,180 @@ private List createMethodList() { private List createUnitOfMeasureList() { List unitOfMeasuresPairs = new ArrayList<>(); // List unitOfMeasures = unitOfMeasureService.getAllActiveUnitOfMeasures(); - List unitOfMeasures = unitOfMeasureService.getAll(); - - for (UnitOfMeasure unitOfMeasure : unitOfMeasures) { - unitOfMeasuresPairs.add(new IdValuePair(unitOfMeasure.getId(), unitOfMeasure.getLocalizedName())); - } - - return unitOfMeasuresPairs; - } - - private List createTypeOfSampleList() { - List typeOfSamplePairs = new ArrayList<>(); - List typeOfSamples = typeOfSampleService.getAllTypeOfSamplesSortOrdered(); - - for (TypeOfSample typeOfSample : typeOfSamples) { - typeOfSamplePairs.add(new IdValuePair(typeOfSample.getId(), typeOfSample.getLocalizedName())); - } - - return typeOfSamplePairs; - } - - private List createInactiveTestSection() { - List testSectionsPairs = new ArrayList<>(); - List testSections = testSectionService.getAllInActiveTestSections(); - - for (TestSection section : testSections) { - testSectionsPairs.add(new IdValuePair(section.getId(), section.getLocalizedName())); - } - - return testSectionsPairs; - } - - private List createInactiveMethod() { - List methodPairs = new ArrayList<>(); - List methods = methodService.getAllInActiveMethods(); - - for (Method method : methods) { - methodPairs.add(new IdValuePair(method.getId(), method.getLocalization().getLocalizedValue())); - } - - return methodPairs; - } - - private List createTestSectionByNameList() { - List testSectionsPairs = new ArrayList<>(); - List testSections = testSectionService.getAllActiveTestSections(); - - for (TestSection section : testSections) { - testSectionsPairs.add(new IdValuePair(section.getId(), section.getTestSectionName())); - } - - return testSectionsPairs; - } - - private List createAddressDepartmentList() { - List departmentPairs = new ArrayList<>(); - List departments = dictionaryService.getDictionaryEntrysByCategoryAbbreviation("description", - "haitiDepartment", true); - - for (Dictionary dictionary : departments) { - departmentPairs.add(new IdValuePair(dictionary.getId(), dictionary.getDictEntry())); - } - - return departmentPairs; - } - - private List createPatientSearchCriteria() { - List searchCriteria = new ArrayList<>(); - - // N.B. If the order is to be changed just change the order but keep the - // id:value pairing the same - searchCriteria.add(new IdValuePair("0", MessageUtil.getMessage("label.select.search.by"))); - searchCriteria.add(new IdValuePair("2", "1. " + MessageUtil.getMessage("label.select.last.name"))); - searchCriteria.add(new IdValuePair("1", "2. " + MessageUtil.getMessage("label.select.first.name"))); - searchCriteria.add(new IdValuePair("3", "3. " + MessageUtil.getMessage("label.select.last.first.name"))); - searchCriteria.add(new IdValuePair("4", "4. " + MessageUtil.getMessage("label.select.patient.ID"))); - searchCriteria - .add(new IdValuePair("5", "5. " + MessageUtil.getContextualMessage("quick.entry.accession.number"))); - - return searchCriteria; - } - - private List createConsequencesList() { - List consequencesList = new ArrayList<>(); - - // N.B. If the order is to be changed just change the order but keep the - // id:value pairing the same - consequencesList.add(new IdValuePair("0", MessageUtil.getMessage("label.select.one"))); - consequencesList.add(new IdValuePair("1", MessageUtil.getMessage("label.select.consequences.none"))); - consequencesList.add(new IdValuePair("2", MessageUtil.getMessage("label.select.consequences.moderate"))); - consequencesList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.consequences.high"))); - return consequencesList; - } - - private List createRecurrenceList() { - List recurrenceList = new ArrayList<>(); - - // N.B. If the order is to be changed just change the order but keep the - // id:value pairing the same - recurrenceList.add(new IdValuePair("0", MessageUtil.getMessage("label.select.one"))); - recurrenceList.add(new IdValuePair("1", MessageUtil.getMessage("label.select.recurrence.not"))); - recurrenceList.add(new IdValuePair("2", MessageUtil.getMessage("label.select.recurrence.somewhat"))); - recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.recurrence.highly"))); - return recurrenceList; - } - - private List createActionTypeList() { - List recurrenceList = new ArrayList<>(); - - // N.B. If the order is to be changed just change the order but keep the - // id:value pairing the same - recurrenceList.add(new IdValuePair("1", MessageUtil.getMessage("label.input.actiontype.corrective"))); - recurrenceList.add(new IdValuePair("2", MessageUtil.getMessage("label.input.actiontype.preventive"))); - recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.input.actiontype.concurrent"))); - return recurrenceList; - } - - private List createLaboratoryComponentList() { - List recurrenceList = new ArrayList<>(); - - // N.B. If the order is to be changed just change the order but keep the - // id:value pairing the same - recurrenceList.add( - new IdValuePair("1", MessageUtil.getMessage("label.select.laboratoryComponent.facilitiesAndSafety"))); - recurrenceList - .add(new IdValuePair("2", MessageUtil.getMessage("label.select.laboratoryComponent.organization"))); - recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.laboratoryComponent.personnel"))); - recurrenceList.add(new IdValuePair("4", MessageUtil.getMessage("label.select.laboratoryComponent.equipment"))); - recurrenceList.add(new IdValuePair("5", MessageUtil.getMessage("label.select.laboratoryComponent.purchasing"))); - recurrenceList.add(new IdValuePair("6", MessageUtil.getMessage("label.select.laboratoryComponent.process"))); - recurrenceList - .add(new IdValuePair("7", MessageUtil.getMessage("label.select.laboratoryComponent.information"))); - recurrenceList.add(new IdValuePair("8", MessageUtil.getMessage("label.select.laboratoryComponent.documents"))); - recurrenceList.add(new IdValuePair("9", MessageUtil.getMessage("label.select.laboratoryComponent.assessment"))); - recurrenceList - .add(new IdValuePair("10", MessageUtil.getMessage("label.select.laboratoryComponent.nceManagement"))); - recurrenceList.add( - new IdValuePair("11", MessageUtil.getMessage("label.select.laboratoryComponent.continualImprovement"))); - return recurrenceList; - } - - private List createMethodByNameList() { - List methodsPairs = new ArrayList<>(); - List methods = methodService.getAllActiveMethods(); - for (Method method : methods) { - methodsPairs.add(new IdValuePair(method.getId(), method.getMethodName())); - } - return methodsPairs; - } - - private List createSamplePriorityList() { - List priorities = new ArrayList<>(); - priorities.add(new IdValuePair(OrderPriority.ROUTINE.name(), MessageUtil.getMessage("label.priority.routine"))); - priorities.add(new IdValuePair(OrderPriority.ASAP.name(), MessageUtil.getMessage("label.priority.asap"))); - priorities.add(new IdValuePair(OrderPriority.STAT.name(), MessageUtil.getMessage("label.priority.stat"))); - priorities.add(new IdValuePair(OrderPriority.TIMED.name(), MessageUtil.getMessage("label.priority.timed"))); - priorities.add( - new IdValuePair(OrderPriority.FUTURE_STAT.name(), MessageUtil.getMessage("label.priority.futureStat"))); - return priorities; - } + List unitOfMeasures = unitOfMeasureService.getAll(); + + for (UnitOfMeasure unitOfMeasure : unitOfMeasures) { + unitOfMeasuresPairs.add(new IdValuePair(unitOfMeasure.getId(), unitOfMeasure.getLocalizedName())); + } + + return unitOfMeasuresPairs; + } + + private List createTypeOfSampleList() { + List typeOfSamplePairs = new ArrayList<>(); + List typeOfSamples = typeOfSampleService.getAllTypeOfSamplesSortOrdered(); + + for (TypeOfSample typeOfSample : typeOfSamples) { + typeOfSamplePairs.add(new IdValuePair(typeOfSample.getId(), typeOfSample.getLocalizedName())); + } + + return typeOfSamplePairs; + } + + private List createInactiveTestSection() { + List testSectionsPairs = new ArrayList<>(); + List testSections = testSectionService.getAllInActiveTestSections(); + + for (TestSection section : testSections) { + testSectionsPairs.add(new IdValuePair(section.getId(), section.getLocalizedName())); + } + + return testSectionsPairs; + } + + private List createInactiveMethod() { + List methodPairs = new ArrayList<>(); + List methods = methodService.getAllInActiveMethods(); + + for (Method method : methods) { + methodPairs.add(new IdValuePair(method.getId(), method.getLocalization().getLocalizedValue())); + } + + return methodPairs; + } + + private List createTestSectionByNameList() { + List testSectionsPairs = new ArrayList<>(); + List testSections = testSectionService.getAllActiveTestSections(); + + for (TestSection section : testSections) { + testSectionsPairs.add(new IdValuePair(section.getId(), section.getTestSectionName())); + } + + return testSectionsPairs; + } + + private List createAddressDepartmentList() { + List departmentPairs = new ArrayList<>(); + List departments = dictionaryService.getDictionaryEntrysByCategoryAbbreviation("description", + "haitiDepartment", true); + + for (Dictionary dictionary : departments) { + departmentPairs.add(new IdValuePair(dictionary.getId(), dictionary.getDictEntry())); + } + + return departmentPairs; + } + + private List createPatientSearchCriteria() { + List searchCriteria = new ArrayList<>(); + + // N.B. If the order is to be changed just change the order but keep the + // id:value pairing the same + searchCriteria.add(new IdValuePair("0", MessageUtil.getMessage("label.select.search.by"))); + searchCriteria.add(new IdValuePair("2", "1. " + MessageUtil.getMessage("label.select.last.name"))); + searchCriteria.add(new IdValuePair("1", "2. " + MessageUtil.getMessage("label.select.first.name"))); + searchCriteria.add(new IdValuePair("3", "3. " + MessageUtil.getMessage("label.select.last.first.name"))); + searchCriteria.add(new IdValuePair("4", "4. " + MessageUtil.getMessage("label.select.patient.ID"))); + searchCriteria + .add(new IdValuePair("5", "5. " + MessageUtil.getContextualMessage("quick.entry.accession.number"))); + + return searchCriteria; + } + + private List createConsequencesList() { + List consequencesList = new ArrayList<>(); + + // N.B. If the order is to be changed just change the order but keep the + // id:value pairing the same + consequencesList.add(new IdValuePair("0", MessageUtil.getMessage("label.select.one"))); + consequencesList.add(new IdValuePair("1", MessageUtil.getMessage("label.select.consequences.none"))); + consequencesList.add(new IdValuePair("2", MessageUtil.getMessage("label.select.consequences.moderate"))); + consequencesList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.consequences.high"))); + return consequencesList; + } + + private List createRecurrenceList() { + List recurrenceList = new ArrayList<>(); + + // N.B. If the order is to be changed just change the order but keep the + // id:value pairing the same + recurrenceList.add(new IdValuePair("0", MessageUtil.getMessage("label.select.one"))); + recurrenceList.add(new IdValuePair("1", MessageUtil.getMessage("label.select.recurrence.not"))); + recurrenceList.add(new IdValuePair("2", MessageUtil.getMessage("label.select.recurrence.somewhat"))); + recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.recurrence.highly"))); + return recurrenceList; + } + + private List createTBFollowupLine1List() { + List tbFollowupLine1List = new ArrayList<>(); + tbFollowupLine1List.add(new IdValuePair("M2", MessageUtil.getMessage("dictionary.tb.order.followup") + " M2")); + tbFollowupLine1List.add(new IdValuePair("M5", MessageUtil.getMessage("dictionary.tb.order.followup") + " M5")); + tbFollowupLine1List.add(new IdValuePair("M6", MessageUtil.getMessage("dictionary.tb.order.followup") + " M6")); + return tbFollowupLine1List; + } + + private List createTBFollowupLine2List() { + List tbFollowupLine2List = new ArrayList<>(); + for (int i = 0; i <= 24; i++) { + tbFollowupLine2List + .add(new IdValuePair("M" + i, MessageUtil.getMessage("dictionary.tb.order.followup") + " M" + i)); + } + return tbFollowupLine2List; + } + + private List createActionTypeList() { + List recurrenceList = new ArrayList<>(); + + // N.B. If the order is to be changed just change the order but keep the + // id:value pairing the same + recurrenceList.add(new IdValuePair("1", MessageUtil.getMessage("label.input.actiontype.corrective"))); + recurrenceList.add(new IdValuePair("2", MessageUtil.getMessage("label.input.actiontype.preventive"))); + recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.input.actiontype.concurrent"))); + return recurrenceList; + } + + private List createLaboratoryComponentList() { + List recurrenceList = new ArrayList<>(); + + // N.B. If the order is to be changed just change the order but keep the + // id:value pairing the same + recurrenceList.add( + new IdValuePair("1", MessageUtil.getMessage("label.select.laboratoryComponent.facilitiesAndSafety"))); + recurrenceList + .add(new IdValuePair("2", MessageUtil.getMessage("label.select.laboratoryComponent.organization"))); + recurrenceList.add(new IdValuePair("3", MessageUtil.getMessage("label.select.laboratoryComponent.personnel"))); + recurrenceList.add(new IdValuePair("4", MessageUtil.getMessage("label.select.laboratoryComponent.equipment"))); + recurrenceList.add(new IdValuePair("5", MessageUtil.getMessage("label.select.laboratoryComponent.purchasing"))); + recurrenceList.add(new IdValuePair("6", MessageUtil.getMessage("label.select.laboratoryComponent.process"))); + recurrenceList + .add(new IdValuePair("7", MessageUtil.getMessage("label.select.laboratoryComponent.information"))); + recurrenceList.add(new IdValuePair("8", MessageUtil.getMessage("label.select.laboratoryComponent.documents"))); + recurrenceList.add(new IdValuePair("9", MessageUtil.getMessage("label.select.laboratoryComponent.assessment"))); + recurrenceList + .add(new IdValuePair("10", MessageUtil.getMessage("label.select.laboratoryComponent.nceManagement"))); + recurrenceList.add( + new IdValuePair("11", MessageUtil.getMessage("label.select.laboratoryComponent.continualImprovement"))); + return recurrenceList; + } + + private List createMethodByNameList() { + List methodsPairs = new ArrayList<>(); + List methods = methodService.getAllActiveMethods(); + for (Method method : methods) { + methodsPairs.add(new IdValuePair(method.getId(), method.getMethodName())); + } + return methodsPairs; + } + + private List createSamplePriorityList() { + List priorities = new ArrayList<>(); + priorities.add(new IdValuePair(OrderPriority.ROUTINE.name(), MessageUtil.getMessage("label.priority.routine"))); + priorities.add(new IdValuePair(OrderPriority.ASAP.name(), MessageUtil.getMessage("label.priority.asap"))); + priorities.add(new IdValuePair(OrderPriority.STAT.name(), MessageUtil.getMessage("label.priority.stat"))); + priorities.add(new IdValuePair(OrderPriority.TIMED.name(), MessageUtil.getMessage("label.priority.timed"))); + priorities.add( + new IdValuePair(OrderPriority.FUTURE_STAT.name(), MessageUtil.getMessage("label.priority.futureStat"))); + return priorities; + } } diff --git a/src/main/java/org/openelisglobal/common/util/DateUtil.java b/src/main/java/org/openelisglobal/common/util/DateUtil.java index 9987a57970..facfb7aa7a 100644 --- a/src/main/java/org/openelisglobal/common/util/DateUtil.java +++ b/src/main/java/org/openelisglobal/common/util/DateUtil.java @@ -620,7 +620,7 @@ public static Timestamp convertStringDateStringTimeToTimestamp(String date, Stri if (!GenericValidator.isBlankOrNull(date) && !GenericValidator.isBlankOrNull(time)) { date = date + " " + time; } else if (!GenericValidator.isBlankOrNull(date) && GenericValidator.isBlankOrNull(time)) { - date = date + " 00:00"; + date = date + " 09:00"; } else { return null; } diff --git a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirApiWorkFlowServiceImpl.java b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirApiWorkFlowServiceImpl.java index 60806cae28..c636b4a0b8 100644 --- a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirApiWorkFlowServiceImpl.java +++ b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirApiWorkFlowServiceImpl.java @@ -498,6 +498,9 @@ private Task saveTaskBasedOnRemoteTask(IGenericClient fhirClient, Task remoteTas referenceString = referenceString + "/"; } referenceString = referenceString + ResourceType.Task.toString() + "/" + remoteTask.getIdElement().getIdPart(); + if (referenceString.endsWith("null")) { + LogEvent.logWarn(this.getClass().getName(), "saveTaskBasedOnRemoteTask", "remote task has a null identifier: " + remoteTask.getId()); + } reference.setReference(referenceString); taskBasedOnRemoteTask.addBasedOn(reference); diff --git a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceService.java b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceService.java index f2ab9026b0..cfced03d4f 100644 --- a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceService.java +++ b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceService.java @@ -40,6 +40,8 @@ Bundle createUpdateFhirResourcesInFhirStore(List fhirOperationsL Optional getTaskBasedOnServiceRequest(String referringId); + Optional getServiceRequestByReferingId(String referringId); + Optional getTaskBasedOnTask(String taskId); Bundle createUpdateFhirResourcesInFhirStore(Map createResources, diff --git a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceServiceImpl.java b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceServiceImpl.java index 48e13f2458..21aceeb1af 100644 --- a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceServiceImpl.java +++ b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirPersistanceServiceImpl.java @@ -354,6 +354,40 @@ public Optional getTaskBasedOnServiceRequest(String referringId) { return Optional.empty(); } + @Override + public Optional getServiceRequestByReferingId(String referringId) { + ServiceRequest serviceRequest = null; + Bundle bundle = localFhirClient.search()// + .forResource(ServiceRequest.class)// + .returnBundle(Bundle.class)// + .where(ServiceRequest.IDENTIFIER.exactly().identifier(referringId))// + .execute(); + if (bundle.hasEntry()) { + serviceRequest = (ServiceRequest) bundle.getEntryFirstRep().getResource(); + } + if (serviceRequest == null) { + LogEvent.logDebug(this.getClass().getName(), "", "no service request with identifier " + referringId); + for (String remotePath : fhirConfig.getRemoteStorePaths()) { + + bundle = localFhirClient.search()// + .forResource(ServiceRequest.class)// + .returnBundle(Bundle.class)// + .where(ServiceRequest.IDENTIFIER.exactly().systemAndIdentifier(remotePath, referringId))// + .execute(); + if (bundle.hasEntry()) { + serviceRequest = (ServiceRequest) bundle.getEntryFirstRep().getResource(); + } + } + } + if (serviceRequest == null) { + LogEvent.logDebug(this.getClass().getName(), "", + "no service request with identifier " + referringId + " with configured systems"); + } else { + return Optional.of(serviceRequest); + } + return Optional.empty(); + } + @Override public Optional getTaskBasedOnTask(String taskId) { Bundle bundle = localFhirClient.search()// diff --git a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirTransformServiceImpl.java b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirTransformServiceImpl.java index ca026ee213..047893f8c7 100644 --- a/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirTransformServiceImpl.java +++ b/src/main/java/org/openelisglobal/dataexchange/fhir/service/FhirTransformServiceImpl.java @@ -118,72 +118,72 @@ @Service public class FhirTransformServiceImpl implements FhirTransformService { - @Autowired - private FhirConfig fhirConfig; - @Autowired - private ElectronicOrderService electronicOrderService; - @Autowired - private PatientService patientService; - @Autowired - private TypeOfSampleService typeOfSampleService; - @Autowired - private SampleService sampleService; - @Autowired - private AnalysisService analysisService; - @Autowired - private TestService testService; - @Autowired - private ResultService resultService; - @Autowired - private SampleHumanService sampleHumanService; - @Autowired - private FhirPersistanceService fhirPersistanceService; - @Autowired - private DictionaryService dictionaryService; - @Autowired - private LocalizationService localizationService; - @Autowired - private NoteService noteService; - @Autowired - private SampleItemService sampleItemService; - @Autowired - private ObservationHistoryService observationHistoryService; - @Autowired - private IStatusService statusService; - @Autowired - private ProviderService providerService; - @Autowired - private ReferralSetService referralSetService; - @Autowired - private PersonAddressService personAddressService; - @Autowired - private AddressPartService addressPartService; - - private String ADDRESS_PART_VILLAGE_ID; - private String ADDRESS_PART_COMMUNE_ID; - private String ADDRESS_PART_DEPT_ID; - - @PostConstruct - public void initializeGlobalVariables() { - List partList = addressPartService.getAll(); - for (AddressPart addressPart : partList) { - if ("department".equals(addressPart.getPartName())) { - ADDRESS_PART_DEPT_ID = addressPart.getId(); - } else if ("commune".equals(addressPart.getPartName())) { - ADDRESS_PART_COMMUNE_ID = addressPart.getId(); - } else if ("village".equals(addressPart.getPartName())) { - ADDRESS_PART_VILLAGE_ID = addressPart.getId(); - } - } - - } - - @Transactional - @Async - @Override - public AsyncResult transformPersistPatients(List patientIds) throws FhirLocalPersistingException { - FhirOperations fhirOperations = new FhirOperations(); - CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); + @Autowired + private FhirConfig fhirConfig; + @Autowired + private ElectronicOrderService electronicOrderService; + @Autowired + private PatientService patientService; + @Autowired + private TypeOfSampleService typeOfSampleService; + @Autowired + private SampleService sampleService; + @Autowired + private AnalysisService analysisService; + @Autowired + private TestService testService; + @Autowired + private ResultService resultService; + @Autowired + private SampleHumanService sampleHumanService; + @Autowired + private FhirPersistanceService fhirPersistanceService; + @Autowired + private DictionaryService dictionaryService; + @Autowired + private LocalizationService localizationService; + @Autowired + private NoteService noteService; + @Autowired + private SampleItemService sampleItemService; + @Autowired + private ObservationHistoryService observationHistoryService; + @Autowired + private IStatusService statusService; + @Autowired + private ProviderService providerService; + @Autowired + private ReferralSetService referralSetService; + @Autowired + private PersonAddressService personAddressService; + @Autowired + private AddressPartService addressPartService; + + private String ADDRESS_PART_VILLAGE_ID; + private String ADDRESS_PART_COMMUNE_ID; + private String ADDRESS_PART_DEPT_ID; + + @PostConstruct + public void initializeGlobalVariables() { + List partList = addressPartService.getAll(); + for (AddressPart addressPart : partList) { + if ("department".equals(addressPart.getPartName())) { + ADDRESS_PART_DEPT_ID = addressPart.getId(); + } else if ("commune".equals(addressPart.getPartName())) { + ADDRESS_PART_COMMUNE_ID = addressPart.getId(); + } else if ("village".equals(addressPart.getPartName())) { + ADDRESS_PART_VILLAGE_ID = addressPart.getId(); + } + } + + } + + @Transactional + @Async + @Override + public AsyncResult transformPersistPatients(List patientIds) throws FhirLocalPersistingException { + FhirOperations fhirOperations = new FhirOperations(); + CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); Map fhirPatients = new HashMap<>(); for (String patientId : patientIds) { @@ -193,27 +193,28 @@ public AsyncResult transformPersistPatients(List patientIds) thr } org.hl7.fhir.r4.model.Patient fhirPatient = this.transformToFhirPatient(patient); if (fhirPatients.containsKey(fhirPatient.getIdElement().getIdPart())) { - LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistPatients", "patient collision with id: " + fhirPatient.getIdElement().getIdPart()); + LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistPatients", + "patient collision with id: " + fhirPatient.getIdElement().getIdPart()); } fhirPatients.put(fhirPatient.getIdElement().getIdPart(), fhirPatient); - } + } - for (org.hl7.fhir.r4.model.Patient fhirPatient : fhirPatients.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, fhirPatient); - } + for (org.hl7.fhir.r4.model.Patient fhirPatient : fhirPatients.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, fhirPatient); + } - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - return new AsyncResult<>(responseBundle); - } + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + return new AsyncResult<>(responseBundle); + } - @Transactional - @Async - @Override - public AsyncResult transformPersistObjectsUnderSamples(List sampleIds) - throws FhirLocalPersistingException { - FhirOperations fhirOperations = new FhirOperations(); - CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); + @Transactional + @Async + @Override + public AsyncResult transformPersistObjectsUnderSamples(List sampleIds) + throws FhirLocalPersistingException { + FhirOperations fhirOperations = new FhirOperations(); + CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); Map tasks = new HashMap<>(); Map fhirPatients = new HashMap<>(); @@ -232,26 +233,26 @@ public AsyncResult transformPersistObjectsUnderSamples(List samp List analysises = analysisService.getAnalysesBySampleId(sampleId); List results = resultService.getResultsForSample(sample); - if (sample.getFhirUuid() == null) { - sample.setFhirUuid(UUID.randomUUID()); - } - if (patient.getFhirUuid() == null) { - patient.setFhirUuid(UUID.randomUUID()); - } - if (provider.getFhirUuid() == null) { - provider.setFhirUuid(UUID.randomUUID()); - } - sampleItems.stream().forEach((e) -> { - if (e.getFhirUuid() == null) { - e.setFhirUuid(UUID.randomUUID()); - } - }); - - analysises.stream().forEach((e) -> { - if (e.getFhirUuid() == null) { - e.setFhirUuid(UUID.randomUUID()); - } - }); + if (sample.getFhirUuid() == null) { + sample.setFhirUuid(UUID.randomUUID()); + } + if (patient.getFhirUuid() == null) { + patient.setFhirUuid(UUID.randomUUID()); + } + if (provider.getFhirUuid() == null) { + provider.setFhirUuid(UUID.randomUUID()); + } + sampleItems.stream().forEach((e) -> { + if (e.getFhirUuid() == null) { + e.setFhirUuid(UUID.randomUUID()); + } + }); + + analysises.stream().forEach((e) -> { + if (e.getFhirUuid() == null) { + e.setFhirUuid(UUID.randomUUID()); + } + }); results.stream().forEach((e) -> { if (e.getFhirUuid() == null) { @@ -260,7 +261,8 @@ public AsyncResult transformPersistObjectsUnderSamples(List samp }); Task task = this.transformToTask(sample); if (tasks.containsKey(task.getIdElement().getIdPart())) { - LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", "task collision with id: " + task.getIdElement().getIdPart()); + LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", + "task collision with id: " + task.getIdElement().getIdPart()); } tasks.put(task.getIdElement().getIdPart(), task); @@ -275,20 +277,23 @@ public AsyncResult transformPersistObjectsUnderSamples(List samp org.hl7.fhir.r4.model.Patient fhirPatient = this.transformToFhirPatient(patient); if (fhirPatients.containsKey(fhirPatient.getIdElement().getIdPart())) { - LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", "patient collision with id: " + fhirPatient.getIdElement().getIdPart()); + LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", + "patient collision with id: " + fhirPatient.getIdElement().getIdPart()); } fhirPatients.put(fhirPatient.getIdElement().getIdPart(), fhirPatient); Practitioner requester = transformProviderToPractitioner(provider); if (requesters.containsKey(requester.getIdElement().getIdPart())) { - LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", "practitioner collision with id: " + fhirPatient.getIdElement().getIdPart()); + LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", + "practitioner collision with id: " + fhirPatient.getIdElement().getIdPart()); } requesters.put(requester.getIdElement().getIdPart(), requester); for (SampleItem sampleItem : sampleItems) { Specimen specimen = this.transformToSpecimen(sampleItem); if (specimens.containsKey(specimen.getIdElement().getIdPart())) { - LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", "specimen collision with id: " + specimen.getIdElement().getIdPart()); + LogEvent.logWarn(this.getClass().getSimpleName(), "transformPersistObjectsUnderSamples", + "specimen collision with id: " + specimen.getIdElement().getIdPart()); } specimens.put(specimen.getIdElement().getIdPart(), specimen); } @@ -318,43 +323,43 @@ public AsyncResult transformPersistObjectsUnderSamples(List samp } } - for (Task task : tasks.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, task); - } - for (org.hl7.fhir.r4.model.Patient fhirPatient : fhirPatients.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, fhirPatient); - } - for (Specimen specimen : specimens.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, specimen); - } - for (ServiceRequest serviceRequest : serviceRequests.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); - } - for (Observation observation : observations.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, observation); - } - for (DiagnosticReport diagnosticReport : diagnosticReports.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); - } - - for (Practitioner requester : requesters.values()) { - this.addToOperations(fhirOperations, tempIdGenerator, requester); - } - - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - return new AsyncResult<>(responseBundle); - } - - @Override - @Async - @Transactional(readOnly = true) - public void transformPersistPatient(PatientManagementInfo patientInfo) throws FhirLocalPersistingException { - CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); - FhirOperations fhirOperations = new FhirOperations(); - org.hl7.fhir.r4.model.Patient patient = transformToFhirPatient(patientInfo.getPatientPK()); - this.addToOperations(fhirOperations, tempIdGenerator, patient); - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - } + for (Task task : tasks.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, task); + } + for (org.hl7.fhir.r4.model.Patient fhirPatient : fhirPatients.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, fhirPatient); + } + for (Specimen specimen : specimens.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, specimen); + } + for (ServiceRequest serviceRequest : serviceRequests.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); + } + for (Observation observation : observations.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, observation); + } + for (DiagnosticReport diagnosticReport : diagnosticReports.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); + } + + for (Practitioner requester : requesters.values()) { + this.addToOperations(fhirOperations, tempIdGenerator, requester); + } + + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + return new AsyncResult<>(responseBundle); + } + + @Override + @Async + @Transactional(readOnly = true) + public void transformPersistPatient(PatientManagementInfo patientInfo) throws FhirLocalPersistingException { + CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); + FhirOperations fhirOperations = new FhirOperations(); + org.hl7.fhir.r4.model.Patient patient = transformToFhirPatient(patientInfo.getPatientPK()); + this.addToOperations(fhirOperations, tempIdGenerator, patient); + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + } @Override @Async @@ -367,47 +372,53 @@ public void transformPersistOrderEntryFhirObjects(SamplePatientUpdateData update CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); FhirOperations fhirOperations = new FhirOperations(); - FhirOrderEntryObjects orderEntryObjects = new FhirOrderEntryObjects(); - // TODO should we create a task per service request that is part of this task so - // we can have the ServiceRequest as the focus in those tasks? - // task for entering the order - Task task = transformToTask(updateData.getSample().getId()); - this.addToOperations(fhirOperations, tempIdGenerator, task); - - Optional referringTask = getReferringTaskForSample(updateData.getSample()); - if (referringTask.isPresent()) { - updateReferringTaskWithTaskInfo(referringTask.get(), task); - this.addToOperations(fhirOperations, tempIdGenerator, referringTask.get()); - } - - // patient - org.hl7.fhir.r4.model.Patient patient = transformToFhirPatient(patientInfo.getPatientPK()); - this.addToOperations(fhirOperations, tempIdGenerator, patient); - orderEntryObjects.patient = patient; - - // requester - Practitioner requester = transformProviderToPractitioner(updateData.getProvider().getId()); - this.addToOperations(fhirOperations, tempIdGenerator, requester); - orderEntryObjects.requester = requester; - - // Specimens and service requests - for (SampleTestCollection sampleTest : updateData.getSampleItemsTests()) { - FhirSampleEntryObjects fhirSampleEntryObjects = new FhirSampleEntryObjects(); - fhirSampleEntryObjects.specimen = transformToFhirSpecimen(sampleTest); - - // TODO collector + FhirOrderEntryObjects orderEntryObjects = new FhirOrderEntryObjects(); + // TODO should we create a task per service request that is part of this task so + // we can have the ServiceRequest as the focus in those tasks? + // task for entering the order + Task task = transformToTask(updateData.getSample().getId()); + this.addToOperations(fhirOperations, tempIdGenerator, task); + + Optional referringTask = getReferringTaskForSample(updateData.getSample()); + if (referringTask.isPresent()) { + updateReferringTaskWithTaskInfo(referringTask.get(), task); + this.addToOperations(fhirOperations, tempIdGenerator, referringTask.get()); + } + + Optional referingServiceRequest = getReferringServiceRequestForSample(updateData.getSample()); + if (referingServiceRequest.isPresent()) { + updateReferringServiceRequestWithSampleInfo(updateData.getSample(), referingServiceRequest.get()); + this.addToOperations(fhirOperations, tempIdGenerator, referingServiceRequest.get()); + } + + // patient + org.hl7.fhir.r4.model.Patient patient = transformToFhirPatient(patientInfo.getPatientPK()); + this.addToOperations(fhirOperations, tempIdGenerator, patient); + orderEntryObjects.patient = patient; + + // requester + Practitioner requester = transformProviderToPractitioner(updateData.getProvider().getId()); + this.addToOperations(fhirOperations, tempIdGenerator, requester); + orderEntryObjects.requester = requester; + + // Specimens and service requests + for (SampleTestCollection sampleTest : updateData.getSampleItemsTests()) { + FhirSampleEntryObjects fhirSampleEntryObjects = new FhirSampleEntryObjects(); + fhirSampleEntryObjects.specimen = transformToFhirSpecimen(sampleTest); + + // TODO collector // fhirSampleEntryObjects.collector = transformCollectorToPractitioner(sampleTest.item.getCollector()); - fhirSampleEntryObjects.serviceRequests = transformToServiceRequests(updateData, sampleTest); + fhirSampleEntryObjects.serviceRequests = transformToServiceRequests(updateData, sampleTest); - this.addToOperations(fhirOperations, tempIdGenerator, fhirSampleEntryObjects.specimen); + this.addToOperations(fhirOperations, tempIdGenerator, fhirSampleEntryObjects.specimen); // this.addToOperations(fhirOperations, tempIdGenerator, fhirSampleEntryObjects.collector); - for (ServiceRequest serviceRequest : fhirSampleEntryObjects.serviceRequests) { - this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); - } + for (ServiceRequest serviceRequest : fhirSampleEntryObjects.serviceRequests) { + this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); + } - orderEntryObjects.sampleEntryObjectsList.add(fhirSampleEntryObjects); - } + orderEntryObjects.sampleEntryObjectsList.add(fhirSampleEntryObjects); + } if (updateData.getProgramQuestionnaireResponse() != null) { updateData.getProgramQuestionnaireResponse() @@ -418,578 +429,591 @@ public void transformPersistOrderEntryFhirObjects(SamplePatientUpdateData update // TODO location? // TODO create encounter? - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - - if (useReferral) { - referralSetService.createSaveReferralSetsSamplePatientEntry(referralItems, updateData); - } - } - - private void updateReferringTaskWithTaskInfo(Task referringTask, Task task) { - if (TaskStatus.COMPLETED.equals(task.getStatus())) { - referringTask.setStatus(TaskStatus.COMPLETED); - task.getOutput().forEach(outPut -> { - referringTask.addOutput(outPut); - }); - } - } - - private Optional getReferringTaskForSample(Sample sample) { - List eOrders = electronicOrderService.getElectronicOrdersByExternalId(sample.getReferringId()); - if (eOrders.size() > 0 && ElectronicOrderType.FHIR.equals(eOrders.get(0).getType())) { - return fhirPersistanceService.getTaskBasedOnServiceRequest(sample.getReferringId()); - } - return Optional.empty(); - } - - private Practitioner transformProviderToPractitioner(String providerId) { - return transformProviderToPractitioner(providerService.get(providerId)); - } - - @Override - public Practitioner transformProviderToPractitioner(Provider provider) { - Practitioner practitioner = new Practitioner(); - practitioner.setId(provider.getFhirUuidAsString()); - practitioner.addIdentifier( - this.createIdentifier(fhirConfig.getOeFhirSystem() + "/provider_uuid", provider.getFhirUuidAsString())); - practitioner.addName(new HumanName().setFamily(provider.getPerson().getLastName()) - .addGiven(provider.getPerson().getFirstName())); - practitioner.setTelecom(transformToTelecom(provider.getPerson())); - practitioner.setActive(provider.getActive()); - - return practitioner; - } - - private List transformToTelecom(Person person) { - List contactPoints = new ArrayList<>(); - contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.PHONE).setValue(person.getPrimaryPhone())); - contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.EMAIL).setValue(person.getEmail())); - contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.FAX).setValue(person.getFax())); - return contactPoints; - } - - private Task transformToTask(String sampleId) { - return this.transformToTask(sampleService.get(sampleId)); - } - - private Task transformToTask(Sample sample) { - Task task = new Task(); - Patient patient = sampleHumanService.getPatientForSample(sample); - List analysises = sampleService.getAnalysis(sample); - task.setId(sample.getFhirUuidAsString()); - Optional referredTask = getReferringTaskForSample(sample); - if (referredTask.isPresent()) { - task.addPartOf(this.createReferenceFor(referredTask.get())); - task.setIntent(TaskIntent.ORDER); - } else { - task.setIntent(TaskIntent.ORIGINALORDER); - } - if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Entered))) { - task.setStatus(TaskStatus.READY); - } else if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Started))) { - task.setStatus(TaskStatus.INPROGRESS); - } else if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Finished))) { - task.setStatus(TaskStatus.COMPLETED); - } else { - task.setStatus(TaskStatus.NULL); - } - task.setAuthoredOn(sample.getEnteredDate()); - task.setPriority(TaskPriority.ROUTINE); - task.addIdentifier( - this.createIdentifier(fhirConfig.getOeFhirSystem() + "/order_uuid", sample.getFhirUuidAsString())); - task.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/order_accessionNumber", - sample.getAccessionNumber())); - - for (Analysis analysis : analysises) { - task.addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); - if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Finished))) { - task.addOutput()// - .setType(new CodeableConcept().addCoding(new Coding().setCode("reference")))// - .setValue( - this.createReferenceFor(ResourceType.DiagnosticReport, analysis.getFhirUuidAsString())); - } - - } - task.setFor(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); - - return task; - } - - private DateType transformToDateElement(String strDate) throws ParseException { - boolean dayAmbiguous = false; - boolean monthAmbiguous = false; - // TODO look at this logic for detecting ambiguity - if (strDate.contains(DateUtil.AMBIGUOUS_DATE_SEGMENT)) { - strDate = strDate.replaceFirst(DateUtil.AMBIGUOUS_DATE_SEGMENT, "01"); - dayAmbiguous = true; - } - if (strDate.contains(DateUtil.AMBIGUOUS_DATE_SEGMENT)) { - strDate = strDate.replaceFirst(DateUtil.AMBIGUOUS_DATE_SEGMENT, "01"); - monthAmbiguous = true; - } - Date birthDate = new SimpleDateFormat("dd/MM/yyyy").parse(strDate); - DateType dateType = new DateType(); - if (monthAmbiguous) { - dateType.setValue(birthDate, TemporalPrecisionEnum.YEAR); - } else if (dayAmbiguous) { - dateType.setValue(birthDate, TemporalPrecisionEnum.MONTH); - } else { - dateType.setValue(birthDate, TemporalPrecisionEnum.DAY); - } - return dateType; - } - - @Override - public org.hl7.fhir.r4.model.Patient transformToFhirPatient(String patientId) { - return transformToFhirPatient(patientService.get(patientId)); - } - - private org.hl7.fhir.r4.model.Patient transformToFhirPatient(Patient patient) { - org.hl7.fhir.r4.model.Patient fhirPatient = new org.hl7.fhir.r4.model.Patient(); - String subjectNumber = patientService.getSubjectNumber(patient); - String nationalId = patientService.getNationalId(patient); - String guid = patientService.getGUID(patient); - String stNumber = patientService.getSTNumber(patient); - String uuid = patient.getFhirUuidAsString(); - - fhirPatient.setId(uuid); - fhirPatient.setIdentifier(createPatientIdentifiers(subjectNumber, nationalId, stNumber, guid, uuid)); - - HumanName humanName = new HumanName(); - List humanNameList = new ArrayList<>(); - humanName.setFamily(patient.getPerson().getLastName()); - humanName.addGiven(patient.getPerson().getFirstName()); - humanNameList.add(humanName); - fhirPatient.setName(humanNameList); - - try { - if (patient.getBirthDateForDisplay() != null) { - fhirPatient.setBirthDateElement(transformToDateElement(patient.getBirthDateForDisplay())); - } - } catch (ParseException e) { - LogEvent.logError("patient date unparseable", e); - } - if (GenericValidator.isBlankOrNull(patient.getGender())) { - fhirPatient.setGender(AdministrativeGender.UNKNOWN); - } else if (patient.getGender().equalsIgnoreCase("M")) { - fhirPatient.setGender(AdministrativeGender.MALE); - } else { - fhirPatient.setGender(AdministrativeGender.FEMALE); - } - fhirPatient.setTelecom(transformToTelecom(patient.getPerson())); - - fhirPatient.addAddress(transformToAddress(patient.getPerson())); - - return fhirPatient; - } - - private Address transformToAddress(Person person) { - @SuppressWarnings("unused") - PersonAddress village = null; - PersonAddress commune = null; - @SuppressWarnings("unused") - PersonAddress dept = null; - List personAddressList = personAddressService.getAddressPartsByPersonId(person.getId()); - - for (PersonAddress address : personAddressList) { - if (address.getAddressPartId().equals(ADDRESS_PART_COMMUNE_ID)) { - commune = address; - } else if (address.getAddressPartId().equals(ADDRESS_PART_VILLAGE_ID)) { - village = address; - } else if (address.getAddressPartId().equals(ADDRESS_PART_DEPT_ID)) { - dept = address; - } - } - Address address = new Address()// - .addLine(person.getStreetAddress())// - .setCity(person.getCity())// + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + + if (useReferral) { + referralSetService.createSaveReferralSetsSamplePatientEntry(referralItems, updateData); + } + } + + private void updateReferringTaskWithTaskInfo(Task referringTask, Task task) { + if (TaskStatus.COMPLETED.equals(task.getStatus())) { + referringTask.setStatus(TaskStatus.COMPLETED); + task.getOutput().forEach(outPut -> { + referringTask.addOutput(outPut); + }); + } + } + + private void updateReferringServiceRequestWithSampleInfo(Sample sample, ServiceRequest serviceRequest) { + serviceRequest.setRequisition( + this.createIdentifier(fhirConfig.getOeFhirSystem() + "/samp_labNo", sample.getAccessionNumber())); + } + + private Optional getReferringTaskForSample(Sample sample) { + List eOrders = electronicOrderService.getElectronicOrdersByExternalId(sample.getReferringId()); + if (eOrders.size() > 0 && ElectronicOrderType.FHIR.equals(eOrders.get(0).getType())) { + return fhirPersistanceService.getTaskBasedOnServiceRequest(sample.getReferringId()); + } + return Optional.empty(); + } + + private Optional getReferringServiceRequestForSample(Sample sample) { + List eOrders = electronicOrderService.getElectronicOrdersByExternalId(sample.getReferringId()); + if (eOrders.size() > 0 && ElectronicOrderType.FHIR.equals(eOrders.get(0).getType())) { + return fhirPersistanceService.getServiceRequestByReferingId(sample.getReferringId()); + } + return Optional.empty(); + } + + private Practitioner transformProviderToPractitioner(String providerId) { + return transformProviderToPractitioner(providerService.get(providerId)); + } + + @Override + public Practitioner transformProviderToPractitioner(Provider provider) { + Practitioner practitioner = new Practitioner(); + practitioner.setId(provider.getFhirUuidAsString()); + practitioner.addIdentifier( + this.createIdentifier(fhirConfig.getOeFhirSystem() + "/provider_uuid", provider.getFhirUuidAsString())); + practitioner.addName(new HumanName().setFamily(provider.getPerson().getLastName()) + .addGiven(provider.getPerson().getFirstName())); + practitioner.setTelecom(transformToTelecom(provider.getPerson())); + practitioner.setActive(provider.getActive()); + + return practitioner; + } + + private List transformToTelecom(Person person) { + List contactPoints = new ArrayList<>(); + contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.PHONE).setValue(person.getPrimaryPhone())); + contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.EMAIL).setValue(person.getEmail())); + contactPoints.add(new ContactPoint().setSystem(ContactPointSystem.FAX).setValue(person.getFax())); + return contactPoints; + } + + private Task transformToTask(String sampleId) { + return this.transformToTask(sampleService.get(sampleId)); + } + + private Task transformToTask(Sample sample) { + Task task = new Task(); + Patient patient = sampleHumanService.getPatientForSample(sample); + List analysises = sampleService.getAnalysis(sample); + task.setId(sample.getFhirUuidAsString()); + Optional referredTask = getReferringTaskForSample(sample); + if (referredTask.isPresent()) { + task.addPartOf(this.createReferenceFor(referredTask.get())); + task.setIntent(TaskIntent.ORDER); + } else { + task.setIntent(TaskIntent.ORIGINALORDER); + } + if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Entered))) { + task.setStatus(TaskStatus.READY); + } else if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Started))) { + task.setStatus(TaskStatus.INPROGRESS); + } else if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Finished))) { + task.setStatus(TaskStatus.COMPLETED); + } else { + task.setStatus(TaskStatus.NULL); + } + task.setAuthoredOn(sample.getEnteredDate()); + task.setPriority(TaskPriority.ROUTINE); + task.addIdentifier( + this.createIdentifier(fhirConfig.getOeFhirSystem() + "/order_uuid", sample.getFhirUuidAsString())); + task.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/order_accessionNumber", + sample.getAccessionNumber())); + + for (Analysis analysis : analysises) { + task.addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); + if (sample.getStatusId().equals(statusService.getStatusID(OrderStatus.Finished))) { + task.addOutput()// + .setType(new CodeableConcept().addCoding(new Coding().setCode("reference")))// + .setValue( + this.createReferenceFor(ResourceType.DiagnosticReport, analysis.getFhirUuidAsString())); + } + + } + task.setFor(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); + + return task; + } + + private DateType transformToDateElement(String strDate) throws ParseException { + boolean dayAmbiguous = false; + boolean monthAmbiguous = false; + // TODO look at this logic for detecting ambiguity + if (strDate.contains(DateUtil.AMBIGUOUS_DATE_SEGMENT)) { + strDate = strDate.replaceFirst(DateUtil.AMBIGUOUS_DATE_SEGMENT, "01"); + dayAmbiguous = true; + } + if (strDate.contains(DateUtil.AMBIGUOUS_DATE_SEGMENT)) { + strDate = strDate.replaceFirst(DateUtil.AMBIGUOUS_DATE_SEGMENT, "01"); + monthAmbiguous = true; + } + Date birthDate = new SimpleDateFormat("dd/MM/yyyy").parse(strDate); + DateType dateType = new DateType(); + if (monthAmbiguous) { + dateType.setValue(birthDate, TemporalPrecisionEnum.YEAR); + } else if (dayAmbiguous) { + dateType.setValue(birthDate, TemporalPrecisionEnum.MONTH); + } else { + dateType.setValue(birthDate, TemporalPrecisionEnum.DAY); + } + return dateType; + } + + @Override + public org.hl7.fhir.r4.model.Patient transformToFhirPatient(String patientId) { + return transformToFhirPatient(patientService.get(patientId)); + } + + private org.hl7.fhir.r4.model.Patient transformToFhirPatient(Patient patient) { + org.hl7.fhir.r4.model.Patient fhirPatient = new org.hl7.fhir.r4.model.Patient(); + String subjectNumber = patientService.getSubjectNumber(patient); + String nationalId = patientService.getNationalId(patient); + String guid = patientService.getGUID(patient); + String stNumber = patientService.getSTNumber(patient); + String uuid = patient.getFhirUuidAsString(); + + fhirPatient.setId(uuid); + fhirPatient.setIdentifier(createPatientIdentifiers(subjectNumber, nationalId, stNumber, guid, uuid)); + + HumanName humanName = new HumanName(); + List humanNameList = new ArrayList<>(); + humanName.setFamily(patient.getPerson().getLastName()); + humanName.addGiven(patient.getPerson().getFirstName()); + humanNameList.add(humanName); + fhirPatient.setName(humanNameList); + + try { + if (patient.getBirthDateForDisplay() != null) { + fhirPatient.setBirthDateElement(transformToDateElement(patient.getBirthDateForDisplay())); + } + } catch (ParseException e) { + LogEvent.logError("patient date unparseable", e); + } + if (GenericValidator.isBlankOrNull(patient.getGender())) { + fhirPatient.setGender(AdministrativeGender.UNKNOWN); + } else if (patient.getGender().equalsIgnoreCase("M")) { + fhirPatient.setGender(AdministrativeGender.MALE); + } else { + fhirPatient.setGender(AdministrativeGender.FEMALE); + } + fhirPatient.setTelecom(transformToTelecom(patient.getPerson())); + + fhirPatient.addAddress(transformToAddress(patient.getPerson())); + + return fhirPatient; + } + + private Address transformToAddress(Person person) { + @SuppressWarnings("unused") + PersonAddress village = null; + PersonAddress commune = null; + @SuppressWarnings("unused") + PersonAddress dept = null; + List personAddressList = personAddressService.getAddressPartsByPersonId(person.getId()); + + for (PersonAddress address : personAddressList) { + if (address.getAddressPartId().equals(ADDRESS_PART_COMMUNE_ID)) { + commune = address; + } else if (address.getAddressPartId().equals(ADDRESS_PART_VILLAGE_ID)) { + village = address; + } else if (address.getAddressPartId().equals(ADDRESS_PART_DEPT_ID)) { + dept = address; + } + } + Address address = new Address()// + .addLine(person.getStreetAddress())// + .setCity(person.getCity())// // .setDistrict(value) - .setState(person.getState())// + .setState(person.getState())// // .setPostalCode(value) - .setCountry(person.getCountry())// - ; - if (commune != null) { - address.addLine("commune: " + commune.getValue()); - } - return address; - } - - private List createPatientIdentifiers(String subjectNumber, String nationalId, String stNumber, - String guid, String fhirUuid) { - List identifierList = new ArrayList<>(); - if (!GenericValidator.isBlankOrNull(subjectNumber)) { - identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_subjectNumber", subjectNumber)); - } - if (!GenericValidator.isBlankOrNull(nationalId)) { - identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_nationalId", nationalId)); - } - if (!GenericValidator.isBlankOrNull(stNumber)) { - identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_stNumber", stNumber)); - } - if (!GenericValidator.isBlankOrNull(guid)) { - identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_guid", guid)); - } - if (!GenericValidator.isBlankOrNull(fhirUuid)) { - identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_uuid", fhirUuid)); - } - return identifierList; - } - - private List transformToServiceRequests(SamplePatientUpdateData updateData, - SampleTestCollection sampleTestCollection) { - List serviceRequestsForSampleItem = new ArrayList<>(); - - for (Analysis analysis : sampleTestCollection.analysises) { - serviceRequestsForSampleItem.add(this.transformToServiceRequest(analysis.getId())); - } - return serviceRequestsForSampleItem; - } - - private ServiceRequest transformToServiceRequest(String anlaysisId) { - return transformToServiceRequest(analysisService.get(anlaysisId)); - } - - private ServiceRequest transformToServiceRequest(Analysis analysis) { - Sample sample = analysis.getSampleItem().getSample(); - Patient patient = sampleHumanService.getPatientForSample(sample); - Provider provider = sampleHumanService.getProviderForSample(sample); - - Organization organization = sampleService.getOrganizationRequester(sample, - TableIdService.getInstance().REFERRING_ORG_TYPE_ID); - Organization organizationDepartment = sampleService.getOrganizationRequester(sample, - TableIdService.getInstance().REFERRING_ORG_DEPARTMENT_TYPE_ID); - - Test test = analysis.getTest(); - ServiceRequest serviceRequest = new ServiceRequest(); - serviceRequest.setId(analysis.getFhirUuidAsString()); - serviceRequest.addIdentifier( - this.createIdentifier(fhirConfig.getOeFhirSystem() + "/analysis_uuid", analysis.getFhirUuidAsString())); - serviceRequest.setRequisition(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/samp_labNo", - analysis.getSampleItem().getSample().getAccessionNumber())); - if (organization != null) { - serviceRequest.addLocationReference( - this.createReferenceFor(ResourceType.Location, organization.getFhirUuidAsString())); - } - if (organizationDepartment != null) { - serviceRequest.addLocationReference( - this.createReferenceFor(ResourceType.Location, organizationDepartment.getFhirUuidAsString())); - } - - List eOrders = electronicOrderService.getElectronicOrdersByExternalId(sample.getReferringId()); - - if (eOrders.size() <= 0) { - serviceRequest.setIntent(ServiceRequestIntent.ORIGINALORDER); - } else if (ElectronicOrderType.FHIR.equals(eOrders.get(eOrders.size() - 1).getType())) { - serviceRequest.addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, sample.getReferringId())); - serviceRequest.setIntent(ServiceRequestIntent.ORDER); - } else if (ElectronicOrderType.HL7_V2.equals(eOrders.get(eOrders.size() - 1).getType())) { - serviceRequest.setIntent(ServiceRequestIntent.ORDER); - } - - if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.NotStarted))) { - serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalAcceptance))) { - serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalRejected))) { - serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Finalized))) { - serviceRequest.setStatus(ServiceRequestStatus.COMPLETED); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Canceled))) { - serviceRequest.setStatus(ServiceRequestStatus.REVOKED); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.SampleRejected))) { - serviceRequest.setStatus(ServiceRequestStatus.ENTEREDINERROR); - } else { - serviceRequest.setStatus(ServiceRequestStatus.UNKNOWN); - } - ObservationHistory program = observationHistoryService.getObservationHistoriesBySampleIdAndType(sample.getId(), - observationHistoryService.getObservationTypeIdForType(ObservationType.PROGRAM)); - if (program != null && !GenericValidator.isBlankOrNull(program.getValue())) { - serviceRequest.addCategory(transformSampleProgramToCodeableConcept(program)); - } - serviceRequest.setPriority(ServiceRequestPriority.ROUTINE); - serviceRequest.setCode(transformTestToCodeableConcept(test.getId())); - serviceRequest.setAuthoredOn(new Date()); - for (Note note : noteService.getNotes(analysis)) { - serviceRequest.addNote(transformNoteToAnnotation(note)); - } - // TODO performer type? - - serviceRequest.addSpecimen( - this.createReferenceFor(ResourceType.Specimen, analysis.getSampleItem().getFhirUuidAsString())); - serviceRequest.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); - if (provider != null && provider.getFhirUuid() != null) { - serviceRequest - .setRequester(this.createReferenceFor(ResourceType.Practitioner, provider.getFhirUuidAsString())); - } - - return serviceRequest; - } - - private CodeableConcept transformSampleProgramToCodeableConcept(ObservationHistory program) { - CodeableConcept codeableConcept = new CodeableConcept(); - String programDisplay = ""; - String programCode = ""; - if ("D".equals(program.getValueType())) { - Dictionary dictionary = dictionaryService.get(program.getValue()); - if (dictionary != null) { - programCode = dictionary.getDictEntry(); - programDisplay = dictionary.getDictEntry(); - } - } else { - programCode = program.getValue(); - programDisplay = program.getValue(); - } - codeableConcept - .addCoding(new Coding(fhirConfig.getOeFhirSystem() + "/sample_program", programCode, programDisplay)); - return codeableConcept; - } - - private CodeableConcept transformTestToCodeableConcept(String testId) { - return transformTestToCodeableConcept(testService.get(testId)); - } - - private CodeableConcept transformTestToCodeableConcept(Test test) { - CodeableConcept codeableConcept = new CodeableConcept(); - codeableConcept - .addCoding(new Coding("http://loinc.org", test.getLoinc(), test.getLocalizedTestName().getEnglish())); - return codeableConcept; - } - - private Specimen transformToFhirSpecimen(SampleTestCollection sampleTest) { - Specimen specimen = this.transformToSpecimen(sampleTest.item.getId()); - if (sampleTest.initialSampleConditionIdList != null) { - for (ObservationHistory initialSampleCondition : sampleTest.initialSampleConditionIdList) { - specimen.addCondition(transformSampleConditionToCodeableConcept(initialSampleCondition)); - } - } - - return specimen; - } - - private Specimen transformToSpecimen(String sampleItemId) { - return transformToSpecimen(sampleItemService.get(sampleItemId)); - } - - private Specimen transformToSpecimen(SampleItem sampleItem) { - Specimen specimen = new Specimen(); - Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); - specimen.setId(sampleItem.getFhirUuidAsString()); - specimen.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/sampleItem_uuid", - sampleItem.getFhirUuidAsString())); - specimen.setAccessionIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/sampleItem_labNo", - sampleItem.getSample().getAccessionNumber() + "-" + sampleItem.getSortOrder())); - specimen.setStatus(SpecimenStatus.AVAILABLE); - specimen.setType(transformTypeOfSampleToCodeableConcept(sampleItem.getTypeOfSample())); - specimen.setReceivedTime(new Date()); - specimen.setCollection(transformToCollection(sampleItem.getCollectionDate(), sampleItem.getCollector())); - - for (Analysis analysis : analysisService.getAnalysesBySampleItem(sampleItem)) { - specimen.addRequest(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); - } - specimen.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); - - return specimen; - } - - @SuppressWarnings("unused") - private CodeableConcept transformSampleConditionToCodeableConcept(String sampleConditionId) { - return transformSampleConditionToCodeableConcept(observationHistoryService.get(sampleConditionId)); - } - - private CodeableConcept transformSampleConditionToCodeableConcept(ObservationHistory initialSampleCondition) { - String observationValue; - String observationDisplay; - if (ValueType.DICTIONARY.getCode().equals(initialSampleCondition.getValueType())) { - observationValue = dictionaryService.get(initialSampleCondition.getValue()).getDictEntry(); - observationDisplay = dictionaryService.get(initialSampleCondition.getValue()).getDictEntryDisplayValue(); - } else if (ValueType.KEY.getCode().equals(initialSampleCondition.getValueType())) { - observationValue = localizationService.get(initialSampleCondition.getValue()).getEnglish(); - observationDisplay = ""; - } else { - observationValue = initialSampleCondition.getValue(); - observationDisplay = ""; - } - - CodeableConcept condition = new CodeableConcept(); - condition.addCoding( - new Coding(fhirConfig.getOeFhirSystem() + "/sample_condition", observationValue, observationDisplay)); - return condition; - } + .setCountry(person.getCountry())// + ; + if (commune != null) { + address.addLine("commune: " + commune.getValue()); + } + return address; + } + + private List createPatientIdentifiers(String subjectNumber, String nationalId, String stNumber, + String guid, String fhirUuid) { + List identifierList = new ArrayList<>(); + if (!GenericValidator.isBlankOrNull(subjectNumber)) { + identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_subjectNumber", subjectNumber)); + } + if (!GenericValidator.isBlankOrNull(nationalId)) { + identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_nationalId", nationalId)); + } + if (!GenericValidator.isBlankOrNull(stNumber)) { + identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_stNumber", stNumber)); + } + if (!GenericValidator.isBlankOrNull(guid)) { + identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_guid", guid)); + } + if (!GenericValidator.isBlankOrNull(fhirUuid)) { + identifierList.add(createIdentifier(fhirConfig.getOeFhirSystem() + "/pat_uuid", fhirUuid)); + } + return identifierList; + } + + private List transformToServiceRequests(SamplePatientUpdateData updateData, + SampleTestCollection sampleTestCollection) { + List serviceRequestsForSampleItem = new ArrayList<>(); + + for (Analysis analysis : sampleTestCollection.analysises) { + serviceRequestsForSampleItem.add(this.transformToServiceRequest(analysis.getId())); + } + return serviceRequestsForSampleItem; + } + + private ServiceRequest transformToServiceRequest(String anlaysisId) { + return transformToServiceRequest(analysisService.get(anlaysisId)); + } + + private ServiceRequest transformToServiceRequest(Analysis analysis) { + Sample sample = analysis.getSampleItem().getSample(); + Patient patient = sampleHumanService.getPatientForSample(sample); + Provider provider = sampleHumanService.getProviderForSample(sample); + + Organization organization = sampleService.getOrganizationRequester(sample, + TableIdService.getInstance().REFERRING_ORG_TYPE_ID); + Organization organizationDepartment = sampleService.getOrganizationRequester(sample, + TableIdService.getInstance().REFERRING_ORG_DEPARTMENT_TYPE_ID); + + Test test = analysis.getTest(); + ServiceRequest serviceRequest = new ServiceRequest(); + serviceRequest.setId(analysis.getFhirUuidAsString()); + serviceRequest.addIdentifier( + this.createIdentifier(fhirConfig.getOeFhirSystem() + "/analysis_uuid", analysis.getFhirUuidAsString())); + serviceRequest.setRequisition(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/samp_labNo", + analysis.getSampleItem().getSample().getAccessionNumber())); + if (organization != null) { + serviceRequest.addLocationReference( + this.createReferenceFor(ResourceType.Location, organization.getFhirUuidAsString())); + } + if (organizationDepartment != null) { + serviceRequest.addLocationReference( + this.createReferenceFor(ResourceType.Location, organizationDepartment.getFhirUuidAsString())); + } + + List eOrders = electronicOrderService.getElectronicOrdersByExternalId(sample.getReferringId()); + + if (eOrders.size() <= 0) { + serviceRequest.setIntent(ServiceRequestIntent.ORIGINALORDER); + } else if (ElectronicOrderType.FHIR.equals(eOrders.get(eOrders.size() - 1).getType())) { + serviceRequest.addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, sample.getReferringId())); + serviceRequest.setIntent(ServiceRequestIntent.ORDER); + } else if (ElectronicOrderType.HL7_V2.equals(eOrders.get(eOrders.size() - 1).getType())) { + serviceRequest.setIntent(ServiceRequestIntent.ORDER); + } + + if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.NotStarted))) { + serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalAcceptance))) { + serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalRejected))) { + serviceRequest.setStatus(ServiceRequestStatus.ACTIVE); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Finalized))) { + serviceRequest.setStatus(ServiceRequestStatus.COMPLETED); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Canceled))) { + serviceRequest.setStatus(ServiceRequestStatus.REVOKED); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.SampleRejected))) { + serviceRequest.setStatus(ServiceRequestStatus.ENTEREDINERROR); + } else { + serviceRequest.setStatus(ServiceRequestStatus.UNKNOWN); + } + ObservationHistory program = observationHistoryService.getObservationHistoriesBySampleIdAndType(sample.getId(), + observationHistoryService.getObservationTypeIdForType(ObservationType.PROGRAM)); + if (program != null && !GenericValidator.isBlankOrNull(program.getValue())) { + serviceRequest.addCategory(transformSampleProgramToCodeableConcept(program)); + } + serviceRequest.setPriority(ServiceRequestPriority.ROUTINE); + serviceRequest.setCode(transformTestToCodeableConcept(test.getId())); + serviceRequest.setAuthoredOn(new Date()); + for (Note note : noteService.getNotes(analysis)) { + serviceRequest.addNote(transformNoteToAnnotation(note)); + } + // TODO performer type? + + serviceRequest.addSpecimen( + this.createReferenceFor(ResourceType.Specimen, analysis.getSampleItem().getFhirUuidAsString())); + serviceRequest.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); + if (provider != null && provider.getFhirUuid() != null) { + serviceRequest + .setRequester(this.createReferenceFor(ResourceType.Practitioner, provider.getFhirUuidAsString())); + } + + return serviceRequest; + } + + private CodeableConcept transformSampleProgramToCodeableConcept(ObservationHistory program) { + CodeableConcept codeableConcept = new CodeableConcept(); + String programDisplay = ""; + String programCode = ""; + if ("D".equals(program.getValueType())) { + Dictionary dictionary = dictionaryService.get(program.getValue()); + if (dictionary != null) { + programCode = dictionary.getDictEntry(); + programDisplay = dictionary.getDictEntry(); + } + } else { + programCode = program.getValue(); + programDisplay = program.getValue(); + } + codeableConcept + .addCoding(new Coding(fhirConfig.getOeFhirSystem() + "/sample_program", programCode, programDisplay)); + return codeableConcept; + } + + private CodeableConcept transformTestToCodeableConcept(String testId) { + return transformTestToCodeableConcept(testService.get(testId)); + } + + private CodeableConcept transformTestToCodeableConcept(Test test) { + CodeableConcept codeableConcept = new CodeableConcept(); + codeableConcept + .addCoding(new Coding("http://loinc.org", test.getLoinc(), test.getLocalizedTestName().getEnglish())); + return codeableConcept; + } + + private Specimen transformToFhirSpecimen(SampleTestCollection sampleTest) { + Specimen specimen = this.transformToSpecimen(sampleTest.item.getId()); + if (sampleTest.initialSampleConditionIdList != null) { + for (ObservationHistory initialSampleCondition : sampleTest.initialSampleConditionIdList) { + specimen.addCondition(transformSampleConditionToCodeableConcept(initialSampleCondition)); + } + } + + return specimen; + } + + private Specimen transformToSpecimen(String sampleItemId) { + return transformToSpecimen(sampleItemService.get(sampleItemId)); + } + + private Specimen transformToSpecimen(SampleItem sampleItem) { + Specimen specimen = new Specimen(); + Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); + specimen.setId(sampleItem.getFhirUuidAsString()); + specimen.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/sampleItem_uuid", + sampleItem.getFhirUuidAsString())); + specimen.setAccessionIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/sampleItem_labNo", + sampleItem.getSample().getAccessionNumber() + "-" + sampleItem.getSortOrder())); + specimen.setStatus(SpecimenStatus.AVAILABLE); + specimen.setType(transformTypeOfSampleToCodeableConcept(sampleItem.getTypeOfSample())); + specimen.setReceivedTime(new Date()); + specimen.setCollection(transformToCollection(sampleItem.getCollectionDate(), sampleItem.getCollector())); + + for (Analysis analysis : analysisService.getAnalysesBySampleItem(sampleItem)) { + specimen.addRequest(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); + } + specimen.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); + + return specimen; + } + + @SuppressWarnings("unused") + private CodeableConcept transformSampleConditionToCodeableConcept(String sampleConditionId) { + return transformSampleConditionToCodeableConcept(observationHistoryService.get(sampleConditionId)); + } + + private CodeableConcept transformSampleConditionToCodeableConcept(ObservationHistory initialSampleCondition) { + String observationValue; + String observationDisplay; + if (ValueType.DICTIONARY.getCode().equals(initialSampleCondition.getValueType())) { + observationValue = dictionaryService.get(initialSampleCondition.getValue()).getDictEntry(); + observationDisplay = dictionaryService.get(initialSampleCondition.getValue()).getDictEntryDisplayValue(); + } else if (ValueType.KEY.getCode().equals(initialSampleCondition.getValueType())) { + observationValue = localizationService.get(initialSampleCondition.getValue()).getEnglish(); + observationDisplay = ""; + } else { + observationValue = initialSampleCondition.getValue(); + observationDisplay = ""; + } + + CodeableConcept condition = new CodeableConcept(); + condition.addCoding( + new Coding(fhirConfig.getOeFhirSystem() + "/sample_condition", observationValue, observationDisplay)); + return condition; + } private SpecimenCollectionComponent transformToCollection(Timestamp collectionDate, String collector) { SpecimenCollectionComponent specimenCollectionComponent = new SpecimenCollectionComponent(); specimenCollectionComponent.setCollected(new DateTimeType(collectionDate)); // TODO create a collector from this info -// specimenCollectionComponent.setCollector(collector); + // specimenCollectionComponent.setCollector(collector); return specimenCollectionComponent; } - private CodeableConcept transformTypeOfSampleToCodeableConcept(String typeOfSampleId) { - return transformTypeOfSampleToCodeableConcept(typeOfSampleService.get(typeOfSampleId)); - } - - private CodeableConcept transformTypeOfSampleToCodeableConcept(TypeOfSample typeOfSample) { - CodeableConcept codeableConcept = new CodeableConcept(); - codeableConcept.addCoding(new Coding(fhirConfig.getOeFhirSystem() + "/sampleType", - typeOfSample.getLocalAbbreviation(), typeOfSample.getLocalizedName())); - return codeableConcept; - } - - @Override - @Async - @Transactional(readOnly = true) - public void transformPersistResultsEntryFhirObjects(ResultsUpdateDataSet actionDataSet) - throws FhirLocalPersistingException { - CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); - FhirOperations fhirOperations = new FhirOperations(); - for (ResultSet resultSet : actionDataSet.getNewResults()) { - Observation observation = transformResultToObservation(resultSet.result.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, observation); - } - for (ResultSet resultSet : actionDataSet.getModifiedResults()) { - Observation observation = this.transformResultToObservation(resultSet.result.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, observation); - } - - for (Analysis analysis : actionDataSet.getModifiedAnalysis()) { - ServiceRequest serviceRequest = this.transformToServiceRequest(analysis.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); - if (statusService.matches(analysis.getStatusId(), AnalysisStatus.Finalized)) { - DiagnosticReport diagnosticReport = this.transformResultToDiagnosticReport(analysis.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); - } - } - - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - - } - - @Async - @Override - @Transactional(readOnly = true) - public void transformPersistResultValidationFhirObjects(List deletableList, - List analysisUpdateList, ArrayList resultUpdateList, List resultItemList, - ArrayList sampleUpdateList, ArrayList noteUpdateList) throws FhirLocalPersistingException { - CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); - FhirOperations fhirOperations = new FhirOperations(); - - for (Result result : deletableList) { - Observation observation = transformResultToObservation(result.getId()); - observation.setStatus(ObservationStatus.CANCELLED); - this.addToOperations(fhirOperations, tempIdGenerator, observation); - } - - for (Result result : resultUpdateList) { - Observation observation = this.transformResultToObservation(result.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, observation); - } - - for (Analysis analysis : analysisUpdateList) { - ServiceRequest serviceRequest = this.transformToServiceRequest(analysis.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); - if (statusService.matches(analysis.getStatusId(), AnalysisStatus.Finalized)) { - DiagnosticReport diagnosticReport = this.transformResultToDiagnosticReport(analysis.getId()); - this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); - } - } - - Map referingTaskMap = new HashMap<>(); - for (Sample sample : sampleUpdateList) { - Task task = this.transformToTask(sample.getId()); - Optional referringTask = getReferringTaskForSample(sample); - if (referringTask.isPresent()) { - if (referingTaskMap.containsKey(referringTask.get().getIdElement().getIdPart())) { - Task existingReferingTask = referingTaskMap.get(referringTask.get().getIdElement().getIdPart()); - updateReferringTaskWithTaskInfo(existingReferingTask, task); - referingTaskMap.put(existingReferingTask.getIdElement().getIdPart(), existingReferingTask); - this.addToOperations(fhirOperations, tempIdGenerator, existingReferingTask); - } else { - updateReferringTaskWithTaskInfo(referringTask.get(), task); - referingTaskMap.put(referringTask.get().getIdElement().getIdPart(), referringTask.get()); - this.addToOperations(fhirOperations, tempIdGenerator, referringTask.get()); - } - } - this.addToOperations(fhirOperations, tempIdGenerator, task); - } - - Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); - } - - private void addToOperations(FhirOperations fhirOperations, TempIdGenerator tempIdGenerator, Resource resource) { - if (this.setTempIdIfMissing(resource, tempIdGenerator)) { - if (fhirOperations.createResources.containsKey(resource.getIdElement().getIdPart())) { - LogEvent.logError("", "", - "collision on id: " + resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); - } - fhirOperations.createResources.put(resource.getIdElement().getIdPart(), resource); - } else { - if (fhirOperations.updateResources.containsKey(resource.getIdElement().getIdPart())) { - LogEvent.logError("", "", - "collision on id: " + resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); - } - fhirOperations.updateResources.put(resource.getIdElement().getIdPart(), resource); - } - } - - private DiagnosticReport transformResultToDiagnosticReport(String analysisId) { - return transformResultToDiagnosticReport(analysisService.get(analysisId)); - } - - private DiagnosticReport transformResultToDiagnosticReport(Analysis analysis) { - List allResults = resultService.getResultsByAnalysis(analysis); - SampleItem sampleItem = analysis.getSampleItem(); - Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); - - DiagnosticReport diagnosticReport = genNewDiagnosticReport(analysis); - Test test = analysis.getTest(); - - if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Finalized))) { - diagnosticReport.setStatus(DiagnosticReportStatus.FINAL); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalAcceptance))) { - diagnosticReport.setStatus(DiagnosticReportStatus.PRELIMINARY); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalRejected))) { - diagnosticReport.setStatus(DiagnosticReportStatus.PARTIAL); - } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.NotStarted))) { - diagnosticReport.setStatus(DiagnosticReportStatus.REGISTERED); - } else { - diagnosticReport.setStatus(DiagnosticReportStatus.UNKNOWN); - } - - diagnosticReport - .addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); - diagnosticReport.addSpecimen(this.createReferenceFor(ResourceType.Specimen, sampleItem.getFhirUuidAsString())); - diagnosticReport.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); - for (Result curResult : allResults) { - diagnosticReport - .addResult(this.createReferenceFor(ResourceType.Observation, curResult.getFhirUuidAsString())); - } - diagnosticReport.setCode(transformTestToCodeableConcept(test.getId())); - - return diagnosticReport; - } - - private DiagnosticReport genNewDiagnosticReport(Analysis analysis) { - DiagnosticReport diagnosticReport = new DiagnosticReport(); - diagnosticReport.setId(analysis.getFhirUuidAsString()); - diagnosticReport.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/analysisResult_uuid", - analysis.getFhirUuidAsString())); - return diagnosticReport; - } - - private Observation transformResultToObservation(String resultId) { - return transformResultToObservation(resultService.get(resultId)); - } - - private Observation transformResultToObservation(Result result) { - Analysis analysis = result.getAnalysis(); - Test test = analysis.getTest(); - SampleItem sampleItem = analysis.getSampleItem(); - Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); - Observation observation = new Observation(); - - observation.setId(result.getFhirUuidAsString()); - observation.addIdentifier( - this.createIdentifier(fhirConfig.getOeFhirSystem() + "/result_uuid", result.getFhirUuidAsString())); + private CodeableConcept transformTypeOfSampleToCodeableConcept(String typeOfSampleId) { + return transformTypeOfSampleToCodeableConcept(typeOfSampleService.get(typeOfSampleId)); + } + + private CodeableConcept transformTypeOfSampleToCodeableConcept(TypeOfSample typeOfSample) { + CodeableConcept codeableConcept = new CodeableConcept(); + codeableConcept.addCoding(new Coding(fhirConfig.getOeFhirSystem() + "/sampleType", + typeOfSample.getLocalAbbreviation(), typeOfSample.getLocalizedName())); + return codeableConcept; + } + + @Override + @Async + @Transactional(readOnly = true) + public void transformPersistResultsEntryFhirObjects(ResultsUpdateDataSet actionDataSet) + throws FhirLocalPersistingException { + CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); + FhirOperations fhirOperations = new FhirOperations(); + for (ResultSet resultSet : actionDataSet.getNewResults()) { + Observation observation = transformResultToObservation(resultSet.result.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, observation); + } + for (ResultSet resultSet : actionDataSet.getModifiedResults()) { + Observation observation = this.transformResultToObservation(resultSet.result.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, observation); + } + + for (Analysis analysis : actionDataSet.getModifiedAnalysis()) { + ServiceRequest serviceRequest = this.transformToServiceRequest(analysis.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); + if (statusService.matches(analysis.getStatusId(), AnalysisStatus.Finalized)) { + DiagnosticReport diagnosticReport = this.transformResultToDiagnosticReport(analysis.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); + } + } + + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + + } + + @Async + @Override + @Transactional(readOnly = true) + public void transformPersistResultValidationFhirObjects(List deletableList, + List analysisUpdateList, ArrayList resultUpdateList, List resultItemList, + ArrayList sampleUpdateList, ArrayList noteUpdateList) throws FhirLocalPersistingException { + CountingTempIdGenerator tempIdGenerator = new CountingTempIdGenerator(); + FhirOperations fhirOperations = new FhirOperations(); + + for (Result result : deletableList) { + Observation observation = transformResultToObservation(result.getId()); + observation.setStatus(ObservationStatus.CANCELLED); + this.addToOperations(fhirOperations, tempIdGenerator, observation); + } + + for (Result result : resultUpdateList) { + Observation observation = this.transformResultToObservation(result.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, observation); + } + + for (Analysis analysis : analysisUpdateList) { + ServiceRequest serviceRequest = this.transformToServiceRequest(analysis.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, serviceRequest); + if (statusService.matches(analysis.getStatusId(), AnalysisStatus.Finalized)) { + DiagnosticReport diagnosticReport = this.transformResultToDiagnosticReport(analysis.getId()); + this.addToOperations(fhirOperations, tempIdGenerator, diagnosticReport); + } + } + + Map referingTaskMap = new HashMap<>(); + for (Sample sample : sampleUpdateList) { + Task task = this.transformToTask(sample.getId()); + Optional referringTask = getReferringTaskForSample(sample); + if (referringTask.isPresent()) { + if (referingTaskMap.containsKey(referringTask.get().getIdElement().getIdPart())) { + Task existingReferingTask = referingTaskMap.get(referringTask.get().getIdElement().getIdPart()); + updateReferringTaskWithTaskInfo(existingReferingTask, task); + referingTaskMap.put(existingReferingTask.getIdElement().getIdPart(), existingReferingTask); + this.addToOperations(fhirOperations, tempIdGenerator, existingReferingTask); + } else { + updateReferringTaskWithTaskInfo(referringTask.get(), task); + referingTaskMap.put(referringTask.get().getIdElement().getIdPart(), referringTask.get()); + this.addToOperations(fhirOperations, tempIdGenerator, referringTask.get()); + } + } + this.addToOperations(fhirOperations, tempIdGenerator, task); + } + + Bundle responseBundle = fhirPersistanceService.createUpdateFhirResourcesInFhirStore(fhirOperations); + } + + private void addToOperations(FhirOperations fhirOperations, TempIdGenerator tempIdGenerator, Resource resource) { + if (this.setTempIdIfMissing(resource, tempIdGenerator)) { + if (fhirOperations.createResources.containsKey(resource.getIdElement().getIdPart())) { + LogEvent.logError("", "", + "collision on id: " + resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); + } + fhirOperations.createResources.put(resource.getIdElement().getIdPart(), resource); + } else { + if (fhirOperations.updateResources.containsKey(resource.getIdElement().getIdPart())) { + LogEvent.logError("", "", + "collision on id: " + resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); + } + fhirOperations.updateResources.put(resource.getIdElement().getIdPart(), resource); + } + } + + private DiagnosticReport transformResultToDiagnosticReport(String analysisId) { + return transformResultToDiagnosticReport(analysisService.get(analysisId)); + } + + private DiagnosticReport transformResultToDiagnosticReport(Analysis analysis) { + List allResults = resultService.getResultsByAnalysis(analysis); + SampleItem sampleItem = analysis.getSampleItem(); + Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); + + DiagnosticReport diagnosticReport = genNewDiagnosticReport(analysis); + Test test = analysis.getTest(); + + if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.Finalized))) { + diagnosticReport.setStatus(DiagnosticReportStatus.FINAL); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalAcceptance))) { + diagnosticReport.setStatus(DiagnosticReportStatus.PRELIMINARY); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.TechnicalRejected))) { + diagnosticReport.setStatus(DiagnosticReportStatus.PARTIAL); + } else if (analysis.getStatusId().equals(statusService.getStatusID(AnalysisStatus.NotStarted))) { + diagnosticReport.setStatus(DiagnosticReportStatus.REGISTERED); + } else { + diagnosticReport.setStatus(DiagnosticReportStatus.UNKNOWN); + } + + diagnosticReport + .addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); + diagnosticReport.addSpecimen(this.createReferenceFor(ResourceType.Specimen, sampleItem.getFhirUuidAsString())); + diagnosticReport.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); + for (Result curResult : allResults) { + diagnosticReport + .addResult(this.createReferenceFor(ResourceType.Observation, curResult.getFhirUuidAsString())); + } + diagnosticReport.setCode(transformTestToCodeableConcept(test.getId())); + + return diagnosticReport; + } + + private DiagnosticReport genNewDiagnosticReport(Analysis analysis) { + DiagnosticReport diagnosticReport = new DiagnosticReport(); + diagnosticReport.setId(analysis.getFhirUuidAsString()); + diagnosticReport.addIdentifier(this.createIdentifier(fhirConfig.getOeFhirSystem() + "/analysisResult_uuid", + analysis.getFhirUuidAsString())); + return diagnosticReport; + } + + private Observation transformResultToObservation(String resultId) { + return transformResultToObservation(resultService.get(resultId)); + } + + private Observation transformResultToObservation(Result result) { + Analysis analysis = result.getAnalysis(); + Test test = analysis.getTest(); + SampleItem sampleItem = analysis.getSampleItem(); + Patient patient = sampleHumanService.getPatientForSample(sampleItem.getSample()); + Observation observation = new Observation(); + + observation.setId(result.getFhirUuidAsString()); + observation.addIdentifier( + this.createIdentifier(fhirConfig.getOeFhirSystem() + "/result_uuid", result.getFhirUuidAsString())); // TODO make sure these align with each other. // we may need to add detection for when result is changed and add those status @@ -1005,7 +1029,14 @@ private Observation transformResultToObservation(Result result) { } if (!GenericValidator.isBlankOrNull(result.getValue())) { - if (TypeOfTestResultServiceImpl.ResultType.isMultiSelectVariant(result.getResultType()) + // in case of Viral load test + if (result.getAnalysis().getTest().getName().equalsIgnoreCase("Viral Load")) { + Quantity quantity = new Quantity(); + long finalResult = result.getVLValueAsNumber(); + quantity.setValue(finalResult); + quantity.setUnit(resultService.getUOM(result)); + observation.setValue(quantity); + } else if (TypeOfTestResultServiceImpl.ResultType.isMultiSelectVariant(result.getResultType()) && !"0".equals(result.getValue())) { Dictionary dictionary = dictionaryService.getDataForId(result.getValue()); observation.setValue(new CodeableConcept( @@ -1032,268 +1063,271 @@ private Observation transformResultToObservation(Result result) { observation.addBasedOn(this.createReferenceFor(ResourceType.ServiceRequest, analysis.getFhirUuidAsString())); observation.setSpecimen(this.createReferenceFor(ResourceType.Specimen, sampleItem.getFhirUuidAsString())); observation.setSubject(this.createReferenceFor(ResourceType.Patient, patient.getFhirUuidAsString())); -// observation.setIssued(result.getOriginalLastupdated()); - observation.setIssued(result.getLastupdated()); - observation.setEffective(new DateTimeType(result.getLastupdated())); -// observation.setIssued(new Date()); + // observation.setIssued(result.getOriginalLastupdated()); + observation.setIssued(analysis.getReleasedDate());//update to get Released Date instead of commpleted date observation.setEffective(new DateTimeType(result.getLastupdated())); + // observation.setIssued(new Date()); return observation; } - @Override - public Practitioner transformNameToPractitioner(String practitionerName) { - Practitioner practitioner = new Practitioner(); - HumanName name = practitioner.addName(); - - if (practitionerName.contains(",")) { - String[] names = practitionerName.split(",", 2); - name.setFamily(names[0]); - for (int i = 1; i < names.length; ++i) { - name.addGiven(names[i]); - } - } else { - String[] names = practitionerName.split(" "); - if (names.length >= 1) { - name.setFamily(names[names.length - 1]); - for (int i = 0; i < names.length - 1; ++i) { - name.addGiven(names[i]); - } - } - } - return practitioner; - } - - @Override - @Transactional(readOnly = true) - public org.hl7.fhir.r4.model.Organization transformToFhirOrganization(Organization organization) { - org.hl7.fhir.r4.model.Organization fhirOrganization = new org.hl7.fhir.r4.model.Organization(); - fhirOrganization - .setId(organization.getFhirUuid() == null ? organization.getId() : organization.getFhirUuidAsString()); - fhirOrganization.setName(organization.getOrganizationName()); - fhirOrganization.setActive(organization.getIsActive() == IActionConstants.YES ? true : false); - this.setFhirOrganizationIdentifiers(fhirOrganization, organization); - this.setFhirAddressInfo(fhirOrganization, organization); - this.setFhirOrganizationTypes(fhirOrganization, organization); - return fhirOrganization; - } - - @Override - @Transactional(readOnly = true) - public Organization transformToOrganization(org.hl7.fhir.r4.model.Organization fhirOrganization) { - Organization organization = new Organization(); - organization.setOrganizationName(fhirOrganization.getName()); - organization.setIsActive(Boolean.FALSE == fhirOrganization.getActiveElement().getValue() ? IActionConstants.NO - : IActionConstants.YES); - - setOeOrganizationIdentifiers(organization, fhirOrganization); - setOeOrganizationAddressInfo(organization, fhirOrganization); - setOeOrganizationTypes(organization, fhirOrganization); - - organization.setMlsLabFlag(IActionConstants.NO); - organization.setMlsSentinelLabFlag(IActionConstants.NO); - - return organization; - } - - private void setOeOrganizationIdentifiers(Organization organization, - org.hl7.fhir.r4.model.Organization fhirOrganization) { - organization.setFhirUuid(UUID.fromString(fhirOrganization.getIdElement().getIdPart())); - for (Identifier identifier : fhirOrganization.getIdentifier()) { - if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_cliaNum")) { - organization.setCliaNum(identifier.getValue()); - } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_shortName")) { - organization.setShortName(identifier.getValue()); - } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_code")) { - organization.setCode(identifier.getValue()); - } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_uuid")) { - organization.setFhirUuid(UUID.fromString(identifier.getValue())); - } - } - } - - private void setFhirOrganizationIdentifiers(org.hl7.fhir.r4.model.Organization fhirOrganization, - Organization organization) { - if (!GenericValidator.isBlankOrNull(organization.getCliaNum())) { - fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_cliaNum") - .setValue(organization.getCliaNum())); - } - if (!GenericValidator.isBlankOrNull(organization.getShortName())) { - fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_shortName") - .setValue(organization.getShortName())); - } - if (!GenericValidator.isBlankOrNull(organization.getCode())) { - fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_code") - .setValue(organization.getCode())); - } - if (!GenericValidator.isBlankOrNull(organization.getCode())) { - fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_uuid") - .setValue(organization.getFhirUuidAsString())); - } - } - - private void setOeOrganizationTypes(Organization organization, - org.hl7.fhir.r4.model.Organization fhirOrganization) { - Set orgTypes = new HashSet<>(); - OrganizationType orgType = null; - for (CodeableConcept type : fhirOrganization.getType()) { - for (Coding coding : type.getCoding()) { - if (coding.getSystem() != null - && coding.getSystem().equals(fhirConfig.getOeFhirSystem() + "/orgType")) { - orgType = new OrganizationType(); - orgType.setName(coding.getCode()); - orgType.setDescription(type.getText()); - orgType.setNameKey("org_type." + coding.getCode() + ".name"); - orgType.setOrganizations(new HashSet<>()); - orgType.getOrganizations().add(organization); - orgTypes.add(orgType); - } - } - } - organization.setOrganizationTypes(orgTypes); - } - - private void setFhirOrganizationTypes(org.hl7.fhir.r4.model.Organization fhirOrganization, - Organization organization) { - Set orgTypes = organization.getOrganizationTypes(); - for (OrganizationType orgType : orgTypes) { - fhirOrganization.addType(new CodeableConcept() // - .setText(orgType.getDescription()) // - .addCoding(new Coding() // - .setSystem(fhirConfig.getOeFhirSystem() + "/orgType") // - .setCode(orgType.getName()))); - } - } - - private void setOeOrganizationAddressInfo(Organization organization, - org.hl7.fhir.r4.model.Organization fhirOrganization) { - organization.setStreetAddress(fhirOrganization.getAddressFirstRep().getLine().stream() - .map(e -> e.asStringValue()).collect(Collectors.joining("\\n"))); - organization.setCity(fhirOrganization.getAddressFirstRep().getCity()); - organization.setState(fhirOrganization.getAddressFirstRep().getState()); - organization.setZipCode(fhirOrganization.getAddressFirstRep().getPostalCode()); - } - - private void setFhirAddressInfo(org.hl7.fhir.r4.model.Organization fhirOrganization, Organization organization) { - if (!GenericValidator.isBlankOrNull(organization.getStreetAddress())) { - fhirOrganization.getAddressFirstRep().addLine(organization.getStreetAddress()); - } - if (!GenericValidator.isBlankOrNull(organization.getCity())) { - fhirOrganization.getAddressFirstRep().setCity(organization.getCity()); - } - if (!GenericValidator.isBlankOrNull(organization.getState())) { - fhirOrganization.getAddressFirstRep().setState(organization.getState()); - } - if (!GenericValidator.isBlankOrNull(organization.getZipCode())) { - fhirOrganization.getAddressFirstRep().setPostalCode(organization.getZipCode()); - } - } - - private Annotation transformNoteToAnnotation(Note note) { - Annotation annotation = new Annotation(); - annotation.setText(note.getText()); - return annotation; - } - - @Override - public boolean setTempIdIfMissing(Resource resource, TempIdGenerator tempIdGenerator) { - if (GenericValidator.isBlankOrNull(resource.getId())) { - resource.setId(tempIdGenerator.getNextId()); - return true; - } - return false; - } - - @Override - public Reference createReferenceFor(Resource resource) { - if (resource == null) { - return null; - } - Reference reference = new Reference(resource); - reference.setReference(resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); - return reference; - } + @Override + public Practitioner transformNameToPractitioner(String practitionerName) { + Practitioner practitioner = new Practitioner(); + HumanName name = practitioner.addName(); + + if (practitionerName.contains(",")) { + String[] names = practitionerName.split(",", 2); + name.setFamily(names[0]); + for (int i = 1; i < names.length; ++i) { + name.addGiven(names[i]); + } + } else { + String[] names = practitionerName.split(" "); + if (names.length >= 1) { + name.setFamily(names[names.length - 1]); + for (int i = 0; i < names.length - 1; ++i) { + name.addGiven(names[i]); + } + } + } + return practitioner; + } + + @Override + @Transactional(readOnly = true) + public org.hl7.fhir.r4.model.Organization transformToFhirOrganization(Organization organization) { + org.hl7.fhir.r4.model.Organization fhirOrganization = new org.hl7.fhir.r4.model.Organization(); + fhirOrganization + .setId(organization.getFhirUuid() == null ? organization.getId() : organization.getFhirUuidAsString()); + fhirOrganization.setName(organization.getOrganizationName()); + fhirOrganization.setActive(organization.getIsActive() == IActionConstants.YES ? true : false); + this.setFhirOrganizationIdentifiers(fhirOrganization, organization); + this.setFhirAddressInfo(fhirOrganization, organization); + this.setFhirOrganizationTypes(fhirOrganization, organization); + return fhirOrganization; + } + + @Override + @Transactional(readOnly = true) + public Organization transformToOrganization(org.hl7.fhir.r4.model.Organization fhirOrganization) { + Organization organization = new Organization(); + organization.setOrganizationName(fhirOrganization.getName()); + organization.setIsActive(Boolean.FALSE == fhirOrganization.getActiveElement().getValue() ? IActionConstants.NO + : IActionConstants.YES); + + setOeOrganizationIdentifiers(organization, fhirOrganization); + setOeOrganizationAddressInfo(organization, fhirOrganization); + setOeOrganizationTypes(organization, fhirOrganization); + + organization.setMlsLabFlag(IActionConstants.NO); + organization.setMlsSentinelLabFlag(IActionConstants.NO); + + return organization; + } + + private void setOeOrganizationIdentifiers(Organization organization, + org.hl7.fhir.r4.model.Organization fhirOrganization) { + organization.setFhirUuid(UUID.fromString(fhirOrganization.getIdElement().getIdPart())); + for (Identifier identifier : fhirOrganization.getIdentifier()) { + if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_cliaNum")) { + organization.setCliaNum(identifier.getValue()); + } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_shortName")) { + organization.setShortName(identifier.getValue()); + } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_code")) { + organization.setCode(identifier.getValue()); + } else if (identifier.getSystem().equals(fhirConfig.getOeFhirSystem() + "/org_uuid")) { + organization.setFhirUuid(UUID.fromString(identifier.getValue())); + } + } + } + + private void setFhirOrganizationIdentifiers(org.hl7.fhir.r4.model.Organization fhirOrganization, + Organization organization) { + if (!GenericValidator.isBlankOrNull(organization.getCliaNum())) { + fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_cliaNum") + .setValue(organization.getCliaNum())); + } + if (!GenericValidator.isBlankOrNull(organization.getShortName())) { + fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_shortName") + .setValue(organization.getShortName())); + } + if (!GenericValidator.isBlankOrNull(organization.getCode())) { + fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_code") + .setValue(organization.getCode())); + } + if (!GenericValidator.isBlankOrNull(organization.getCode())) { + fhirOrganization.addIdentifier(new Identifier().setSystem(fhirConfig.getOeFhirSystem() + "/org_uuid") + .setValue(organization.getFhirUuidAsString())); + } + } + + private void setOeOrganizationTypes(Organization organization, + org.hl7.fhir.r4.model.Organization fhirOrganization) { + Set orgTypes = new HashSet<>(); + OrganizationType orgType = null; + for (CodeableConcept type : fhirOrganization.getType()) { + for (Coding coding : type.getCoding()) { + if (coding.getSystem() != null + && coding.getSystem().equals(fhirConfig.getOeFhirSystem() + "/orgType")) { + orgType = new OrganizationType(); + orgType.setName(coding.getCode()); + orgType.setDescription(type.getText()); + orgType.setNameKey("org_type." + coding.getCode() + ".name"); + orgType.setOrganizations(new HashSet<>()); + orgType.getOrganizations().add(organization); + orgTypes.add(orgType); + } + } + } + organization.setOrganizationTypes(orgTypes); + } + + private void setFhirOrganizationTypes(org.hl7.fhir.r4.model.Organization fhirOrganization, + Organization organization) { + Set orgTypes = organization.getOrganizationTypes(); + for (OrganizationType orgType : orgTypes) { + fhirOrganization.addType(new CodeableConcept() // + .setText(orgType.getDescription()) // + .addCoding(new Coding() // + .setSystem(fhirConfig.getOeFhirSystem() + "/orgType") // + .setCode(orgType.getName()))); + } + } + + private void setOeOrganizationAddressInfo(Organization organization, + org.hl7.fhir.r4.model.Organization fhirOrganization) { + organization.setStreetAddress(fhirOrganization.getAddressFirstRep().getLine().stream() + .map(e -> e.asStringValue()).collect(Collectors.joining("\\n"))); + organization.setCity(fhirOrganization.getAddressFirstRep().getCity()); + organization.setState(fhirOrganization.getAddressFirstRep().getState()); + organization.setZipCode(fhirOrganization.getAddressFirstRep().getPostalCode()); + } + + private void setFhirAddressInfo(org.hl7.fhir.r4.model.Organization fhirOrganization, Organization organization) { + if (!GenericValidator.isBlankOrNull(organization.getStreetAddress())) { + fhirOrganization.getAddressFirstRep().addLine(organization.getStreetAddress()); + } + if (!GenericValidator.isBlankOrNull(organization.getCity())) { + fhirOrganization.getAddressFirstRep().setCity(organization.getCity()); + } + if (!GenericValidator.isBlankOrNull(organization.getState())) { + fhirOrganization.getAddressFirstRep().setState(organization.getState()); + } + if (!GenericValidator.isBlankOrNull(organization.getZipCode())) { + fhirOrganization.getAddressFirstRep().setPostalCode(organization.getZipCode()); + } + } + + private Annotation transformNoteToAnnotation(Note note) { + Annotation annotation = new Annotation(); + annotation.setText(note.getText()); + return annotation; + } + + @Override + public boolean setTempIdIfMissing(Resource resource, TempIdGenerator tempIdGenerator) { + if (GenericValidator.isBlankOrNull(resource.getId())) { + resource.setId(tempIdGenerator.getNextId()); + return true; + } + return false; + } + + @Override + public Reference createReferenceFor(Resource resource) { + if (resource == null) { + return null; + } + Reference reference = new Reference(resource); + reference.setReference(resource.getResourceType() + "/" + resource.getIdElement().getIdPart()); + return reference; + } @Override public Reference createReferenceFor(ResourceType resourceType, String id) { + if (GenericValidator.isBlankOrNull(id)) { + LogEvent.logWarn(this.getClass().getName(), "createReferenceFor", + "null or empty id used in resource:" + resourceType + "/" + id); + } Reference reference = new Reference(); reference.setReference(resourceType + "/" + id); return reference; } - @Override - public String getIdFromLocation(String location) { - String id = location.substring(location.indexOf("/") + 1); - while (id.lastIndexOf("/") > 0) { - id = id.substring(0, id.lastIndexOf("/")); - } - return id; - } - - @Override - public Identifier createIdentifier(String system, String value) { - Identifier identifier = new Identifier(); - identifier.setSystem(system); - identifier.setValue(value); - return identifier; - } - - private class FhirOrderEntryObjects { - @SuppressWarnings("unused") - public org.hl7.fhir.r4.model.Patient patient; - public Practitioner requester; - List sampleEntryObjectsList = new ArrayList<>(); - } - - private class FhirSampleEntryObjects { - public Practitioner collector; - public Specimen specimen; - public List serviceRequests = new ArrayList<>(); - } - - public void addHumanNameToPerson(HumanName humanName, Person person) { - person.setFirstName( - humanName.getGivenAsSingleString() == null ? "" : humanName.getGivenAsSingleString().strip()); - person.setLastName(humanName.getFamily() == null ? "" : humanName.getFamily().strip()); - } - - public void addTelecomToPerson(List telecoms, Person person) { - for (ContactPoint contact : telecoms) { - String contactValue = contact.getValue(); - if (ContactPointSystem.EMAIL.equals(contact.getSystem())) { - person.setEmail(contactValue); - } else if (ContactPointSystem.FAX.equals(contact.getSystem())) { - person.setFax(contactValue); - } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) - && ContactPointUse.MOBILE.equals(contact.getUse())) { - person.setCellPhone(contactValue); - person.setPrimaryPhone(contactValue); - } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) - && ContactPointUse.HOME.equals(contact.getUse())) { - person.setHomePhone(contactValue); - if (GenericValidator.isBlankOrNull(person.getPrimaryPhone())) { - person.setPrimaryPhone(contactValue); - } - } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) - && ContactPointUse.WORK.equals(contact.getUse())) { - person.setWorkPhone(contactValue); - if (GenericValidator.isBlankOrNull(person.getPrimaryPhone())) { - person.setPrimaryPhone(contactValue); - } - } - } - } - - @Override - public Provider transformToProvider(Practitioner practitioner) { - Provider provider = new Provider(); - provider.setActive(practitioner.getActive()); - provider.setFhirUuid(UUID.fromString(practitioner.getIdElement().getIdPart())); - - provider.setPerson(new Person()); - addHumanNameToPerson(practitioner.getNameFirstRep(), provider.getPerson()); - addTelecomToPerson(practitioner.getTelecom(), provider.getPerson()); - - return provider; - - } + @Override + public String getIdFromLocation(String location) { + String id = location.substring(location.indexOf("/") + 1); + while (id.lastIndexOf("/") > 0) { + id = id.substring(0, id.lastIndexOf("/")); + } + return id; + } + + @Override + public Identifier createIdentifier(String system, String value) { + Identifier identifier = new Identifier(); + identifier.setSystem(system); + identifier.setValue(value); + return identifier; + } + + private class FhirOrderEntryObjects { + @SuppressWarnings("unused") + public org.hl7.fhir.r4.model.Patient patient; + public Practitioner requester; + List sampleEntryObjectsList = new ArrayList<>(); + } + + private class FhirSampleEntryObjects { + public Practitioner collector; + public Specimen specimen; + public List serviceRequests = new ArrayList<>(); + } + + public void addHumanNameToPerson(HumanName humanName, Person person) { + person.setFirstName( + humanName.getGivenAsSingleString() == null ? "" : humanName.getGivenAsSingleString().strip()); + person.setLastName(humanName.getFamily() == null ? "" : humanName.getFamily().strip()); + } + + public void addTelecomToPerson(List telecoms, Person person) { + for (ContactPoint contact : telecoms) { + String contactValue = contact.getValue(); + if (ContactPointSystem.EMAIL.equals(contact.getSystem())) { + person.setEmail(contactValue); + } else if (ContactPointSystem.FAX.equals(contact.getSystem())) { + person.setFax(contactValue); + } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) + && ContactPointUse.MOBILE.equals(contact.getUse())) { + person.setCellPhone(contactValue); + person.setPrimaryPhone(contactValue); + } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) + && ContactPointUse.HOME.equals(contact.getUse())) { + person.setHomePhone(contactValue); + if (GenericValidator.isBlankOrNull(person.getPrimaryPhone())) { + person.setPrimaryPhone(contactValue); + } + } else if (ContactPointSystem.PHONE.equals(contact.getSystem()) + && ContactPointUse.WORK.equals(contact.getUse())) { + person.setWorkPhone(contactValue); + if (GenericValidator.isBlankOrNull(person.getPrimaryPhone())) { + person.setPrimaryPhone(contactValue); + } + } + } + } + + @Override + public Provider transformToProvider(Practitioner practitioner) { + Provider provider = new Provider(); + provider.setActive(practitioner.getActive()); + provider.setFhirUuid(UUID.fromString(practitioner.getIdElement().getIdPart())); + + provider.setPerson(new Person()); + addHumanNameToPerson(practitioner.getNameFirstRep(), provider.getPerson()); + addTelecomToPerson(practitioner.getTelecom(), provider.getPerson()); + + return provider; + + } } diff --git a/src/main/java/org/openelisglobal/dataexchange/order/controller/StudyElectronicOrdersController.java b/src/main/java/org/openelisglobal/dataexchange/order/controller/StudyElectronicOrdersController.java index fc9ff37e35..99c5dd4079 100644 --- a/src/main/java/org/openelisglobal/dataexchange/order/controller/StudyElectronicOrdersController.java +++ b/src/main/java/org/openelisglobal/dataexchange/order/controller/StudyElectronicOrdersController.java @@ -118,8 +118,6 @@ private ElectronicOrderDisplayItem convertToDisplayItem(ElectronicOrder electron Patient patient = electronicOrder.getPatient(); if (patient != null) { displayItem.setSubjectNumber(patientService.getSubjectNumber(patient)); - displayItem.setPatientLastName(patient.getPerson().getLastName()); - displayItem.setPatientFirstName(patient.getPerson().getFirstName()); displayItem.setPatientNationalId(patient.getNationalId()); displayItem.setBirthDate(patient.getBirthDateForDisplay()); displayItem.setGender(patient.getGender()); @@ -140,8 +138,6 @@ private ElectronicOrderDisplayItem convertToDisplayItem(ElectronicOrder electron if (sample != null) { displayItem.setLabNumber(sample.getAccessionNumber()); } - - if (useAllInfo) { IGenericClient fhirClient = fhirUtil.getFhirClient(fhirConfig.getLocalFhirStorePath()); ServiceRequest serviceRequest = fhirClient.read().resource(ServiceRequest.class) @@ -165,20 +161,6 @@ private ElectronicOrderDisplayItem convertToDisplayItem(ElectronicOrder electron if (test != null) { displayItem.setTestName(test.getLocalizedTestName().getLocalizedValue()); } - - String patientUuid = serviceRequest.getSubject().getReferenceElement().getIdPart(); - org.hl7.fhir.r4.model.Patient fhirPatient = fhirClient.read() - .resource(org.hl7.fhir.r4.model.Patient.class).withId(patientUuid).execute(); - - for (Identifier identifier : fhirPatient.getIdentifier()) { - if ("passport".equals(identifier.getSystem())) { - displayItem.setPassportNumber(identifier.getId()); - } - if ((fhirConfig.getOeFhirSystem() + "/pat_subjectNumber").equals(identifier.getSystem())) { - displayItem.setSubjectNumber(identifier.getId()); - } - } - } } catch (ResourceNotFoundException e) { String errorMsg = "error in data collection - FHIR resource not found"; displayItem.setWarnings(Arrays.asList(errorMsg)); diff --git a/src/main/java/org/openelisglobal/dataexchange/order/valueholder/ElectronicOrderDisplayItem.java b/src/main/java/org/openelisglobal/dataexchange/order/valueholder/ElectronicOrderDisplayItem.java index 6f4b22705d..f42274ab7c 100644 --- a/src/main/java/org/openelisglobal/dataexchange/order/valueholder/ElectronicOrderDisplayItem.java +++ b/src/main/java/org/openelisglobal/dataexchange/order/valueholder/ElectronicOrderDisplayItem.java @@ -26,6 +26,8 @@ public class ElectronicOrderDisplayItem { private String electronicOrderId; private String externalOrderId; + + private String patientUpid; private String requestDateDisplay; @@ -192,4 +194,13 @@ public OrderPriority getPriority() { public void setPriority(OrderPriority priority) { this.priority = priority; } + + public String getPatientUpid() { + return patientUpid; + } + + public void setPatientUpid(String patientUpid) { + this.patientUpid = patientUpid; + } + } diff --git a/src/main/java/org/openelisglobal/dictionary/ObservationHistoryList.java b/src/main/java/org/openelisglobal/dictionary/ObservationHistoryList.java index 25b4659cf6..509271a162 100644 --- a/src/main/java/org/openelisglobal/dictionary/ObservationHistoryList.java +++ b/src/main/java/org/openelisglobal/dictionary/ObservationHistoryList.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang3.ObjectUtils; import org.openelisglobal.common.valueholder.BaseObject; import org.openelisglobal.dictionary.service.DictionaryService; import org.openelisglobal.dictionary.valueholder.Dictionary; @@ -81,7 +82,9 @@ private static List copyListAndDeleteEntry(List oldList, private static List copyListAndAddEntry(List oldList, Dictionary entryToAdd) { List newList = new ArrayList<>(oldList); - newList.add(entryToAdd); + if(ObjectUtils.isNotEmpty(entryToAdd)) { + newList.add(entryToAdd); + } return newList; } @@ -92,7 +95,9 @@ private static List copyListAndAddEntry(List oldList, Di public static final Map MAP = new HashMap<>(); static { for (ObservationHistoryList ds : ObservationHistoryList.values()) { - MAP.put(ds.name(), ds); + if(ObjectUtils.isNotEmpty(ds)) { + MAP.put(ds.name(), ds); + } } } diff --git a/src/main/java/org/openelisglobal/observationhistory/daoimpl/ObservationHistoryDAOImpl.java b/src/main/java/org/openelisglobal/observationhistory/daoimpl/ObservationHistoryDAOImpl.java index 5db54a593a..6593f6969c 100644 --- a/src/main/java/org/openelisglobal/observationhistory/daoimpl/ObservationHistoryDAOImpl.java +++ b/src/main/java/org/openelisglobal/observationhistory/daoimpl/ObservationHistoryDAOImpl.java @@ -224,6 +224,6 @@ protected LIMSRuntimeException createAndLogException(String methodName, Exceptio @Override @Transactional(readOnly = true) public ObservationHistory getById(ObservationHistory observation) throws LIMSRuntimeException { - return get(observation.getId()).get(); + return get(observation.getId()).orElse(null); } } diff --git a/src/main/java/org/openelisglobal/observationhistory/service/ObservationHistoryServiceImpl.java b/src/main/java/org/openelisglobal/observationhistory/service/ObservationHistoryServiceImpl.java index 7b4017ac39..a88572caca 100644 --- a/src/main/java/org/openelisglobal/observationhistory/service/ObservationHistoryServiceImpl.java +++ b/src/main/java/org/openelisglobal/observationhistory/service/ObservationHistoryServiceImpl.java @@ -29,7 +29,10 @@ public enum ObservationType { REQUEST_DATE("requestDate"), NEXT_VISIT_DATE("nextVisitDate"), REFERRING_SITE("referringSite"), REFERRERS_PATIENT_ID("referrersPatientId"), BILLING_REFERENCE_NUMBER("billingRefNumber"), TEST_LOCATION_CODE("testLocationCode"), TEST_LOCATION_CODE_OTHER("testLocationCodeOther"), PROGRAM("program"), - HIV_STATUS("hivStatus"),VL_PREGNANCY("vlPregnancy"),VL_SUCKLE("vlSuckle"); + HIV_STATUS("hivStatus"),VL_PREGNANCY("vlPregnancy"),VL_SUCKLE("vlSuckle"), + TB_ORDER_REASON("TbOrderReason"),TB_DIAGNOSTIC_REASON("TbDiagnosticReason"),TB_FOLLOWUP_REASON("TbFollowupReason"), + TB_FOLLOWUP_PERIOD_LINE1("TbFollowupReasonPeriodLine1"),TB_FOLLOWUP_PERIOD_LINE2("TbFollowupReasonPeriodLine2"),TB_ANALYSIS_METHOD("TbAnalysisMethod"), + TB_SAMPLE_ASPECT("TbSampleAspects"); private String dbName; diff --git a/src/main/java/org/openelisglobal/organization/util/OrganizationTypeList.java b/src/main/java/org/openelisglobal/organization/util/OrganizationTypeList.java index 1b75425b40..f5a2c67ed2 100644 --- a/src/main/java/org/openelisglobal/organization/util/OrganizationTypeList.java +++ b/src/main/java/org/openelisglobal/organization/util/OrganizationTypeList.java @@ -91,15 +91,14 @@ private OrganizationTypeList(String orderBy, Comparator comparator * or an empty list. */ public final List getList() { - List all; + List all = SpringContext.getBean(OrganizationService.class).getOrganizationsByTypeName(orderBy, name); try { - all = SpringContext.getBean(OrganizationService.class).getOrganizationsByTypeName(orderBy, name); if (comparator != null) { Collections.sort(all, comparator); } } catch (RuntimeException e) { LogEvent.logError(e); - all = new ArrayList<>(); + //all = new ArrayList<>(); must not return empty List if sorting fails } return all; } diff --git a/src/main/java/org/openelisglobal/patient/controller/BasePatientEntryByProject.java b/src/main/java/org/openelisglobal/patient/controller/BasePatientEntryByProject.java index de0b4b81f8..b11c65abbc 100644 --- a/src/main/java/org/openelisglobal/patient/controller/BasePatientEntryByProject.java +++ b/src/main/java/org/openelisglobal/patient/controller/BasePatientEntryByProject.java @@ -30,7 +30,7 @@ public abstract class BasePatientEntryByProject extends BaseController { private static final String[] BASE_ALLOWED_FIELDS = new String[] { "patientUpdateStatus", "patientPK", "samplePK", "receivedDateForDisplay", "receivedTimeForDisplay", "interviewDate", "interviewTime", "subjectNumber", - "siteSubjectNumber", "labNo", "centerName", "centerCode", "lastName", "firstName", "gender", + "siteSubjectNumber", "labNo", "centerName", "centerCode", "lastName", "firstName", "gender","upidCode", "birthDateForDisplay", "observations.projectFormName", "observations.hivStatus", "observations.educationLevel", "observations.maritalStatus", "observations.nationality", "observations.nationalityOther", "observations.legalResidence", "observations.nameOfDoctor", @@ -38,7 +38,7 @@ public abstract class BasePatientEntryByProject extends BaseController { "observations.arvProphylaxisBenefit", "observations.arvProphylaxis", "observations.currentARVTreatment", "observations.priorARVTreatment", "observations.priorARVTreatmentINNsList*", "observations.cotrimoxazoleTreatment", "observations.aidsStage", "observations.anyCurrentDiseases", - "ProjectData.dbsTaken","ProjectData.dbsvlTaken", "ProjectData.pscvlTaken","ProjectData.viralLoadTest", + "ProjectData.dbsTaken","ProjectData.dbsvlTaken", "ProjectData.pscvlTaken","ProjectData.edtaTubeTaken","ProjectData.viralLoadTest", "observations.currentDiseases", "observations.currentDiseasesValue", "observations.currentOITreatment", "observations.patientWeight", "observations.karnofskyScore", "observations.underInvestigation", "projectData.underInvestigationNote", @@ -67,7 +67,8 @@ public abstract class BasePatientEntryByProject extends BaseController { "observations.demandcd4Date", "observations.vlBenefit", "observations.priorVLLab", "observations.priorVLValue", "observations.priorVLDate", // - "observations.service", "observations.hospitalPatient", "observations.reason" }; + "observations.service", "observations.hospitalPatient", "observations.reason", "ProjectData.asanteTest", + "ProjectData.plasmaTaken", "ProjectData.serumTaken" }; protected List getBasePatientEntryByProjectFields() { List allowedFields = new ArrayList<>(); diff --git a/src/main/java/org/openelisglobal/patient/controller/PatientEditByProjectController.java b/src/main/java/org/openelisglobal/patient/controller/PatientEditByProjectController.java index f3af47a090..3996be2eae 100644 --- a/src/main/java/org/openelisglobal/patient/controller/PatientEditByProjectController.java +++ b/src/main/java/org/openelisglobal/patient/controller/PatientEditByProjectController.java @@ -115,7 +115,7 @@ protected String findLocalForward(String forward) { } else if (FWD_FAIL.equals(forward)) { return "redirect:/Dashboard"; } else if (FWD_SUCCESS_INSERT.equals(forward)) { - return "redirect:/PatientEditByProject"; + return "redirect:/PatientEditByProject?type=readwrite"; } else if (FWD_FAIL_INSERT.equals(forward)) { return "patientEditByProjectDefinition"; } else { diff --git a/src/main/java/org/openelisglobal/patient/form/PatientEntryByProjectForm.java b/src/main/java/org/openelisglobal/patient/form/PatientEntryByProjectForm.java index 4bd5b1142d..3139ce5e4c 100644 --- a/src/main/java/org/openelisglobal/patient/form/PatientEntryByProjectForm.java +++ b/src/main/java/org/openelisglobal/patient/form/PatientEntryByProjectForm.java @@ -10,6 +10,7 @@ import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; import org.openelisglobal.common.util.validator.CustomDateValidator.DateRelation; import org.openelisglobal.common.validator.ValidationHelper; +import org.openelisglobal.dataexchange.order.valueholder.ElectronicOrder; import org.openelisglobal.dictionary.ObservationHistoryList; import org.openelisglobal.organization.util.OrganizationTypeList; import org.openelisglobal.patient.action.IPatientUpdate.PatientUpdateStatus; @@ -23,252 +24,290 @@ import org.openelisglobal.validation.constraintvalidator.NameValidator.NameType; public class PatientEntryByProjectForm extends BaseForm implements IAccessionerForm { - // for display - private Map formLists; + // for display + private Map formLists; - // for display - private Map dictionaryLists; + // for display + private Map dictionaryLists; - // for display - private Map organizationTypeLists; + // for display + private Map organizationTypeLists; - @Pattern(regexp = ValidationHelper.ID_REGEX) - private String patientPK = ""; + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String patientPK = ""; - @Pattern(regexp = ValidationHelper.ID_REGEX) - private String samplePK = ""; + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String samplePK = ""; - @ValidDate(relative = DateRelation.PAST) - private String interviewDate = ""; + @ValidDate(relative = DateRelation.PAST) + private String interviewDate = ""; - @ValidTime - private String interviewTime = ""; + @ValidTime + private String interviewTime = ""; - @ValidDate(relative = DateRelation.PAST) - private String receivedDateForDisplay = ""; + @ValidDate(relative = DateRelation.PAST) + private String receivedDateForDisplay = ""; - @ValidTime - private String receivedTimeForDisplay = ""; + @ValidTime + private String receivedTimeForDisplay = ""; - @ValidDate(relative = DateRelation.TODAY) - private String currentDate = ""; + @ValidDate(relative = DateRelation.TODAY) + private String currentDate = ""; - private PatientUpdateStatus patientUpdateStatus = PatientUpdateStatus.ADD; + private PatientUpdateStatus patientUpdateStatus = PatientUpdateStatus.ADD; - @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) - private String subjectNumber = ""; + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String subjectNumber = ""; - @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) - private String siteSubjectNumber = ""; + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String siteSubjectNumber = ""; + + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String upidCode = ""; @ValidAccessionNumber(format = AccessionFormat.PROGRAMNUM) private String labNo = ""; - @Pattern(regexp = ValidationHelper.ID_REGEX) - private String centerName = ""; + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String centerName = ""; - @Min(0) - private Integer centerCode; + @Min(0) + private Integer centerCode; - @ValidName(nameType = NameType.FIRST_NAME) - private String firstName = ""; + @ValidName(nameType = NameType.FIRST_NAME) + private String firstName = ""; - @ValidName(nameType = NameType.LAST_NAME) - private String lastName = ""; + @ValidName(nameType = NameType.LAST_NAME) + private String lastName = ""; - @Pattern(regexp = ValidationHelper.GENDER_REGEX) - private String gender = ""; + @Pattern(regexp = ValidationHelper.GENDER_REGEX) + private String gender = ""; - @ValidDate(relative = DateRelation.PAST) - private String birthDateForDisplay = ""; + @ValidDate(relative = DateRelation.PAST) + private String birthDateForDisplay = ""; - @Valid - private ObservationData observations; + @Valid + private ObservationData observations; - @Valid - private ProjectData projectData; + @Valid + private ProjectData projectData; - public PatientEntryByProjectForm() { - setFormName("patientEntryByProjectForm"); - } + @Valid + private ElectronicOrder electronicOrder; - public Map getFormLists() { - return formLists; - } + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String patientFhirUuid; - public void setFormLists(Map formLists) { - this.formLists = formLists; - } + public PatientEntryByProjectForm() { + setFormName("patientEntryByProjectForm"); + } - public Map getDictionaryLists() { - return dictionaryLists; - } + public Map getFormLists() { + return formLists; + } - public void setDictionaryLists(Map dictionaryLists) { - this.dictionaryLists = dictionaryLists; - } + public void setFormLists(Map formLists) { + this.formLists = formLists; + } - public Map getOrganizationTypeLists() { - return organizationTypeLists; - } + public Map getDictionaryLists() { + return dictionaryLists; + } - public void setOrganizationTypeLists(Map organizationTypeLists) { - this.organizationTypeLists = organizationTypeLists; - } + public void setDictionaryLists(Map dictionaryLists) { + this.dictionaryLists = dictionaryLists; + } - public String getPatientPK() { - return patientPK; - } + public Map getOrganizationTypeLists() { + return organizationTypeLists; + } - public void setPatientPK(String patientPK) { - this.patientPK = patientPK; - } + public void setOrganizationTypeLists(Map organizationTypeLists) { + this.organizationTypeLists = organizationTypeLists; + } - public String getSamplePK() { - return samplePK; - } + public String getPatientPK() { + return patientPK; + } - public void setSamplePK(String samplePK) { - this.samplePK = samplePK; - } + public void setPatientPK(String patientPK) { + this.patientPK = patientPK; + } - public String getInterviewDate() { - return interviewDate; - } + public String getSamplePK() { + return samplePK; + } - public void setInterviewDate(String interviewDate) { - this.interviewDate = interviewDate; - } + public void setSamplePK(String samplePK) { + this.samplePK = samplePK; + } - public String getInterviewTime() { - return interviewTime; - } + public String getInterviewDate() { + return interviewDate; + } - public void setInterviewTime(String interviewTime) { - this.interviewTime = interviewTime; - } + public void setInterviewDate(String interviewDate) { + this.interviewDate = interviewDate; + } - public String getReceivedDateForDisplay() { - return receivedDateForDisplay; - } + public String getInterviewTime() { + return interviewTime; + } - public void setReceivedDateForDisplay(String receivedDateForDisplay) { - this.receivedDateForDisplay = receivedDateForDisplay; - } + public void setInterviewTime(String interviewTime) { + this.interviewTime = interviewTime; + } - public String getReceivedTimeForDisplay() { - return receivedTimeForDisplay; - } + public String getReceivedDateForDisplay() { + return receivedDateForDisplay; + } - public void setReceivedTimeForDisplay(String receivedTimeForDisplay) { - this.receivedTimeForDisplay = receivedTimeForDisplay; - } + public void setReceivedDateForDisplay(String receivedDateForDisplay) { + this.receivedDateForDisplay = receivedDateForDisplay; + } - public String getCurrentDate() { - return currentDate; - } + public String getReceivedTimeForDisplay() { + return receivedTimeForDisplay; + } - public void setCurrentDate(String currentDate) { - this.currentDate = currentDate; - } + public void setReceivedTimeForDisplay(String receivedTimeForDisplay) { + this.receivedTimeForDisplay = receivedTimeForDisplay; + } - public PatientUpdateStatus getPatientUpdateStatus() { - return patientUpdateStatus; - } + public String getCurrentDate() { + return currentDate; + } - public void setPatientUpdateStatus(PatientUpdateStatus patientUpdateStatus) { - this.patientUpdateStatus = patientUpdateStatus; - } - - public String getSubjectNumber() { - return subjectNumber; - } - - public void setSubjectNumber(String subjectNumber) { - this.subjectNumber = subjectNumber; - } - - public String getSiteSubjectNumber() { - return siteSubjectNumber; - } - - public void setSiteSubjectNumber(String siteSubjectNumber) { - this.siteSubjectNumber = siteSubjectNumber; - } - - public String getLabNo() { - return labNo; - } - - public void setLabNo(String labNo) { - this.labNo = labNo; - } - - public String getCenterName() { - return centerName; - } - - public void setCenterName(String centerName) { - this.centerName = centerName; - } - - public Integer getCenterCode() { - return centerCode; - } - - public void setCenterCode(Integer centerCode) { - this.centerCode = centerCode; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getGender() { - return gender; - } - - public void setGender(String gender) { - this.gender = gender; - } - - public String getBirthDateForDisplay() { - return birthDateForDisplay; - } - - public void setBirthDateForDisplay(String birthDateForDisplay) { - this.birthDateForDisplay = birthDateForDisplay; - } - - @Override - public ObservationData getObservations() { - return observations; - } - - @Override - public void setObservations(ObservationData observations) { - this.observations = observations; - } - - @Override - public ProjectData getProjectData() { - return projectData; - } - - @Override - public void setProjectData(ProjectData projectData) { - this.projectData = projectData; - } + public void setCurrentDate(String currentDate) { + this.currentDate = currentDate; + } + + public PatientUpdateStatus getPatientUpdateStatus() { + return patientUpdateStatus; + } + + public void setPatientUpdateStatus(PatientUpdateStatus patientUpdateStatus) { + this.patientUpdateStatus = patientUpdateStatus; + } + + public String getSubjectNumber() { + return subjectNumber; + } + + public void setSubjectNumber(String subjectNumber) { + this.subjectNumber = subjectNumber; + } + + public String getSiteSubjectNumber() { + return siteSubjectNumber; + } + + public void setSiteSubjectNumber(String siteSubjectNumber) { + this.siteSubjectNumber = siteSubjectNumber; + } + + public String getLabNo() { + return labNo; + } + + public void setLabNo(String labNo) { + this.labNo = labNo; + } + + public String getCenterName() { + return centerName; + } + + public void setCenterName(String centerName) { + this.centerName = centerName; + } + + public Integer getCenterCode() { + return centerCode; + } + + public void setCenterCode(Integer centerCode) { + this.centerCode = centerCode; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getBirthDateForDisplay() { + return birthDateForDisplay; + } + + public void setBirthDateForDisplay(String birthDateForDisplay) { + this.birthDateForDisplay = birthDateForDisplay; + } + + @Override + public ObservationData getObservations() { + return observations; + } + + @Override + public void setObservations(ObservationData observations) { + this.observations = observations; + } + + @Override + public ProjectData getProjectData() { + return projectData; + } + + @Override + public void setProjectData(ProjectData projectData) { + this.projectData = projectData; + } + + @Override + public ElectronicOrder getElectronicOrder() { + return electronicOrder; + } + + @Override + public void setElectronicOrder(ElectronicOrder electronicOrder) { + this.electronicOrder = electronicOrder; + } + + @Override + public String getPatientFhirUuid() { + return patientFhirUuid; + } + + @Override + public void setPatientFhirUuid(String patientFhirUuid) { + this.patientFhirUuid = patientFhirUuid; + } + + public String getUpidCode() { + return upidCode; + } + + public void setUpidCode(String upidCode) { + this.upidCode = upidCode; + } + } diff --git a/src/main/java/org/openelisglobal/patient/saving/Accessioner.java b/src/main/java/org/openelisglobal/patient/saving/Accessioner.java index 7e861c86cf..297e931d74 100644 --- a/src/main/java/org/openelisglobal/patient/saving/Accessioner.java +++ b/src/main/java/org/openelisglobal/patient/saving/Accessioner.java @@ -36,8 +36,10 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.service.AnalysisService; import org.openelisglobal.analysis.valueholder.Analysis; @@ -331,6 +333,7 @@ public String save() throws IllegalAccessException, LIMSRuntimeException, Invoca populateSampleData(); populateSampleHuman(); populateObservationHistory(); + updateSampleWithElectronicEOrders(); // all of the following methods are assumed to only write when // necessary @@ -818,6 +821,9 @@ protected void populatePatientData() patientInDB.setNationalId(convertEmptyToNull(form.getSubjectNumber())); patientInDB.setExternalId(convertEmptyToNull(form.getSiteSubjectNumber())); + if (ObjectUtils.isNotEmpty(form.getPatientFhirUuid())) { + patientInDB.setFhirUuid(UUID.fromString(form.getPatientFhirUuid())); + } populatePatientBirthDate(form.getBirthDateForDisplay()); projectData = form.getProjectData(); @@ -1002,6 +1008,7 @@ private Map findExistingSampleTypeItems() { * * @ */ + @Transactional public void completeSample() { if (isAllAnalysisDone() && !SpringContext.getBean(IStatusService.class) .getStatusID(OrderStatus.NonConforming_depricated).equals(sample.getStatus())) { @@ -1104,6 +1111,10 @@ protected void persistSampleProject() throws LIMSRuntimeException { */ protected void persistSampleHuman() { if (sampleHuman != null) { + SampleHuman otherSampleHuman = sampleHumanService.getMatch("sampleId", sample.getId()).orElse(null); + if (ObjectUtils.isNotEmpty(otherSampleHuman)) { + sampleHuman = otherSampleHuman; + } sampleHuman.setPatientId(patientInDB.getId()); sampleHuman.setSampleId(sample.getId()); // we do not store any doctor name as a provider in SampleHuman @@ -1254,19 +1265,25 @@ protected void persistRecordStatus() { } protected void deleteOldPatient() { - if (patientToDelete != null) { - List oldIdentities = identityService - .getPatientIdentitiesForPatient(patientToDelete.getId()); - for (PatientIdentity listIdentity : oldIdentities) { - identityService.delete(listIdentity.getId(), sysUserId); - } - Person personToDelete = patientToDelete.getPerson(); - patientToDelete.setSysUserId(sysUserId); - patientService.deleteAll(Arrays.asList(patientToDelete)); - personToDelete.setSysUserId(sysUserId); - personService.deleteAll(Arrays.asList(personToDelete)); - } - } + if (patientToDelete != null) { + try { + + List oldIdentities = identityService + .getPatientIdentitiesForPatient(patientToDelete.getId()); + for (PatientIdentity listIdentity : oldIdentities) { + identityService.delete(listIdentity.getId(), sysUserId); + } + Person personToDelete = patientToDelete.getPerson(); + patientToDelete.setSysUserId(sysUserId); + patientService.deleteAll(Arrays.asList(patientToDelete)); + personToDelete.setSysUserId(sysUserId); + personService.deleteAll(Arrays.asList(personToDelete)); + + } catch (Exception e) { + LogEvent.logError(e); + } + } + } protected List getObservationHistories() { return observationHistories; @@ -1343,13 +1360,24 @@ public void logAndAddMessage(String methodName, String messageKey, Exception e) // // } - private static String getObservationHistoryTypeId(ObservationHistoryTypeService ohtService, String name) { - ObservationHistoryType oht; - oht = ohtService.getByName(name); - if (oht != null) { - return oht.getId(); - } - - return null; - } + private static String getObservationHistoryTypeId(ObservationHistoryTypeService ohtService, String name) { + ObservationHistoryType oht; + oht = ohtService.getByName(name); + if (oht != null) { + return oht.getId(); + } + + return null; + } + + private void updateSampleWithElectronicEOrders() { + try { + if (ObjectUtils.isNotEmpty(projectFormMapper.getForm().getElectronicOrder())) { + sample.setReferringId(projectFormMapper.getForm().getElectronicOrder().getExternalId()); + sample.setClinicalOrderId(projectFormMapper.getForm().getElectronicOrder().getId()); + } + } catch (Exception e) { + LogEvent.logError(e); + } + } } diff --git a/src/main/java/org/openelisglobal/patient/validator/PatientEntryByProjectFormValidator.java b/src/main/java/org/openelisglobal/patient/validator/PatientEntryByProjectFormValidator.java index 1e340517b0..18ce985e4e 100644 --- a/src/main/java/org/openelisglobal/patient/validator/PatientEntryByProjectFormValidator.java +++ b/src/main/java/org/openelisglobal/patient/validator/PatientEntryByProjectFormValidator.java @@ -9,152 +9,175 @@ @Component public class PatientEntryByProjectFormValidator implements Validator { - @Override - public boolean supports(Class clazz) { - return PatientEntryByProjectForm.class.isAssignableFrom(clazz); - } + @Override + public boolean supports(Class clazz) { + return PatientEntryByProjectForm.class.isAssignableFrom(clazz); + } - @Override - public void validate(Object target, Errors errors) { - PatientEntryByProjectForm form = (PatientEntryByProjectForm) target; + @Override + public void validate(Object target, Errors errors) { + PatientEntryByProjectForm form = (PatientEntryByProjectForm) target; - if ("InitialARV_Id".equals(form.getObservations().getProjectFormName())) { - validateInitialARVForm(form, errors); - } else if ("FollowUpARV_Id".equals(form.getObservations().getProjectFormName())) { - validateFollowUpARVForm(form, errors); - } else if ("RTN_Id".equals(form.getObservations().getProjectFormName())) { - validateRTNForm(form, errors); - } else if ("VL_Id".equals(form.getObservations().getProjectFormName())) { - validateVLForm(form, errors); - } else if ("EID_Id".equals(form.getObservations().getProjectFormName())) { - validateEIDForm(form, errors); - } else { - errors.reject("error.formname.unrecognized", "The provided form name is unrecognized"); - } - } + if ("InitialARV_Id".equals(form.getObservations().getProjectFormName())) { + validateInitialARVForm(form, errors); + } else if ("FollowUpARV_Id".equals(form.getObservations().getProjectFormName())) { + validateFollowUpARVForm(form, errors); + } else if ("RTN_Id".equals(form.getObservations().getProjectFormName())) { + validateRTNForm(form, errors); + } else if ("VL_Id".equals(form.getObservations().getProjectFormName())) { + validateVLForm(form, errors); + } else if ("EID_Id".equals(form.getObservations().getProjectFormName())) { + validateEIDForm(form, errors); + } else if ("Recency_Id".equals(form.getObservations().getProjectFormName())) { + validateRecencyForm(form, errors); + } else { + errors.reject("error.formname.unrecognized", "The provided form name is unrecognized"); + } + } - private void validateEIDForm(PatientEntryByProjectForm form, Errors errors) { - ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + private void validateEIDForm(PatientEntryByProjectForm form, Errors errors) { + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); - ValidationHelper.validateFieldRequired(form.getProjectData().getEIDSiteName(), "ProjectData.EIDSiteName", - errors); + ValidationHelper.validateFieldRequired(form.getProjectData().getEIDSiteName(), "ProjectData.EIDSiteName", + errors); - ValidationHelper.validateFieldRequired(form.getProjectData().getEIDsiteCode(), "ProjectData.EIDSiteCode", - errors); + ValidationHelper.validateFieldRequired(form.getProjectData().getEIDsiteCode(), "ProjectData.EIDSiteCode", + errors); - if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) - && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { - ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); + if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) + && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { + ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); - ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); - } + ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); + } - ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); - ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); - ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); - } + } - private void validateVLForm(PatientEntryByProjectForm form, Errors errors) { + private void validateVLForm(PatientEntryByProjectForm form, Errors errors) { // ValidationHelper.validateFieldRequired(form.getCenterName(), "centerName", errors); // // if (form.getCenterCode() == null) { // errors.rejectValue("centerCode", "field.error.required"); // } - ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); - if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) - && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { - ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); + if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) + && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { + ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); - ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); - } + ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); + } - ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); - ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); - } + } - private void validateRTNForm(PatientEntryByProjectForm form, Errors errors) { - ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + private void validateRecencyForm(PatientEntryByProjectForm form, Errors errors) { +// ValidationHelper.validateFieldRequired(form.getCenterName(), "centerName", errors); +// +// if (form.getCenterCode() == null) { +// errors.rejectValue("centerCode", "field.error.required"); +// } + + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + + ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); + + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + + } + + private void validateRTNForm(PatientEntryByProjectForm form, Errors errors) { + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); - ValidationHelper.validateFieldRequired(form.getObservations().getNameOfDoctor(), "observations.nameOfDoctor", - errors); + ValidationHelper.validateFieldRequired(form.getObservations().getNameOfDoctor(), "observations.nameOfDoctor", + errors); - if (form.getCenterCode() == null) { - errors.rejectValue("centerCode", "field.error.required"); - } + if (form.getCenterCode() == null) { + errors.rejectValue("centerCode", "field.error.required"); + } - ValidationHelper.validateFieldRequired(form.getObservations().getService(), "observations.service", errors); + ValidationHelper.validateFieldRequired(form.getObservations().getService(), "observations.service", errors); - ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); - ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); - } + } - private void validateFollowUpARVForm(PatientEntryByProjectForm form, Errors errors) { - ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + private void validateFollowUpARVForm(PatientEntryByProjectForm form, Errors errors) { + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); - if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) - && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { - ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); + if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) + && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { + ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); - ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); - } + ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); + } - ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); - if (form.getCenterCode() == null) { - errors.rejectValue("centerCode", "field.error.required"); - } + if (form.getCenterCode() == null) { + errors.rejectValue("centerCode", "field.error.required"); + } - ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); - ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); - } + } - private void validateInitialARVForm(PatientEntryByProjectForm form, Errors errors) { - ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); + private void validateInitialARVForm(PatientEntryByProjectForm form, Errors errors) { + ValidationHelper.validateFieldRequired(form.getReceivedDateForDisplay(), "receivedDateForDisplay", errors); - ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); + ValidationHelper.validateFieldRequired(form.getInterviewDate(), "interviewDate", errors); - if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) - && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { - ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); + if (org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSubjectNumber()) + && org.apache.commons.validator.GenericValidator.isBlankOrNull(form.getSiteSubjectNumber())) { + ValidationHelper.validateFieldRequired(form.getSubjectNumber(), "subjectNumber", errors); - ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); - } + ValidationHelper.validateFieldRequired(form.getSiteSubjectNumber(), "siteSubjectNumber", errors); + } - ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); + ValidationHelper.validateFieldRequired(form.getLabNo(), "labNo", errors); - ValidationHelper.validateFieldRequired(form.getCenterName(), "centerName", errors); + ValidationHelper.validateFieldRequired(form.getCenterName(), "centerName", errors); - if (form.getCenterCode() == null) { - errors.rejectValue("centerCode", "field.error.required"); - } + if (form.getCenterCode() == null) { + errors.rejectValue("centerCode", "field.error.required"); + } - ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); + ValidationHelper.validateFieldRequired(form.getGender(), "gender", errors); - ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); + ValidationHelper.validateFieldRequired(form.getBirthDateForDisplay(), "birthDateForDisplay", errors); - } + } } diff --git a/src/main/java/org/openelisglobal/patient/valueholder/ObservationData.java b/src/main/java/org/openelisglobal/patient/valueholder/ObservationData.java index 8bc9d05368..a43feb7db8 100644 --- a/src/main/java/org/openelisglobal/patient/valueholder/ObservationData.java +++ b/src/main/java/org/openelisglobal/patient/valueholder/ObservationData.java @@ -28,6 +28,7 @@ import org.openelisglobal.common.validator.ValidationHelper; import org.openelisglobal.dictionary.ObservationHistoryList; import org.openelisglobal.dictionary.valueholder.Dictionary; +import org.openelisglobal.resultvalidation.form.ResultValidationForm; import org.openelisglobal.validation.annotations.SafeHtml; import org.openelisglobal.validation.annotations.ValidDate; import org.openelisglobal.validation.annotations.ValidName; @@ -211,7 +212,7 @@ public ObservationData() { private String vlSuckle; @SafeHtml(level = SafeHtml.SafeListLevel.NONE) private String priorVLLab; - @Pattern(regexp = "^[0-9]*$") + @SafeHtml(level = SafeHtml.SafeListLevel.NONE, groups = { ResultValidationForm.ResultValidation.class }) private String priorVLValue; @ValidDate private String priorVLDate; diff --git a/src/main/java/org/openelisglobal/patient/valueholder/Patient.java b/src/main/java/org/openelisglobal/patient/valueholder/Patient.java index 5f2313e8fe..a26b2ef751 100644 --- a/src/main/java/org/openelisglobal/patient/valueholder/Patient.java +++ b/src/main/java/org/openelisglobal/patient/valueholder/Patient.java @@ -68,6 +68,8 @@ public class Patient extends BaseObject { private ValueHolderInterface person; private String externalId; + + private String upidCode; private String selectedPersonId; @@ -287,4 +289,13 @@ public String getFhirUuidAsString() { public void setFhirUuid(UUID fhirUuid) { this.fhirUuid = fhirUuid; } + + public String getUpidCode() { + return upidCode; + } + + public void setUpidCode(String upidCode) { + this.upidCode = upidCode; + } + } \ No newline at end of file diff --git a/src/main/java/org/openelisglobal/program/service/ProgramAutocreateService.java b/src/main/java/org/openelisglobal/program/service/ProgramAutocreateService.java index a6021ba2af..d7c62c1e94 100644 --- a/src/main/java/org/openelisglobal/program/service/ProgramAutocreateService.java +++ b/src/main/java/org/openelisglobal/program/service/ProgramAutocreateService.java @@ -56,6 +56,60 @@ public void autocreateProgram() { if (autocreateOn) { for (Resource programResource : programResources) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(programResource.getInputStream()))) { + reader.mark(100); + String linee = reader.readLine(); + if (linee.startsWith("Test")) { + while ((linee = reader.readLine()) != null) { + String[] lines = linee.split(" "); + UUID uuid = UUID.randomUUID(); + System.out.println( + "\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\n" + // + "\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\n" + // + "\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t \n" + // + "\t\t\t \n" + // + "\t\t\t \n" + // + "\t\t\t \n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t \n" + // + "\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\n" + // + "\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t\t\n" + // + "\t\t" + ); + } + continue; + } else { + reader.reset(); + } + String contents = reader.lines().map(line -> line + "\n").collect(Collectors.joining()); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Hibernate5Module()); @@ -98,6 +152,8 @@ public void autocreateProgram() { questionnaire.setId(program.getQuestionnaireUUID().toString()); fhirPersistanceService.updateFhirResourceInFhirStore(questionnaire); DisplayListService.getInstance().refreshList(ListType.PROGRAM); + + // } } catch (IOException | FhirLocalPersistingException e) { LogEvent.logError(e); diff --git a/src/main/java/org/openelisglobal/program/service/cytology/CytologyDisplayServiceImpl.java b/src/main/java/org/openelisglobal/program/service/cytology/CytologyDisplayServiceImpl.java index 1085906ff8..c8a04a5198 100644 --- a/src/main/java/org/openelisglobal/program/service/cytology/CytologyDisplayServiceImpl.java +++ b/src/main/java/org/openelisglobal/program/service/cytology/CytologyDisplayServiceImpl.java @@ -151,7 +151,9 @@ public CytologyDisplayItem convertToDisplayItem(Integer cytologySampleId) { @Transactional public CytologySample getCytologySampleWithLoadedAttributes(Integer cytologySampleId) { CytologySample cytologySample = cytologySampleService.get(cytologySampleId); - cytologySample.getDiagnosis().getDiagnosisResultsMaps().size(); + if(cytologySample.getDiagnosis() != null){ + cytologySample.getDiagnosis().getDiagnosisResultsMaps().size(); + } return cytologySample; } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ActivityReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/ActivityReport.java index 97c21dfb12..9746bda6bb 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/ActivityReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ActivityReport.java @@ -22,6 +22,8 @@ import java.util.List; import org.apache.commons.validator.GenericValidator; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; import org.openelisglobal.common.util.ConfigurationProperties; import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.common.util.DateUtil; @@ -127,7 +129,11 @@ protected ActivityReportBean createActivityReportBean(Result result, boolean use item.setTechnician(resultService.getSignature(result)); // item.setAccessionNumber(sampleService.getAccessionNumber(sample).substring(PREFIX_LENGTH)); - item.setAccessionNumber(sampleService.getAccessionNumber(sample)); + if (AccessionFormat.ALPHANUM.toString().equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + item.setAccessionNumber(AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(sample))); + }else { + item.setAccessionNumber(sampleService.getAccessionNumber(sample)); + } item.setReceivedDate(sampleService.getReceivedDateWithTwoYearDisplay(sample)); Timestamp start = sample.getReceivedTimestamp(); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ExportStudyProjectByDate.java b/src/main/java/org/openelisglobal/reports/action/implementation/ExportStudyProjectByDate.java index 9be5499354..bb5fa5e131 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/ExportStudyProjectByDate.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ExportStudyProjectByDate.java @@ -25,14 +25,19 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import org.apache.commons.validator.GenericValidator; import org.jfree.util.Log; import org.openelisglobal.internationalization.MessageUtil; import org.openelisglobal.project.service.ProjectService; import org.openelisglobal.project.valueholder.Project; +import org.openelisglobal.reports.action.implementation.reportBeans.ARVFollowupColumnBuilder; +import org.openelisglobal.reports.action.implementation.reportBeans.ARVInitialColumnBuilder; import org.openelisglobal.reports.action.implementation.reportBeans.CIColumnBuilder; import org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder; +import org.openelisglobal.reports.action.implementation.reportBeans.RTNColumnBuilder; +import org.openelisglobal.reports.action.implementation.reportBeans.RTRIColumnBuilder; import org.openelisglobal.reports.action.implementation.reportBeans.StudyEIDColumnBuilder; import org.openelisglobal.reports.action.implementation.reportBeans.StudyVLColumnBuilder; import org.openelisglobal.reports.form.ReportForm; @@ -180,10 +185,20 @@ protected void writeConsolidatedBaseToBuffer(ByteArrayOutputStream buffer, Strin private CSVColumnBuilder getColumnBuilder(String projectId) { String projectTag = CIColumnBuilder.translateProjectId(projectId); - if (projectTag.equalsIgnoreCase("DBS")) { + if (projectTag.equals("ARVB")) { + return new ARVInitialColumnBuilder(dateRange, projectStr); + } else if (projectTag.equals("ARVS")) { + return new ARVFollowupColumnBuilder(dateRange, projectStr); + } else if (projectTag.equalsIgnoreCase("DBS")) { return new StudyEIDColumnBuilder(dateRange, projectStr, dateType); } else if (projectTag.equalsIgnoreCase("VLS")) { return new StudyVLColumnBuilder(dateRange, projectStr, dateType); + }else if (projectTag.equalsIgnoreCase("RTN")) { + return new RTNColumnBuilder(dateRange, projectStr); + } else if (projectTag.equalsIgnoreCase("IND")) { + return new RTNColumnBuilder(dateRange, projectStr); + }else if (projectTag.equalsIgnoreCase("RTRI")) { + return new RTRIColumnBuilder(dateRange, projectStr, dateType); } throw new IllegalArgumentException(); } @@ -194,10 +209,20 @@ private CSVColumnBuilder getColumnBuilder(String projectId) { protected List getProjectList() { List projects = new ArrayList<>(); Project project = new Project(); + project.setProjectName("Antiretroviral Study"); + projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); + project.setProjectName("Antiretroviral Followup Study"); + projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); + project.setProjectName("Routine HIV Testing"); project.setProjectName("Early Infant Diagnosis for HIV Study"); projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); project.setProjectName("Viral Load Results"); projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); + project.setProjectName("Indeterminate Results"); + projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); + project.setProjectName("Recency Testing"); + projects.add(SpringContext.getBean(ProjectService.class).getProjectByName(project, false, false)); + projects.removeIf(Objects::isNull); return projects; } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ExportTBOrdersByDate.java b/src/main/java/org/openelisglobal/reports/action/implementation/ExportTBOrdersByDate.java new file mode 100644 index 0000000000..916462bc24 --- /dev/null +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ExportTBOrdersByDate.java @@ -0,0 +1,157 @@ +/** + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations under + * the License. + * + * The Original Code is OpenELIS code. + * + * Copyright (C) CIRG, University of Washington, Seattle WA. All Rights Reserved. + * + */ +package org.openelisglobal.reports.action.implementation; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.sql.SQLException; +import java.text.ParseException; + +import org.apache.commons.validator.GenericValidator; +import org.jfree.util.Log; +import org.openelisglobal.common.util.StringUtil; +import org.openelisglobal.internationalization.MessageUtil; +import org.openelisglobal.project.service.ProjectService; +import org.openelisglobal.reports.action.implementation.reportBeans.RoutineColumnBuilder; +import org.openelisglobal.reports.action.implementation.reportBeans.TBColumnBuilder; +import org.openelisglobal.reports.form.ReportForm; +import org.openelisglobal.spring.util.SpringContext; + +/** + * @author Paul A. Hill (pahill@uw.edu) + * @since Jan 26, 2011 + */ +public class ExportTBOrdersByDate extends CSVRoutineSampleExportReport + implements IReportParameterSetter, IReportCreator { + protected final ProjectService projectService = SpringContext.getBean(ProjectService.class); + + @Override + protected String reportFileName() { + return "ExportTBOrdersByDate"; + } + + @Override + public void setRequestParameters(ReportForm form) { + try { + form.setReportName(getReportNameForParameterPage()); + form.setUseLowerDateRange(Boolean.TRUE); + form.setUseUpperDateRange(Boolean.TRUE); + } catch (RuntimeException e) { + Log.error("Error in ExportTBOrdersByDate.setRequestParemeters: ", e); + } + } + + protected String getReportNameForParameterPage() { + return MessageUtil.getMessage("reports.label.project.export") + " " + + MessageUtil.getContextualMessage("sample.collectionDate"); + } + + @Override + public void initializeReport(ReportForm form) { + super.initializeReport(); + errorFound = false; + + lowDateStr = form.getLowerDateRange(); + highDateStr = form.getUpperDateRange(); + dateRange = new DateRange(lowDateStr, highDateStr); + + createReportParameters(); + + errorFound = !validateSubmitParameters(); + if (errorFound) { + return; + } + + createReportItems(); + } + + /** + * check everything + */ +//----------------------------------- + private boolean validateSubmitParameters() { + return dateRange.validateHighLowDate("report.error.message.date.received.missing"); + } + + + /** + * creating the list for generation to the report + */ + private void createReportItems() { + try { + csvRoutineColumnBuilder = getColumnBuilder(); + csvRoutineColumnBuilder.buildDataSource(); + } catch (SQLException e) { + Log.error("Error in " + this.getClass().getSimpleName() + ".createReportItems: ", e); + add1LineErrorMessage("report.error.message.general.error"); + } + } + + @Override + protected void writeResultsToBuffer(ByteArrayOutputStream buffer) + throws IOException, UnsupportedEncodingException, SQLException, ParseException { + + String currentAccessionNumber = null; + String[] splitBase = null; + while (csvRoutineColumnBuilder.next()) { + String line = csvRoutineColumnBuilder.nextLine(); + String[] splitLine = StringUtil.separateCSVWithMixedEmbededQuotes(line); + + if (splitLine[0].equals(currentAccessionNumber)) { + merge(splitBase, splitLine); + } else { + if (currentAccessionNumber != null) { + writeConsolidatedBaseToBuffer(buffer, splitBase); + } + splitBase = splitLine; + currentAccessionNumber = splitBase[0]; + } + } + + writeConsolidatedBaseToBuffer(buffer, splitBase); + } + + private void merge(String[] base, String[] line) { + for (int i = 0; i < base.length; ++i) { + if (GenericValidator.isBlankOrNull(base[i])) { + base[i] = line[i]; + } + } + } + + protected void writeConsolidatedBaseToBuffer(ByteArrayOutputStream buffer, String[] splitBase) + throws IOException, UnsupportedEncodingException { + + if (splitBase != null) { + StringBuffer consolidatedLine = new StringBuffer(); + for (String value : splitBase) { + consolidatedLine.append(value); + consolidatedLine.append(","); + } + + consolidatedLine.deleteCharAt(consolidatedLine.lastIndexOf(",")); + buffer.write(consolidatedLine.toString().getBytes("windows-1252")); + } + } + + private RoutineColumnBuilder getColumnBuilder() { + return new TBColumnBuilder(dateRange); + + } + +} diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ExportTrendsByDate.java b/src/main/java/org/openelisglobal/reports/action/implementation/ExportTrendsByDate.java index ec6ecf6336..e5628b4936 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/ExportTrendsByDate.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ExportTrendsByDate.java @@ -173,13 +173,13 @@ private boolean writeAble(String result) throws ParseException { String indic = splitLine[1]; if (indic.equals("Unsuppressed VL")) { return workingResult.contains("Log7") || !workingResult.contains("L") && !workingResult.contains("X") - && !workingResult.contains("<") && !workingResult.contains(">") && workingResult.length() > 0 - && Double.parseDouble(workingResult) >= 1000; + && !workingResult.contains("<") && workingResult.length() > 0 + && Double.parseDouble(workingResult.replaceAll("[^0-9]", "")) >= 1000; } else if (indic.equals("Suppressed VL")) { return workingResult.contains("L") || workingResult.contains("<") || (workingResult.length() > 0 && !workingResult.toUpperCase().contains("X") && !workingResult.toLowerCase().contains("invalid") - && Double.parseDouble(workingResult) < 1000); + && Double.parseDouble(workingResult.replaceAll("[^0-9]", "")) < 1000); } return false; diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/HaitiLNSPExportReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/HaitiLNSPExportReport.java index 4786327b22..c7fbda4477 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/HaitiLNSPExportReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/HaitiLNSPExportReport.java @@ -251,7 +251,7 @@ private void setAppropriateResults(List resultList, Analysis analysis, T String reportResult = resultResultService.getResultValue(result, true); Result quantifiableResult = analysisService.getQuantifiedResult(analysis); if (quantifiableResult != null) { - reportResult += ":" + quantifiableResult.getValue(true); + reportResult += ":" + quantifiableResult.getValue(); } data.setResult(reportResult.replace(",", ";")); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/NonConformityByDate.java b/src/main/java/org/openelisglobal/reports/action/implementation/NonConformityByDate.java index 2dc13f9459..30d1039a9d 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/NonConformityByDate.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/NonConformityByDate.java @@ -21,6 +21,8 @@ import java.util.Comparator; import java.util.List; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.QAService; import org.openelisglobal.common.services.QAService.QAObservationType; import org.openelisglobal.common.services.TableIdService; @@ -121,7 +123,13 @@ private void createReportItems() { String noteForSample = NonConformityHelper.getNoteForSample(sample); NonConformityReportData data = new NonConformityReportData(); - data.setAccessionNumber(sample.getAccessionNumber()); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + data.setAccessionNumber( + AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(sample.getAccessionNumber())); + } else { + data.setAccessionNumber(sample.getAccessionNumber()); + } data.setSubjectNumber(patient.getNationalId()); data.setSiteSubjectNumber(patient.getExternalId()); data.setStudy((project != null) ? project.getLocalizedName() : ""); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientARVReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientARVReport.java index 13573c9908..ae394e872c 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientARVReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientARVReport.java @@ -144,16 +144,16 @@ protected void setTestInfo(ARVReportData data) { data.setShowSerologie(Boolean.TRUE); } else if (result.getAnalyte() != null && result.getAnalyte().getId().equals(CD4_CNT_CONCLUSION)) { - data.setCd4(valid ? result.getValue(true) : invalidValue); + data.setCd4(valid ? result.getValue() : invalidValue); } else { - resultValue = result.getValue(true); + resultValue = result.getValue(); } } } if (resultList.size() > 0) { if (resultValue == null) { - resultValue = resultList.get(resultList.size() - 1).getValue(true); + resultValue = resultList.get(resultList.size() - 1).getValue(); } } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientCILNSPClinical_vreduit.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientCILNSPClinical_vreduit.java index b16af89a7b..eff72f3e44 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientCILNSPClinical_vreduit.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientCILNSPClinical_vreduit.java @@ -28,6 +28,8 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.valueholder.Analysis; import org.openelisglobal.common.constants.Constants; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.StatusService.AnalysisStatus; import org.openelisglobal.common.util.ConfigurationProperties; @@ -129,8 +131,9 @@ protected void createReportItems() { boolean isConfirmationSample = sampleService.isConfirmationSample(currentSample); List analysisList = analysisService .getAnalysesBySampleIdAndStatusId(sampleService.getId(currentSample), analysisStatusIds); - - List filteredAnalysisList = userService.filterAnalysesByLabUnitRoles(systemUserId, analysisList, Constants.ROLE_REPORTS); + + List filteredAnalysisList = userService.filterAnalysesByLabUnitRoles(systemUserId, analysisList, + Constants.ROLE_REPORTS); List currentSampleReportItems = new ArrayList<>(filteredAnalysisList.size()); currentConclusion = null; for (Analysis analysis : filteredAnalysisList) { @@ -270,8 +273,14 @@ private void copyParentData(ClinicalPatientData data, ClinicalPatientData parent data.setDept(parentData.getDept()); data.setCommune(parentData.getCommune()); data.setStNumber(parentData.getStNumber()); - data.setAccessionNumber(parentData.getAccessionNumber()); data.setLabOrderType(parentData.getLabOrderType()); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + data.setAccessionNumber( + AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(parentData.getAccessionNumber())); + } else { + data.setAccessionNumber(parentData.getAccessionNumber()); + } } @Override @@ -329,25 +338,28 @@ public int compare(ClinicalPatientData o1, ClinicalPatientData o2) { } }); -// ArrayList augmentedList = new ArrayList<>(reportItems.size()); -// HashSet parentResults = new HashSet<>(); -// for (ClinicalPatientData data : reportItems) { -// if (data.getParentResult() != null && !parentResults.contains(data.getParentResult().getId())) { -// parentResults.add(data.getParentResult().getId()); -// ClinicalPatientData marker = new ClinicalPatientData(data); -// ResultService resultResultService = SpringContext.getBean(ResultService.class); -// Result result = (data.getParentResult()); -// marker.setTestName(resultResultService.getSimpleResultValue(result)); -// marker.setResult(null); -// marker.setTestRefRange(null); -// marker.setParentMarker(true); -// augmentedList.add(marker); -// } -// -// augmentedList.add(data); -// } -// -// reportItems = augmentedList; + // ArrayList augmentedList = new + // ArrayList<>(reportItems.size()); + // HashSet parentResults = new HashSet<>(); + // for (ClinicalPatientData data : reportItems) { + // if (data.getParentResult() != null && + // !parentResults.contains(data.getParentResult().getId())) { + // parentResults.add(data.getParentResult().getId()); + // ClinicalPatientData marker = new ClinicalPatientData(data); + // ResultService resultResultService = + // SpringContext.getBean(ResultService.class); + // Result result = (data.getParentResult()); + // marker.setTestName(resultResultService.getSimpleResultValue(result)); + // marker.setResult(null); + // marker.setTestRefRange(null); + // marker.setParentMarker(true); + // augmentedList.add(marker); + // } + // + // augmentedList.add(data); + // } + // + // reportItems = augmentedList; String currentPanelId = null; for (ClinicalPatientData reportItem : reportItems) { diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientClinicalReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientClinicalReport.java index 554e19e4f1..506b34f617 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientClinicalReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientClinicalReport.java @@ -26,8 +26,12 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.valueholder.Analysis; import org.openelisglobal.common.constants.Constants; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.StatusService.AnalysisStatus; +import org.openelisglobal.common.util.ConfigurationProperties; +import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.internationalization.MessageUtil; import org.openelisglobal.note.service.NoteService; import org.openelisglobal.referral.valueholder.Referral; @@ -88,7 +92,8 @@ protected void createReportItems() { List analysisList = analysisService .getAnalysesBySampleIdAndStatusId(sampleService.getId(currentSample), analysisStatusIds); - List filteredAnalysisList = userService.filterAnalysesByLabUnitRoles(systemUserId, analysisList, Constants.ROLE_REPORTS); + List filteredAnalysisList = userService.filterAnalysesByLabUnitRoles(systemUserId, analysisList, + Constants.ROLE_REPORTS); currentConclusion = null; Set sampleSet = new HashSet<>(); List currentSampleReportItems = new ArrayList<>(filteredAnalysisList.size()); @@ -298,7 +303,14 @@ public int compare(ClinicalPatientData o1, ClinicalPatientData o2) { reportItem.setSeparator(true); } - reportItem.setAccessionNumber(reportItem.getAccessionNumber().split("-")[0]); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + reportItem.setAccessionNumber( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(reportItem.getAccessionNumber().split("-")[0])); + } else { + reportItem.setAccessionNumber(reportItem.getAccessionNumber().split("-")[0]); + } reportItem.setCompleteFlag(MessageUtil .getMessage(sampleCompleteMap.get(reportItem.getAccessionNumber()) ? "report.status.complete" : "report.status.partial")); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientEIDReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientEIDReport.java index 5d05a2554a..ebbcb807d1 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientEIDReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientEIDReport.java @@ -8,10 +8,14 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.service.AnalysisService; import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.IReportTrackingService; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.ReportTrackingService; import org.openelisglobal.common.services.StatusService.AnalysisStatus; +import org.openelisglobal.common.util.ConfigurationProperties; +import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.dictionary.service.DictionaryService; import org.openelisglobal.dictionary.valueholder.Dictionary; @@ -105,7 +109,7 @@ protected void setTestInfo(EIDReportData data) { if (valid) { String resultValue = ""; if (resultList.size() > 0) { - resultValue = resultList.get(resultList.size() - 1).getValue(true); + resultValue = resultList.get(resultList.size() - 1).getValue(); } Dictionary dictionary = new Dictionary(); dictionary.setId(resultValue); @@ -151,7 +155,13 @@ protected void setPatientInfo(EIDReportData data) { orgService.getDataBySample(sampleOrg); data.setServicename(sampleOrg.getId() == null ? "" : sampleOrg.getOrganization().getOrganizationName()); data.setDoctor(getObservationValues(OBSERVATION_REQUESTOR_ID)); - data.setAccession_number(reportSample.getAccessionNumber()); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + data.setAccessionNumber( + AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(reportSample.getAccessionNumber())); + } else { + data.setAccessionNumber(reportSample.getAccessionNumber()); + } data.setReceptiondate(DateUtil.convertTimestampToStringDateAndTime(reportSample.getReceivedTimestamp())); Timestamp collectionDate = reportSample.getCollectionDate(); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientProgramReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientProgramReport.java index c7d0c59de3..f7285956f5 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientProgramReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientProgramReport.java @@ -22,6 +22,8 @@ import org.openelisglobal.analysis.valueholder.Analysis; import org.openelisglobal.common.formfields.FormFields; import org.openelisglobal.common.formfields.FormFields.Field; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.StatusService.AnalysisStatus; import org.openelisglobal.common.services.TableIdService; @@ -66,116 +68,123 @@ import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; public abstract class PatientProgramReport extends Report implements IReportCreator { - + private ImageService imageService = SpringContext.getBean(ImageService.class); - + protected PathologySampleService pathologySerivice = SpringContext.getBean(PathologySampleService.class); - + protected PatientService patientService = SpringContext.getBean(PatientService.class); - + private static final String configName = ConfigurationProperties.getInstance() .getPropertyValue(Property.configurationName); - + protected SampleService sampleService = SpringContext.getBean(SampleService.class); - + protected SampleHumanService sampleHumanService = SpringContext.getBean(SampleHumanService.class); - + protected AddressPartService addressPartService = SpringContext.getBean(AddressPartService.class); - + protected OrganizationService organizationService = SpringContext.getBean(OrganizationService.class); - + protected DictionaryService dictionaryService = SpringContext.getBean(DictionaryService.class); - + protected PersonAddressService addressService = SpringContext.getBean(PersonAddressService.class); - + protected ProviderService providerService = SpringContext.getBean(ProviderService.class); - + protected AnalysisService analysisService = SpringContext.getBean(AnalysisService.class); - + protected TestService testService = SpringContext.getBean(TestService.class); - + private static String ADDRESS_DEPT_ID; - + private static String ADDRESS_COMMUNE_ID; - + protected String currentContactInfo = ""; - + protected String currentSiteInfo = ""; - + protected String STNumber = null; - + protected String subjectNumber = null; - + protected String healthRegion = null; - + protected String healthDistrict = null; - + protected String patientName = null; - + protected String patientDOB = null; - + protected String currentConclusion = null; - + protected String patientDept = null; - + protected String patientCommune = null; - + protected Provider currentProvider; - + protected Analysis currentAnalysis = null; - + protected String reportReferralResultValue; - + protected String completionDate; - + protected Patient patient; - + protected Sample sample; - + protected List reportItems; - + protected List analyses; - + protected ProgramSampleReportData data; - + protected ReportForm form; - + protected static Set analysisStatusIds; - + static { analysisStatusIds = new HashSet<>(); analysisStatusIds.add( - Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.BiologistRejected))); + Integer.parseInt( + SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.BiologistRejected))); analysisStatusIds - .add(Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Finalized))); + .add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Finalized))); analysisStatusIds.add(Integer - .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NonConforming_depricated))); + .parseInt(SpringContext.getBean(IStatusService.class) + .getStatusID(AnalysisStatus.NonConforming_depricated))); analysisStatusIds - .add(Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted))); + .add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted))); analysisStatusIds.add( - Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalAcceptance))); + Integer.parseInt( + SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalAcceptance))); analysisStatusIds - .add(Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Canceled))); + .add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Canceled))); analysisStatusIds.add( - Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalRejected))); - + Integer.parseInt( + SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalRejected))); + } - + abstract protected String getReportName(); - + abstract protected void setAdditionalReportItems(); - + abstract protected void innitializeSample(ReportForm form); - + @Override protected String reportFileName() { return getReportName(); } - + protected String getHeaderName() { return "CDIHeader.jasper"; } - + @PostConstruct private void initialize() { List partList = addressPartService.getAll(); @@ -187,7 +196,7 @@ private void initialize() { } } } - + @Override public void initializeReport(ReportForm form) { this.form = form; @@ -208,46 +217,49 @@ public void initializeReport(ReportForm form) { findPatientInfo(); createReportItems(); } - + protected void createReportItems() { reportItems.add(buildClinicalPatientData()); } - + @Override public JRDataSource getReportDataSource() throws IllegalStateException { if (!initialized) { throw new IllegalStateException("initializeReport not called first"); } - + return errorFound ? new JRBeanCollectionDataSource(errorMsgs) : new JRBeanCollectionDataSource(reportItems); } - + @Override protected void createReportParameters() { super.createReportParameters(); reportParameters.put("siteId", ConfigurationProperties.getInstance().getPropertyValue(Property.SiteCode)); reportParameters.put("headerName", getHeaderName()); - reportParameters.put("billingNumberLabel", SpringContext.getBean(LocalizationService.class).getLocalizedValueById( - ConfigurationProperties.getInstance().getPropertyValue(Property.BILLING_REFERENCE_NUMBER_LABEL))); + reportParameters.put("billingNumberLabel", + SpringContext.getBean(LocalizationService.class).getLocalizedValueById( + ConfigurationProperties.getInstance() + .getPropertyValue(Property.BILLING_REFERENCE_NUMBER_LABEL))); reportParameters.put("footerName", getFooterName()); Optional labDirectorSignature = imageService.getImageBySiteInfoName("labDirectorSignature"); reportParameters.put("useLabDirectorSignature", labDirectorSignature.isPresent()); if (labDirectorSignature.isPresent()) { - reportParameters.put("labDirectorSignature", new ByteArrayInputStream(labDirectorSignature.get().getImage())); + reportParameters.put("labDirectorSignature", + new ByteArrayInputStream(labDirectorSignature.get().getImage())); } - + reportParameters.put("labDirectorName", - ConfigurationProperties.getInstance().getPropertyValue(Property.LAB_DIRECTOR_NAME)); + ConfigurationProperties.getInstance().getPropertyValue(Property.LAB_DIRECTOR_NAME)); reportParameters.put("labDirectorTitle", - ConfigurationProperties.getInstance().getPropertyValue(Property.LAB_DIRECTOR_TITLE)); + ConfigurationProperties.getInstance().getPropertyValue(Property.LAB_DIRECTOR_TITLE)); createExtraReportParameters(); - + } - + protected void createExtraReportParameters() { - + } - + private Object getFooterName() { if (configName.equals("CI IPCI") || configName.equals("CI LNSP")) { return "CILNSPFooter.jasper"; @@ -255,70 +267,70 @@ private Object getFooterName() { return ""; } } - + protected void initializeReportItems() { reportItems = new ArrayList<>(); } - + private void findCompletionDate() { Date date = sampleService.getCompletedDate(sample); completionDate = date == null ? null : DateUtil.convertSqlDateToStringDate(date); } - + protected void findPatientFromSample() { patient = sampleHumanService.getPatientForSample(sample); } - + private void findPatientInfo() { if (patientService.getPerson(patient) == null) { return; } - + patientDept = ""; patientCommune = ""; if (ADDRESS_DEPT_ID != null) { PersonAddress deptAddress = addressService.getByPersonIdAndPartId(patientService.getPerson(patient).getId(), - ADDRESS_DEPT_ID); - + ADDRESS_DEPT_ID); + if (deptAddress != null && !GenericValidator.isBlankOrNull(deptAddress.getValue())) { patientDept = dictionaryService.getDictionaryById(deptAddress.getValue()).getDictEntry(); } } - + if (ADDRESS_COMMUNE_ID != null) { PersonAddress deptAddress = addressService.getByPersonIdAndPartId(patientService.getPerson(patient).getId(), - ADDRESS_COMMUNE_ID); - + ADDRESS_COMMUNE_ID); + if (deptAddress != null) { patientCommune = deptAddress.getValue(); } } - + } - + private void findContactInfo() { currentContactInfo = ""; currentSiteInfo = ""; currentProvider = null; - - // sampleService.getOrganizationRequester(currentSample); + + // sampleService.getOrganizationRequester(currentSample); Organization referringOrg = sampleService.getOrganizationRequester(sample, - TableIdService.getInstance().REFERRING_ORG_TYPE_ID); + TableIdService.getInstance().REFERRING_ORG_TYPE_ID); Organization referringDepartmentOrg = sampleService.getOrganizationRequester(sample, - TableIdService.getInstance().REFERRING_ORG_DEPARTMENT_TYPE_ID); - + TableIdService.getInstance().REFERRING_ORG_DEPARTMENT_TYPE_ID); + currentSiteInfo += referringOrg == null ? "" : referringOrg.getOrganizationName(); currentSiteInfo += "|" + (referringDepartmentOrg == null ? "" : referringDepartmentOrg.getOrganizationName()); - + Person person = sampleService.getPersonRequester(sample); if (person != null) { PersonService personService = SpringContext.getBean(PersonService.class); currentContactInfo = personService.getLastFirstName(person); currentProvider = providerService.getProviderByPerson(person); } - + } - + protected ProgramSampleReportData buildClinicalPatientData() { data = new ProgramSampleReportData(); String testName = currentAnalysis != null @@ -330,13 +342,13 @@ protected ProgramSampleReportData buildClinicalPatientData() { String orderDateForDisplay = orderDate != null ? DateUtil.convertTimestampToStringDateAndConfiguredHourTime(orderDate) : ""; - + if (FormFields.getInstance().useField(Field.SampleEntryUseReceptionHour)) { receivedDate += " " + sampleService.getReceivedTimeForDisplay(sample); } ObservationHistoryService observationHistoryService = SpringContext.getBean(ObservationHistoryService.class); data.setSampleType( - currentAnalysis != null ? analysisService.getTypeOfSample(currentAnalysis).getLocalizedName() : ""); + currentAnalysis != null ? analysisService.getTypeOfSample(currentAnalysis).getLocalizedName() : ""); Set sampleSet = new HashSet<>(); if (analyses != null) { analyses.forEach(analysis -> { @@ -356,35 +368,49 @@ protected ProgramSampleReportData buildClinicalPatientData() { data.setCommune(patientCommune); data.setStNumber(getLazyPatientIdentity(patient, STNumber, PatientServiceImpl.getPatientSTIdentity())); data.setSubjectNumber( - getLazyPatientIdentity(patient, subjectNumber, PatientServiceImpl.getPatientSubjectIdentity())); + getLazyPatientIdentity(patient, subjectNumber, PatientServiceImpl.getPatientSubjectIdentity())); data.setHealthRegion( - getLazyPatientIdentity(patient, healthRegion, PatientServiceImpl.getPatientHealthRegionIdentity())); + getLazyPatientIdentity(patient, healthRegion, PatientServiceImpl.getPatientHealthRegionIdentity())); data.setHealthDistrict( - getLazyPatientIdentity(patient, healthDistrict, PatientServiceImpl.getPatientHealthDistrictIdentity())); - + getLazyPatientIdentity(patient, healthDistrict, PatientServiceImpl.getPatientHealthDistrictIdentity())); + data.setLabOrderType( - observationHistoryService.getValueForSample(ObservationType.PROGRAM, sampleService.getId(sample))); + observationHistoryService.getValueForSample(ObservationType.PROGRAM, sampleService.getId(sample))); data.setTestName(testName); data.setPatientSiteNumber( - observationHistoryService.getValueForSample(ObservationType.REFERRERS_PATIENT_ID, sampleService.getId(sample))); + observationHistoryService.getValueForSample(ObservationType.REFERRERS_PATIENT_ID, + sampleService.getId(sample))); data.setBillingNumber(observationHistoryService.getValueForSample(ObservationType.BILLING_REFERENCE_NUMBER, - sampleService.getId(sample))); + sampleService.getId(sample))); data.setOrderDate(orderDateForDisplay); data.setSampleSortOrder(currentAnalysis != null ? currentAnalysis.getSampleItem().getSortOrder() : ""); - data.setSampleId(sampleService.getAccessionNumber(sample) + "-" + data.getSampleSortOrder()); - data.setAccessionNumber(sampleService.getAccessionNumber(sample) + "-" + data.getSampleSortOrder()); - + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + data.setSampleId( + AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(sample)) + + "-" + data.getSampleSortOrder()); + data.setAccessionNumber( + AlphanumAccessionValidator.convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(sample)) + + "-" + data.getSampleSortOrder()); + } else { + data.setSampleId(sampleService.getAccessionNumber(sample) + "-" + data.getSampleSortOrder()); + + data.setAccessionNumber(sampleService.getAccessionNumber(sample) + "-" + data.getSampleSortOrder()); + } + if (Boolean.valueOf(ConfigurationProperties.getInstance().getPropertyValue(Property.CONTACT_TRACING))) { data.setContactTracingIndexName(sampleService.getSampleAdditionalFieldForSample(sampleService.getId(sample), - AdditionalFieldName.CONTACT_TRACING_INDEX_NAME).getFieldValue()); + AdditionalFieldName.CONTACT_TRACING_INDEX_NAME).getFieldValue()); data.setContactTracingIndexRecordNumber(sampleService.getSampleAdditionalFieldForSample( - sampleService.getId(sample), AdditionalFieldName.CONTACT_TRACING_INDEX_RECORD_NUMBER).getFieldValue()); + sampleService.getId(sample), AdditionalFieldName.CONTACT_TRACING_INDEX_RECORD_NUMBER) + .getFieldValue()); } setAdditionalReportItems(); return data; } - - protected void setCollectionTime(Set sampleSet, ProgramSampleReportData data, boolean addAccessionNumber) { + + protected void setCollectionTime(Set sampleSet, ProgramSampleReportData data, + boolean addAccessionNumber) { StringBuilder buffer = new StringBuilder(); boolean firstItem = true; for (SampleItem sampleItem : sampleSet) { @@ -393,7 +419,7 @@ protected void setCollectionTime(Set sampleSet, ProgramSampleReportD } else { buffer.append(", "); } - + buffer.append(sampleItem.getTypeOfSample().getLocalizedName()); if (addAccessionNumber) { buffer.append(" "); @@ -404,21 +430,22 @@ protected void setCollectionTime(Set sampleSet, ProgramSampleReportD buffer.append(MessageUtil.getMessage("label.not.available")); } else { buffer.append(" "); - buffer.append(DateUtil.convertTimestampToStringDateAndConfiguredHourTime(sampleItem.getCollectionDate())); + buffer.append( + DateUtil.convertTimestampToStringDateAndConfiguredHourTime(sampleItem.getCollectionDate())); } } - + String collectionTimes = buffer.toString(); - + data.setCollectionDateTime(collectionTimes); - + } - + private String createReadableAge(String dob) { if (GenericValidator.isBlankOrNull(dob)) { return ""; } - + dob = dob.replaceAll(DateUtil.AMBIGUOUS_DATE_SEGMENT, "01"); Date dobDate = DateUtil.convertStringDateToSqlDate(dob); int months = DateUtil.getAgeInMonths(dobDate, DateUtil.getNowAsSqlDate()); @@ -430,27 +457,27 @@ private String createReadableAge(String dob) { int days = DateUtil.getAgeInDays(dobDate, DateUtil.getNowAsSqlDate()); return days + " " + MessageUtil.getMessage("abbreviation.day.single"); } - + } - + protected String getPatientDOB(Patient patient) { if (patientDOB == null) { patientDOB = patientService.getBirthdayForDisplay(patient); } - + return patientDOB; } - + protected void setPatientName(ProgramSampleReportData data) { data.setPatientName(patientService.getLastFirstName(patient)); data.setFirstName(patientService.getFirstName(patient)); data.setLastName(patientService.getLastName(patient)); } - + protected String getUnitOfMeasure(Test test) { return (test != null && test.getUnitOfMeasure() != null) ? test.getUnitOfMeasure().getName() : ""; } - + protected String getLazyPatientIdentity(Patient patient, String identity, String id) { if (identity == null) { identity = " "; @@ -462,14 +489,14 @@ protected String getLazyPatientIdentity(Patient patient, String identity, String } } } - + return identity; } - + protected String getAppropriateResults(List resultList) { String reportResult = ""; if (!resultList.isEmpty()) { - + // If only one result just get it and get out if (resultList.size() == 1) { Result result = resultList.get(0); @@ -477,7 +504,7 @@ protected String getAppropriateResults(List resultList) { Dictionary dictionary = new Dictionary(); dictionary.setId(result.getValue()); dictionaryService.getData(dictionary); - + if (result.getAnalyte() != null && "Conclusion".equals(result.getAnalyte().getAnalyteName())) { currentConclusion = dictionary.getId() != null ? dictionary.getLocalizedName() : ""; } else { @@ -486,7 +513,7 @@ protected String getAppropriateResults(List resultList) { } else { ResultService resultResultService = SpringContext.getBean(ResultService.class); reportResult = resultResultService.getResultValue(result, true); - + } } else { // If multiple results it can be a quantified result, multiple @@ -494,8 +521,9 @@ protected String getAppropriateResults(List resultList) { // conclusion ResultService resultResultService = SpringContext.getBean(ResultService.class); Result result = resultList.get(0); - - if (TypeOfTestResultServiceImpl.ResultType.DICTIONARY.matches(resultResultService.getTestType(result))) { + + if (TypeOfTestResultServiceImpl.ResultType.DICTIONARY + .matches(resultResultService.getTestType(result))) { // data.setAbnormalResult(resultResultService.isAbnormalDictionaryResult(result)); List dictionaryResults = new ArrayList<>(); Result quantification = null; @@ -507,12 +535,13 @@ protected String getAppropriateResults(List resultList) { quantification = sibResult; } } - + Dictionary dictionary = new Dictionary(); for (Result sibResult : dictionaryResults) { dictionary.setId(sibResult.getValue()); dictionaryService.getData(dictionary); - if (sibResult.getAnalyte() != null && "Conclusion".equals(sibResult.getAnalyte().getAnalyteName())) { + if (sibResult.getAnalyte() != null + && "Conclusion".equals(sibResult.getAnalyte().getAnalyteName())) { currentConclusion = dictionary.getId() != null ? dictionary.getLocalizedName() : ""; } else { reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : ""; @@ -526,9 +555,9 @@ protected String getAppropriateResults(List resultList) { .isMultiSelectVariant(resultResultService.getTestType(result))) { Dictionary dictionary = new Dictionary(); StringBuilder multiResult = new StringBuilder(); - + Collections.sort(resultList, new Comparator() { - + @Override public int compare(Result o1, Result o2) { if (o1.getGrouping() == o2.getGrouping()) { @@ -538,7 +567,7 @@ public int compare(Result o1, Result o2) { } } }); - + Result quantifiedResult = null; for (Result subResult : resultList) { if (TypeOfTestResultServiceImpl.ResultType.ALPHA.matches(subResult.getResultType())) { @@ -555,7 +584,7 @@ public int compare(Result o1, Result o2) { } dictionary.setId(subResult.getValue()); dictionaryService.getData(dictionary); - + if (dictionary.getId() != null) { multiResult.append(dictionary.getLocalizedName()); if (quantifiedResult != null @@ -567,18 +596,18 @@ public int compare(Result o1, Result o2) { multiResult.append("\n"); } } - + if (multiResult.length() > 1) { // remove last "\n" multiResult.setLength(multiResult.length() - 1); } - + reportResult = multiResult.toString(); } } } return reportResult; - + } - + } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientReport.java index a1f918bbbd..8281055d1a 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientReport.java @@ -43,6 +43,8 @@ import org.openelisglobal.common.formfields.FormFields; import org.openelisglobal.common.formfields.FormFields.Field; import org.openelisglobal.common.log.LogEvent; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.provider.validation.IAccessionNumberValidator; import org.openelisglobal.common.services.DisplayListService; import org.openelisglobal.common.services.IStatusService; @@ -87,6 +89,7 @@ import org.openelisglobal.sample.valueholder.SampleAdditionalField.AdditionalFieldName; import org.openelisglobal.samplehuman.service.SampleHumanService; import org.openelisglobal.sampleitem.valueholder.SampleItem; +import org.openelisglobal.sampleorganization.service.SampleOrganizationService; import org.openelisglobal.spring.util.SpringContext; import org.openelisglobal.systemuser.service.UserService; import org.openelisglobal.test.service.TestService; @@ -102,7 +105,7 @@ public abstract class PatientReport extends Report { private static String ADDRESS_DEPT_ID; private static String ADDRESS_COMMUNE_ID; protected String currentContactInfo = ""; - protected String currentSiteInfo = ""; + protected String currentSiteInfo = ""; protected SampleHumanService sampleHumanService = SpringContext.getBean(SampleHumanService.class); protected DictionaryService dictionaryService = SpringContext.getBean(DictionaryService.class); @@ -120,6 +123,7 @@ public abstract class PatientReport extends Report { protected PersonAddressService addressService = SpringContext.getBean(PersonAddressService.class); protected AddressPartService addressPartService = SpringContext.getBean(AddressPartService.class); protected OrganizationService organizationService = SpringContext.getBean(OrganizationService.class); + protected SampleOrganizationService sampleOrganizationService = SpringContext.getBean(SampleOrganizationService.class); protected UserService userService = SpringContext.getBean(UserService.class);; private List handledOrders; private List updatedAnalysis = new ArrayList<>(); @@ -273,9 +277,9 @@ public void initializeReport(ReportForm form) { if (!updatedAnalysis.isEmpty()) { try { analysisService.updateAllNoAuditTrail(updatedAnalysis); -// for (Analysis analysis : updatedAnalysis) { -// analysisService.update(analysis, true); -// } + // for (Analysis analysis : updatedAnalysis) { + // analysisService.update(analysis, true); + // } } catch (LIMSRuntimeException e) { LogEvent.logError(e); @@ -362,7 +366,7 @@ private void findContactInfo() { currentSiteInfo = ""; currentProvider = null; -// sampleService.getOrganizationRequester(currentSample); + // sampleService.getOrganizationRequester(currentSample); Organization referringOrg = sampleService.getOrganizationRequester(currentSample, TableIdService.getInstance().REFERRING_ORG_TYPE_ID); Organization referringDepartmentOrg = sampleService.getOrganizationRequester(currentSample, @@ -371,7 +375,9 @@ private void findContactInfo() { currentSiteInfo += referringOrg == null ? "" : referringOrg.getOrganizationName(); currentSiteInfo += "|" + (referringDepartmentOrg == null ? "" : referringDepartmentOrg.getOrganizationName()); - Person person = sampleService.getPersonRequester(currentSample); + //Person person = sampleService.getPersonRequester(currentSample); + Person person = sampleHumanService.getProviderForSample(currentSample).getPerson(); + if (person != null) { PersonService personService = SpringContext.getBean(PersonService.class); currentContactInfo = personService.getLastFirstName(person); @@ -594,7 +600,7 @@ protected void setEmptyResult(ClinicalPatientData data) { private void setCorrectedStatus(Result result, ClinicalPatientData data) { if (currentAnalysis.isCorrectedSincePatientReport() && !GenericValidator.isBlankOrNull(result.getValue())) { - data.setCorrectedResult(true); + data.setCorrectedResult(true);data.setContactInfo(currentContactInfo); sampleCorrectedMap.put(sampleService.getAccessionNumber(currentSample), true); currentAnalysis.setCorrectedSincePatientReport(false); updatedAnalysis.add(currentAnalysis); @@ -747,7 +753,7 @@ private void setAppropriateResults(List resultList, ClinicalPatientData reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : ""; if (quantification != null && quantification.getParentResult().getId().equals(sibResult.getId())) { - reportResult += ": " + quantification.getValue(true); + reportResult += ": " + quantification.getValue(); } } } @@ -790,7 +796,7 @@ public int compare(Result o1, Result o2) { && quantifiedResult.getParentResult().getId().equals(subResult.getId()) && !GenericValidator.isBlankOrNull(quantifiedResult.getValue())) { multiResult.append(": "); - multiResult.append(quantifiedResult.getValue(true)); + multiResult.append(quantifiedResult.getValue()); } multiResult.append("\n"); } @@ -852,8 +858,10 @@ protected void initializeReportItems() { * If you have a string that you wish to add a suffix like units of measure, use * this. * - * @param base something - * @param plus something to add, if the above is not null or blank. + * @param base + * something + * @param plus + * something to add, if the above is not null or blank. * @return the two args put together, or the original if it was blank to begin * with. */ @@ -928,8 +936,24 @@ protected ClinicalPatientData buildClinicalPatientData(boolean hasParent) { data.setCollectionDateTime(DateUtil.convertTimestampToStringDateAndConfiguredHourTime( currentAnalysis.getSampleItem().getCollectionDate())); } - - data.setAccessionNumber(sampleService.getAccessionNumber(currentSample) + "-" + sortOrder); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + if (doAnalysis) { + data.setSampleId( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(currentSample)) + + "-" + data.getSampleSortOrder()); + } + data.setAccessionNumber( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(currentSample)) + + "-" + data.getSampleSortOrder()); + } else { + if (doAnalysis) { + data.setSampleId(sampleService.getAccessionNumber(currentSample) + "-" + data.getSampleSortOrder()); + } + data.setAccessionNumber(sampleService.getAccessionNumber(currentSample) + "-" + data.getSampleSortOrder()); + } if (doAnalysis) { reportResultAndConclusion(data); @@ -942,6 +966,23 @@ protected ClinicalPatientData buildClinicalPatientData(boolean hasParent) { sampleService.getSampleAdditionalFieldForSample(sampleService.getId(currentSample), AdditionalFieldName.CONTACT_TRACING_INDEX_RECORD_NUMBER).getFieldValue()); } + String testSection = analysisService.getTestSection(currentAnalysis).getDescription(); + if(testSection.equals("Tuberculose")) { + data.setTbOrderReason(observationHistoryService.getValueForSample(ObservationType.TB_ORDER_REASON, + sampleService.getId(currentSample))); + data.setTbDiagnosticReason(observationHistoryService.getValueForSample(ObservationType.TB_DIAGNOSTIC_REASON, + sampleService.getId(currentSample))); + data.setTbFollowupReason(observationHistoryService.getValueForSample(ObservationType.TB_FOLLOWUP_REASON, + sampleService.getId(currentSample))); + data.setTbAnalysisMethod(observationHistoryService.getValueForSample(ObservationType.TB_ANALYSIS_METHOD, + sampleService.getId(currentSample))); + data.setTbSampleAspect(observationHistoryService.getValueForSample(ObservationType.TB_SAMPLE_ASPECT, + sampleService.getId(currentSample))); + data.setTbFollowupPeriodLine1(observationHistoryService.getValueForSample(ObservationType.TB_FOLLOWUP_PERIOD_LINE1, + sampleService.getId(currentSample))); + data.setTbFollowupPeriodLine2(observationHistoryService.getValueForSample(ObservationType.TB_FOLLOWUP_PERIOD_LINE2, + sampleService.getId(currentSample))); + } return data; } @@ -967,8 +1008,10 @@ private String getTestName(boolean indent) { * starting at the given index. It uses multiresult form the list when the * results are for the same test. * - * @param referralResultsForReferral The referral - * @param i starting index. + * @param referralResultsForReferral + * The referral + * @param i + * starting index. * @return last index actually used. If you start with 2 and this routine uses * just item #2, then return result is 2, but if there are two results * for the same test (e.g. a multi-select result) and those are in item @@ -995,7 +1038,8 @@ protected int lastUsedReportReferralResultValue(List referralRes * Derive the appropriate displayable string results, either dictionary result * or direct value. * - * @param result The result + * @param result + * The result * @return a reportable result string. */ private String findDisplayableReportResult(Result result) { @@ -1016,7 +1060,7 @@ private String findDisplayableReportResult(Result result) { reportResult = dictionary.getId() != null ? dictionary.getLocalizedName() : ""; } } else { - reportResult = result.getValue(true); + reportResult = result.getValue(); } return reportResult; } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/PatientVLReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/PatientVLReport.java index 6c2d7b193b..1dab10f84a 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/PatientVLReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/PatientVLReport.java @@ -8,10 +8,14 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.service.AnalysisService; import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.IReportTrackingService; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.ReportTrackingService; import org.openelisglobal.common.services.StatusService.AnalysisStatus; +import org.openelisglobal.common.util.ConfigurationProperties; +import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.internationalization.MessageUtil; import org.openelisglobal.observationhistory.service.ObservationHistoryService; @@ -70,7 +74,7 @@ protected void createReportItems() { setPatientInfo(data); setTestInfo(data); reportItems.add(data); - + } protected void setTestInfo(VLReportData data) { @@ -82,6 +86,8 @@ protected void setTestInfo(VLReportData data) { Date maxCompleationDate = null; long maxCompleationTime = 0L; + Date maxReleasedDate = null; + long maxReleasedTime = 0L; // String invalidValue = MessageUtil.getMessage("report.test.status.inProgress"); for (Analysis analysis : analysisList) { @@ -93,7 +99,12 @@ protected void setTestInfo(VLReportData data) { maxCompleationDate = analysis.getCompletedDate(); maxCompleationTime = maxCompleationDate.getTime(); } - + } + if (analysis.getReleasedDate() != null) { + if (analysis.getReleasedDate().getTime() > maxReleasedTime) { + maxReleasedDate = analysis.getReleasedDate(); + maxReleasedTime = maxReleasedDate.getTime(); + } } String testName = TestServiceImpl.getUserLocalizedTestName(analysis.getTest()); @@ -110,7 +121,7 @@ protected void setTestInfo(VLReportData data) { // data.setShowVirologie(Boolean.TRUE); String resultValue = ""; if (resultList.size() > 0) { - resultValue = resultList.get(resultList.size() - 1).getValue(true); + resultValue = resultList.get(resultList.size() - 1).getValue(false); } String baseValue = resultValue; @@ -144,6 +155,9 @@ protected void setTestInfo(VLReportData data) { if (maxCompleationDate != null) { data.setCompleationdate(DateUtil.convertSqlDateToStringDate(maxCompleationDate)); } + if (maxReleasedDate != null) { + data.setReleasedate(DateUtil.convertSqlDateToStringDate(maxReleasedDate)); + } data.setDuplicateReport(mayBeDuplicate); data.setStatus(atLeastOneAnalysisNotValidated ? MessageUtil.getMessage("report.status.partial") @@ -167,7 +181,14 @@ protected void setPatientInfo(VLReportData data) { data.setServicename(sampleOrg.getId() == null ? "" : oService.get(sampleOrg.getOrganization().getId()).getOrganizationName()); data.setDoctor(getObservationValues(OBSERVATION_DOCTOR_ID)); - data.setAccession_number(reportSample.getAccessionNumber()); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + data.setAccessionNumber( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(reportSample.getAccessionNumber())); + } else { + data.setAccessionNumber(reportSample.getAccessionNumber()); + } data.setReceptiondate(DateUtil.convertTimestampToStringDateAndTime(reportSample.getReceivedTimestamp())); Timestamp collectionDate = reportSample.getCollectionDate(); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/RejectionReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/RejectionReport.java index ab2f27e0b8..2c0de4d145 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/RejectionReport.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/RejectionReport.java @@ -24,6 +24,8 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.analysis.service.AnalysisService; import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.util.ConfigurationProperties; import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.common.util.DateUtil; @@ -131,8 +133,14 @@ protected RejectionReportBean createRejectionReportBean(String noteText, Analysi break; } } - - item.setAccessionNumber(sampleService.getAccessionNumber(sample).substring(PREFIX_LENGTH)); +if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + item.setAccessionNumber( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(sampleService.getAccessionNumber(sample).substring(PREFIX_LENGTH))); + } else { + item.setAccessionNumber(sampleService.getAccessionNumber(sample).substring(PREFIX_LENGTH)); + } item.setReceivedDate(sampleService.getTwoYearReceivedDateForDisplay(sample)); item.setCollectionDate( DateUtil.convertTimestampToTwoYearStringDate(analysis.getSampleItem().getCollectionDate())); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ReportImplementationFactory.java b/src/main/java/org/openelisglobal/reports/action/implementation/ReportImplementationFactory.java index 18c11b5fea..a11294f184 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/ReportImplementationFactory.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ReportImplementationFactory.java @@ -68,7 +68,9 @@ public static IReportParameterSetter getParameterSetter(String report) { } else if (report.equals("patientHaitiClinical") || report.equals("patientHaitiLNSP") || report.equals("patientCILNSP") || report.equals("patientCILNSP_vreduit")) { return new PatientClinicalReport(); - } else if (report.equals("indicatorHaitiClinicalHIV")) { + }else if (report.equals("TBPatientReport")) { + return new PatientClinicalReport(); + }else if (report.equals("indicatorHaitiClinicalHIV")) { return new IndicatorHIV(); } else if (report.equals("indicatorHaitiLNSPHIV")) { return new IndicatorHIVLNSP(); @@ -132,6 +134,8 @@ public static IReportParameterSetter getParameterSetter(String report) { return new RejectionReportByTestSection(); } else if (report.equals("CIStudyExport")) { return new ExportStudyProjectByDate(); + } else if (report.equals("TBOrderExport")) { + return new ExportTBOrdersByDate(); } else if (report.equals("Trends")) { return new ExportTrendsByDate(); } @@ -194,7 +198,10 @@ public static IReportCreator getReportCreator(String report) { } else if (report.equals("patientCILNSP")) { return new PatientCILNSPClinical(); } else if (report.equals("patientCILNSP_vreduit")) { - return new PatientCILNSPClinical_vreduit(); + //return new PatientCILNSPClinical_vreduit(); + return new PatientCILNSPClinical(); + } else if (report.equals("TBPatientReport")) { + return new TBPatientReport(); } else if (report.equals("indicatorHaitiClinicalHIV")) { return new IndicatorHIV(); } else if (report.equals("indicatorHaitiLNSPHIV")) { @@ -266,6 +273,8 @@ else if (report.equals("CISampleRoutineExport")) { return new ExportStudyProjectByDate(); } else if (report.equals("Trends")) { return new ExportTrendsByDate(); + } else if (report.equals("TBOrderExport")) { + return new ExportTBOrdersByDate(); } else if (report.equals("MauritiusProtocolSheet")) { return new MauritiusProtocolSheet(); } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/ReportSpecificationParameters.java b/src/main/java/org/openelisglobal/reports/action/implementation/ReportSpecificationParameters.java index 1d37ae6f92..2026e390f1 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/ReportSpecificationParameters.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/ReportSpecificationParameters.java @@ -24,79 +24,84 @@ import org.openelisglobal.reports.form.ReportForm; public class ReportSpecificationParameters implements IReportParameterSetter { - public enum Parameter { - NO_SPECIFICATION, DATE_RANGE, ACCESSION_RANGE, USE_SITE_SEARCH, USE_PATIENT_SEARCH - } + public enum Parameter { + NO_SPECIFICATION, DATE_RANGE, ACCESSION_RANGE, USE_SITE_SEARCH, USE_PATIENT_SEARCH + } - private String reportTitle; - private String instructions; - private ArrayList parameters = new ArrayList<>(); + private String reportTitle; + private String instructions; + private ArrayList parameters = new ArrayList<>(); - /** - * Constructor for a single parameter. - * - * @param parameter The parameter which will appear on the parameter page - * @param title The title for the page, it will appear above the - * parameters - * @param instructions The instructions for the user on how to fill in the - * parameters - */ - public ReportSpecificationParameters(Parameter parameter, String title, String instructions) { - parameters.add(parameter); - reportTitle = title; - this.instructions = instructions; - } + /** + * Constructor for a single parameter. + * + * @param parameter The parameter which will appear on the parameter page + * @param title The title for the page, it will appear above the + * parameters + * @param instructions The instructions for the user on how to fill in the + * parameters + */ + public ReportSpecificationParameters(Parameter parameter, String title, String instructions) { + parameters.add(parameter); + reportTitle = title; + this.instructions = instructions; + } - public ReportSpecificationParameters(Parameter[] parameters, String title, String instructions) { - reportTitle = title; - this.instructions = instructions; + public ReportSpecificationParameters(Parameter[] parameters, String title, String instructions) { + reportTitle = title; + this.instructions = instructions; - for (Parameter newParameter : parameters) { - this.parameters.add(newParameter); - } + for (Parameter newParameter : parameters) { + this.parameters.add(newParameter); + } - } + } - @Override - public void setRequestParameters(ReportForm form) { - try { - form.setReportName(reportTitle); - if (!GenericValidator.isBlankOrNull(instructions)) { - form.setInstructions(instructions); - } - form.setReportName(reportTitle); - for (Parameter parameter : parameters) { - switch (parameter) { - case USE_PATIENT_SEARCH: { - form.setUsePatientSearch(true); - form.setPatientSearch(new PatientSearch()); - break; - } - case USE_SITE_SEARCH: { - form.setUseSiteSearch(true); - form.setReferringSiteList(DisplayListService.getInstance() - .getList(DisplayListService.ListType.SAMPLE_PATIENT_REFERRING_CLINIC)); - break; - } - case DATE_RANGE: { - form.setUseLowerDateRange(true); - form.setUseUpperDateRange(true); - break; - } - case ACCESSION_RANGE: { - form.setUseAccessionDirect(true); - form.setUseHighAccessionDirect(true); - break; - } - case NO_SPECIFICATION: { - form.setNoRequestSpecifications(true); - break; - } - } - } - } catch (RuntimeException e) { - LogEvent.logDebug(e); - } - } + @Override + public void setRequestParameters(ReportForm form) { + try { + form.setReportName(reportTitle); + if (!GenericValidator.isBlankOrNull(instructions)) { + form.setInstructions(instructions); + } + form.setReportName(reportTitle); + for (Parameter parameter : parameters) { + switch (parameter) { + case USE_PATIENT_SEARCH: { + form.setUsePatientSearch(true); + form.setPatientSearch(new PatientSearch()); + break; + } + case USE_SITE_SEARCH: { + form.setUseSiteSearch(true); + if (form.getReport().equals("patientVL1")) { + form.setReferringSiteList(DisplayListService.getInstance() + .getList(DisplayListService.ListType.ARV_ORG_LIST)); + } else { + form.setReferringSiteList(DisplayListService.getInstance() + .getList(DisplayListService.ListType.SAMPLE_PATIENT_REFERRING_CLINIC)); + } + break; + } + case DATE_RANGE: { + form.setUseLowerDateRange(true); + form.setUseUpperDateRange(true); + break; + } + case ACCESSION_RANGE: { + form.setUseAccessionDirect(true); + form.setUseHighAccessionDirect(true); + break; + } + case NO_SPECIFICATION: { + form.setNoRequestSpecifications(true); + break; + } + } + } + } catch (RuntimeException e) { + LogEvent.logDebug(e); + } + } } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/RetroCINonConformityNotification.java b/src/main/java/org/openelisglobal/reports/action/implementation/RetroCINonConformityNotification.java index 096a142b31..d5f8f46a70 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/RetroCINonConformityNotification.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/RetroCINonConformityNotification.java @@ -25,8 +25,12 @@ import org.apache.commons.validator.GenericValidator; import org.openelisglobal.common.log.LogEvent; +import org.openelisglobal.common.provider.validation.AccessionNumberValidatorFactory.AccessionFormat; +import org.openelisglobal.common.provider.validation.AlphanumAccessionValidator; import org.openelisglobal.common.services.QAService; import org.openelisglobal.common.services.QAService.QAObservationType; +import org.openelisglobal.common.util.ConfigurationProperties; +import org.openelisglobal.common.util.ConfigurationProperties.Property; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.common.util.IdValuePair; import org.openelisglobal.internationalization.MessageUtil; @@ -235,7 +239,14 @@ private List createNonconformityItem(Sample sample) { if (eventPrintable(sampleAccessionNumber, event)) { NonConformityReportData item = new NonConformityReportData(); QAService qa = new QAService(event); - item.setAccessionNumber(sampleAccessionNumber); + if (AccessionFormat.ALPHANUM.toString() + .equals(ConfigurationProperties.getInstance().getPropertyValue(Property.AccessionFormat))) { + item.setAccessionNumber( + AlphanumAccessionValidator + .convertAlphaNumLabNumForDisplay(sampleAccessionNumber)); + } else { + item.setAccessionNumber(sampleAccessionNumber); + } item.setReceivedDate(receivedDate); item.setReceivedHour(receivedHour); item.setService(orgName); diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/TBPatientReport.java b/src/main/java/org/openelisglobal/reports/action/implementation/TBPatientReport.java new file mode 100644 index 0000000000..5088a50284 --- /dev/null +++ b/src/main/java/org/openelisglobal/reports/action/implementation/TBPatientReport.java @@ -0,0 +1,304 @@ +/** + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations under + * the License. + * + * The Original Code is OpenELIS code. + * + * Copyright (C) ITECH, University of Washington, Seattle WA. All Rights Reserved. + * + */ +package org.openelisglobal.reports.action.implementation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.validator.GenericValidator; +import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.constants.Constants; +import org.openelisglobal.common.services.IStatusService; +import org.openelisglobal.common.services.TableIdService; +import org.openelisglobal.common.services.StatusService.AnalysisStatus; +import org.openelisglobal.common.util.ConfigurationProperties; +import org.openelisglobal.common.util.ConfigurationProperties.Property; +import org.openelisglobal.internationalization.MessageUtil; +import org.openelisglobal.localization.service.LocalizationService; +import org.openelisglobal.note.service.NoteService; +import org.openelisglobal.organization.valueholder.Organization; +import org.openelisglobal.referral.valueholder.Referral; +import org.openelisglobal.referral.valueholder.ReferralResult; +import org.openelisglobal.reports.action.implementation.reportBeans.ClinicalPatientData; +import org.openelisglobal.result.service.ResultService; +import org.openelisglobal.result.valueholder.Result; +import org.openelisglobal.sample.util.AccessionNumberUtil; +import org.openelisglobal.sampleitem.valueholder.SampleItem; +import org.openelisglobal.sampleorganization.service.SampleOrganizationService; +import org.openelisglobal.spring.util.SpringContext; +import org.openelisglobal.test.service.TestServiceImpl; +import org.openelisglobal.test.valueholder.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; + +public class TBPatientReport extends PatientReport implements IReportCreator, IReportParameterSetter { + + private static Set analysisStatusIds; + protected List clinicalReportItems; + + static { + analysisStatusIds = new HashSet<>(); + analysisStatusIds.add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.BiologistRejected))); + analysisStatusIds.add( + Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Finalized))); + analysisStatusIds.add(Integer.parseInt( + SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NonConforming_depricated))); + analysisStatusIds.add( + Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted))); + analysisStatusIds.add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalAcceptance))); + analysisStatusIds.add( + Integer.parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.Canceled))); + analysisStatusIds.add(Integer + .parseInt(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalRejected))); + + } + + static final String configName = ConfigurationProperties.getInstance().getPropertyValue(Property.configurationName); + + public TBPatientReport() { + super(); + } + + @Override + protected String reportFileName() { + return "TBPatientReport"; + } + + @Override + protected void createReportParameters() { + super.createReportParameters(); + reportParameters.put("billingNumberLabel", + SpringContext.getBean(LocalizationService.class).getLocalizedValueById(ConfigurationProperties + .getInstance().getPropertyValue(Property.BILLING_REFERENCE_NUMBER_LABEL))); + reportParameters.put("footerName", getFooterName()); + } + + private Object getFooterName() { + if (configName.equals("CI IPCI") || configName.equals("CI LNSP")) { + return "CILNSPFooter.jasper"; + } else { + return ""; + } + } + + @Override + protected String getHeaderName() { + return "CDIHeader.jasper"; + } + + @Override + protected void createReportItems() { + Set sampleSet = new HashSet<>(); + + boolean isConfirmationSample = sampleService.isConfirmationSample(currentSample); + List analysisList = analysisService + .getAnalysesBySampleIdAndStatusId(sampleService.getId(currentSample), analysisStatusIds); + List filteredAnalysisList = userService.filterAnalysesByLabUnitRoles(systemUserId, analysisList, + Constants.ROLE_REPORTS); + List currentSampleReportItems = new ArrayList<>(filteredAnalysisList.size()); + currentConclusion = null; + for (Analysis analysis : filteredAnalysisList) { + if (!analysis.getTest().isInLabOnly()) { + boolean hasParentResult = analysis.getParentResult() != null; + sampleSet.add(analysis.getSampleItem()); + if (analysis.getTest() != null) { + currentAnalysis = analysis; + ClinicalPatientData resultsData = buildClinicalPatientData(hasParentResult); + Organization referringOrg = sampleOrganizationService.getDataBySample(currentSample).getOrganization(); + currentSiteInfo = referringOrg == null ? "" : referringOrg.getOrganizationName(); + resultsData.setSiteInfo(currentSiteInfo); + if (isConfirmationSample) { + String alerts = resultsData.getAlerts(); + if (!GenericValidator.isBlankOrNull(alerts)) { + alerts += ", C"; + } else { + alerts = "C"; + } + resultsData.setAlerts(alerts); + } + reportItems.add(resultsData); + currentSampleReportItems.add(resultsData); + } + } + } + setCollectionTime(sampleSet, currentSampleReportItems, true); + } + + @Override + protected void setEmptyResult(ClinicalPatientData data) { + data.setAnalysisStatus(MessageUtil.getMessage("report.test.status.inProgress")); + } + + @Override + protected void setReferredOutResult(ClinicalPatientData data) { + data.setAlerts("R"); + data.setAnalysisStatus(MessageUtil.getMessage("report.test.status.inProgress")); + } + + @Override + protected void postSampleBuild() { + if (reportItems.isEmpty()) { + ClinicalPatientData reportItem = buildClinicalPatientData(false); + reportItem.setTestSection(MessageUtil.getMessage("report.no.results")); + clinicalReportItems.add(reportItem); + } else { + buildReport(); + } + + } + + private void buildReport() { + Collections.sort(reportItems, new Comparator() { + @Override + public int compare(ClinicalPatientData o1, ClinicalPatientData o2) { + String o1AccessionNumber = AccessionNumberUtil + .getAccessionNumberFromSampleItemAccessionNumber(o1.getAccessionNumber()); + String o2AccessionNumber = AccessionNumberUtil + .getAccessionNumberFromSampleItemAccessionNumber(o2.getAccessionNumber()); + int accessionSort = o1AccessionNumber.compareTo(o2AccessionNumber); + + if (accessionSort != 0) { + return accessionSort; + } + + int sectionSort = o1.getSectionSortOrder() - o2.getSectionSortOrder(); + + if (sectionSort != 0) { + return sectionSort; + } + + int sampleTypeSort = o1.getSampleType().compareTo(o2.getSampleType()); + + if (sampleTypeSort != 0) { + return sampleTypeSort; + } + + int sampleIdSort = o1.getSampleId().compareTo(o2.getSampleId()); + + if (sampleIdSort != 0) { + return sampleIdSort; + } + + if (o1.getParentResult() != null && o2.getParentResult() != null) { + int parentSort = Integer.parseInt(o1.getParentResult().getId()) + - Integer.parseInt(o2.getParentResult().getId()); + if (parentSort != 0) { + return parentSort; + } + } + return o1.getTestSortOrder() - o2.getTestSortOrder(); + } + }); + + ArrayList augmentedList = new ArrayList<>(reportItems.size()); + HashSet parentResults = new HashSet<>(); + for (ClinicalPatientData data : reportItems) { + if (data.getParentResult() != null && !parentResults.contains(data.getParentResult().getId())) { + parentResults.add(data.getParentResult().getId()); + ClinicalPatientData marker = new ClinicalPatientData(data); + ResultService resultResultService = SpringContext.getBean(ResultService.class); + Result result = data.getParentResult(); + marker.setTestName(resultResultService.getSimpleResultValue(result)); + marker.setResult(null); + marker.setTestRefRange(null); + marker.setParentMarker(true); + augmentedList.add(marker); + } + + augmentedList.add(data); + } + + reportItems = augmentedList; + + String currentPanelId = null; + for (ClinicalPatientData reportItem : reportItems) { + if (reportItem.getPanel() != null && !reportItem.getPanel().getId().equals(currentPanelId)) { + currentPanelId = reportItem.getPanel().getId(); + reportItem.setSeparator(true); + } else if (reportItem.getPanel() == null && currentPanelId != null) { + currentPanelId = null; + reportItem.setSeparator(true); + } + + int dividerIndex = reportItem.getAccessionNumber().lastIndexOf("-"); + reportItem.setAccessionNumber(reportItem.getAccessionNumber().substring(0, dividerIndex)); + reportItem.setCompleteFlag(MessageUtil + .getMessage(sampleCompleteMap.get(reportItem.getAccessionNumber()) ? "report.status.complete" + : "report.status.partial")); + if (reportItem.isCorrectedResult()) { + if (reportItem.getNote() != null && reportItem.getNote().length() > 0) { + reportItem.setNote(MessageUtil.getMessage("result.corrected") + "
" + reportItem.getNote()); + } else { + reportItem.setNote(MessageUtil.getMessage("result.corrected")); + } + + } + + reportItem + .setCorrectedResult(sampleCorrectedMap.get(reportItem.getAccessionNumber().split("_")[0]) != null); + } + } + + @Override + protected String getReportNameForParameterPage() { + return MessageUtil.getMessage("openreports.patientTestStatus"); + } + + @Override + public JRDataSource getReportDataSource() throws IllegalStateException { + if (!initialized) { + throw new IllegalStateException("initializeReport not called first"); + } + + return errorFound ? new JRBeanCollectionDataSource(errorMsgs) : new JRBeanCollectionDataSource(reportItems); + } + + @Override + protected void initializeReportItems() { + super.initializeReportItems(); + clinicalReportItems = new ArrayList<>(); + } + + @Override + protected void setReferredResult(ClinicalPatientData data, Result result) { + data.setResult(data.getResult()); + data.setAlerts(getResultFlag(result, null)); + } + + @Override + protected boolean appendUOMToRange() { + return false; + } + + @Override + protected boolean augmentResultWithFlag() { + return false; + } + + @Override + protected boolean useReportingDescription() { + return true; + } +} diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ARVReportData.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ARVReportData.java index 4dc0e7068d..4837dd7117 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ARVReportData.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ARVReportData.java @@ -65,6 +65,7 @@ public class ARVReportData { private String orgname; private String doctor; private String compleationdate; + private String releasedate; private String labNo; private String pcr; private String status; @@ -543,4 +544,12 @@ public static String getNoteForSampleQaEvent(SampleQaEvent sampleQaEvent) { return note != null ? note.getText() : null; } } + + public String getReleasedate() { + return releasedate; + } + + public void setReleasedate(String releasedate) { + this.releasedate = releasedate; + } } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CIRoutineColumnBuilder.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CIRoutineColumnBuilder.java index 4a016b82ba..f1584654d6 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CIRoutineColumnBuilder.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CIRoutineColumnBuilder.java @@ -80,11 +80,13 @@ public CIRoutineColumnBuilder(DateRange dateRange) { protected String buildWhereSamplePatienOrgSQL(Date lowDate, Date highDate) { String WHERE_SAMPLE_PATIENT_ORG = " WHERE " + "\n pat.id = sh.patient_id " + "\n AND sh.samp_id = s.id " + "\n AND s.entered_date >= '" + formatDateForDatabaseSql(lowDate) + "'" + "\n AND s.entered_date <= '" - + formatDateForDatabaseSql(highDate) + "'" + "\n AND s.id = sq.sample_id " - + "\n AND pat.person_id = per.id " + "\n AND sq.requester_type_id = rq.id " + + formatDateForDatabaseSql(highDate) + "'" + "\n " + + "\n AND sq.requester_type_id = rq.id " + + "\n AND sq.sample_id= s.id " + + "\n AND pat.person_id = per.id " + "\n AND o.id = sq.requester_id " // + ((GenericValidator.isBlankOrNull(projectStr))?"": " AND sp.proj_id = " + // projectStr) - + "\n AND o.id = sq.requester_id "; + ; return WHERE_SAMPLE_PATIENT_ORG; } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVColumnBuilder.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVColumnBuilder.java index e3551083d3..1b5f7543b2 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVColumnBuilder.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVColumnBuilder.java @@ -40,6 +40,7 @@ import org.openelisglobal.common.log.LogEvent; import org.openelisglobal.common.services.IStatusService; import org.openelisglobal.common.services.StatusService; +import org.openelisglobal.common.services.StatusService.AnalysisStatus; import org.openelisglobal.common.services.StatusService.OrderStatus; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.common.util.StringUtil; @@ -193,7 +194,9 @@ public static void defineAllProjectTags() { projectTag = "ARVB"; } else if (project.getNameKey().contains("VLS")) { projectTag = "VLS"; - } else { + } else if (project.getNameKey().contains("Recency")) { + projectTag = "RTRI"; + } else { // otherwise we use the letters from the Sample ID prefix, which // at some locations for some projects is undefined. String code = project.getProgramCode(); @@ -409,7 +412,7 @@ public String translate(String value, String accessionNumber) throws SQLExceptio case DROP_ZERO: return ("0".equals(value) || value == null) ? "" : value; case TEST_RESULT: - return isBlankOrNull(value) ? "" : translateTestResult(csvName, value); + return isBlankOrNull(value) ? "" : translateTestResult(this.csvName, value); case GEND_CD4: return isBlankOrNull(value) ? "" : translateGendResult(getGendCD4CountAnalyteId(), value); case LOG: @@ -429,6 +432,30 @@ public String translate(String value, String accessionNumber) throws SQLExceptio case NonConforming_depricated: return "N"; // Non-conforming, Non-conformes } + case ANALYSIS_STATUS: + AnalysisStatus analysisStatus = StatusService.getInstance().getAnalysisStatusForID(value); + if (analysisStatus == null) + return "?"; + switch (analysisStatus) { + case SampleRejected: + return "Reject"; // rejété, entr�e + case NotStarted: + return "Not_Started"; // entered, entr�e + case Canceled: + return "Canceled"; // commenced, commenc� + case TechnicalAcceptance: + return "Validation_Technique"; // Finished, Finale + case TechnicalRejected: + return "Rejet - Technique"; // Non-conforming, Non-conformes + case BiologistRejected: + return "Rejet - Biologie"; // entered, entr�e + case NonConforming_depricated: + return "Non Conforme"; // commenced, commenc� + case Finalized: + return "Validation_Biologique"; // Finished, Finale + + + } case PROJECT: return translateProjectId(value); case DEBUG: @@ -486,7 +513,10 @@ public String translateAge(Strategy strategy, String end) throws SQLException, P * @throws SQLException */ public String translateTestResult(String testName, String value) throws SQLException { - TestResult testResult = testResultsByTestName.get(testName); + TestResult testResult = testResultsByTestName.get(testName); + if(testName.equalsIgnoreCase("DNA PCR")) { //need fix: testName is different from map key + return ResourceTranslator.DictionaryTranslator.getInstance().translateRaw(value); + } // if it is not in the table then its just a value in the result // that was NOT selected from a list, thus no translation if (testResult == null) { diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVRoutineColumnBuilder.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVRoutineColumnBuilder.java index 98d491944d..94e964b860 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVRoutineColumnBuilder.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/CSVRoutineColumnBuilder.java @@ -134,8 +134,8 @@ public CSVRoutineColumnBuilder(StatusService.AnalysisStatus validStatusFilter) { protected ResultService resultService = SpringContext.getBean(ResultService.class); private ObservationHistoryTypeService ohtService = SpringContext.getBean(ObservationHistoryTypeService.class); private AnalyteService analyteService = SpringContext.getBean(AnalyteService.class); - private TestService testService = SpringContext.getBean(TestService.class); - private TestResultService testResultService = SpringContext.getBean(TestResultService.class); + protected TestService testService = SpringContext.getBean(TestService.class); + protected TestResultService testResultService = SpringContext.getBean(TestResultService.class); // This is the largest value possible for a postgres column name. The code will // convert the @@ -150,7 +150,7 @@ public CSVRoutineColumnBuilder(StatusService.AnalysisStatus validStatusFilter) { @SuppressWarnings("unchecked") protected void defineAllTestsAndResults() { if (allTests == null) { - allTests = testService.getAllOrderBy("name"); + allTests = testService.getAllOrderBy("description"); } if (testResultsByTestName == null) { testResultsByTestName = new HashMap<>(); @@ -215,8 +215,8 @@ protected void buildResultSet() throws SQLException { // MAKE SURE ALL GENERATED QUERIES STAY SQL INJECTION SAFE makeSQL(); String sql = query.toString(); - System.out.println("buildResultSet:" + sql); - // LogEvent.logInfo(this.getClass().getSimpleName(), "method unkown", "===1===\n" + + LogEvent.logDebug(this.getClass().getSimpleName(), "buildResultSet", sql); + // LogEvent.logInfo(this.getClass().getName(), "method unkown", "===1===\n" + // sql.substring(0, 7000)); // the SQL is // chunked out only because Eclipse thinks printing really big strings to the // console must be wrong, so it truncates them @@ -231,7 +231,8 @@ protected void buildResultSet() throws SQLException { @Override public ResultSet execute(Connection connection) throws SQLException { - return connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY) + + return connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY) .executeQuery(); } @@ -304,7 +305,7 @@ public String getValue(CSVRoutineColumn column, String accessionNumber) throws S return result; } - private String prepareColumnName(String columnName) { + protected String prepareColumnName(String columnName) { // trim and escape the column name so it is more safe from sql injection if (!columnName.matches("(?i)[a-zàâçéèêëîïôûùüÿñæœ0-9_ ()%/\\[\\]+\\-]+")) { LogEvent.logWarn(this.getClass().getSimpleName(), "prepareColumnName", @@ -501,7 +502,7 @@ private String findMultiSelectItemsForTest(String testId) throws SQLException { List results = resultService.getResultsForTestAndSample(sampleId, testId); StringBuilder multi = new StringBuilder(); for (Result result : results) { - multi.append(ResourceTranslator.DictionaryTranslator.getInstance().translateRaw(result.getValue())); + multi.append(ResourceTranslator.DictionaryTranslator.getInstance().translateRaw(result.getValue().replace(",", "."))); multi.append(","); } @@ -533,23 +534,26 @@ protected void appendResultCrosstab(java.sql.Date lowDate, java.sql.Date highDat // String excludeAnalytes = getExcludedAnalytesSet(); SQLConstant listName = SQLConstant.RESULT; query.append(", \n\n ( SELECT si.samp_id, si.id AS sampleItem_id, si.sort_order AS sampleItemNo, " + listName - + ".* " + " FROM sample_item AS si LEFT JOIN \n "); + + ".* " + " FROM sample_item AS si JOIN \n "); // Begin cross tab / pivot table - query.append(" crosstab( " + "\n 'SELECT si.id, t.description, r.value " - + "\n FROM clinlims.result AS r, clinlims.analysis AS a, clinlims.sample_item AS si, clinlims.sample AS s, clinlims.test AS t, clinlims.test_result AS tr " - + "\n WHERE " + "\n s.id = si.samp_id" + " AND s.entered_date >= date(''" + query.append(" crosstab( " + "\n 'SELECT si.id, t.description, replace(replace(replace(replace(r.value ,E''\\n'', '' ''), E''\\t'', '' ''), E''\\r'', '' ''),'','',''.'') " + + "\n FROM clinlims.result AS r join clinlims.analysis AS a on a.id = r.analysis_id \n " + + " join clinlims.sample_item AS si on si.id = a.sampitem_id \n " + + " join clinlims.sample AS s on s.id = si.samp_id \n" + + " join clinlims.test_result AS tr on r.test_result_id = tr.id \n" + + " join clinlims.test AS t on tr.test_id = t.id \n" + + " left join sample_projects sp on si.samp_id = sp.samp_id \n" + + "\n WHERE sp.id IS NULL AND s.entered_date >= date(''" + formatDateForDatabaseSql(lowDate) + "'') AND s.entered_date <= date(''" - + formatDateForDatabaseSql(highDate) + " '') " + "\n AND s.id = si.samp_id " - + "\n AND si.id = a.sampitem_id " + + formatDateForDatabaseSql(highDate) + " '') " + "\n " // sql injection safe as user cannot overwrite validStatusId in database + ((validStatusId == null) ? "" : " AND a.status_id = " + validStatusId) - + "\n AND a.id = r.analysis_id " + "\n AND r.test_result_id = tr.id" + "\n AND tr.test_id = t.id " // + (( excludeAnalytes == null)?"": // " AND r.analyte_id NOT IN ( " + excludeAnalytes) + ")" // + " AND a.test_id = t.id " + "\n ORDER BY 1, 2 " - + "\n ', 'SELECT description FROM test where is_active = ''Y'' ORDER BY 1' ) "); + + "\n ', 'SELECT t.description FROM test t where t.is_active = ''Y'' ORDER BY 1' ) "); // end of cross tab // Name the test pivot table columns . We'll name them all after the diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ClinicalPatientData.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ClinicalPatientData.java index 15f3d5792b..0ff0ca1f8f 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ClinicalPatientData.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/ClinicalPatientData.java @@ -78,6 +78,14 @@ public final class ClinicalPatientData { private String analysisStatus; private String contactTracingIndexName; private String contactTracingIndexRecordNumber; + private String prescriber; + private String tbOrderReason; + private String tbDiagnosticReason; + private String tbFollowupReason; + private String tbAnalysisMethod; + private String tbSampleAspect; + private String tbFollowupPeriodLine1; + private String tbFollowupPeriodLine2; public ClinicalPatientData() { } @@ -600,4 +608,70 @@ public String getContactTracingIndexRecordNumber() { public void setContactTracingIndexRecordNumber(String contactTracingIndexRecordNumber) { this.contactTracingIndexRecordNumber = contactTracingIndexRecordNumber; } + + public String getTbOrderReason() { + return tbOrderReason; + } + + public void setTbOrderReason(String tbOrderReason) { + this.tbOrderReason = tbOrderReason; + } + + public String getTbDiagnosticReason() { + return tbDiagnosticReason; + } + + public void setTbDiagnosticReason(String tbDiagnosticReason) { + this.tbDiagnosticReason = tbDiagnosticReason; + } + + public String getTbFollowupReason() { + return tbFollowupReason; + } + + public void setTbFollowupReason(String tbFollowupReason) { + this.tbFollowupReason = tbFollowupReason; + } + + public String getTbAnalysisMethod() { + return tbAnalysisMethod; + } + + public void setTbAnalysisMethod(String tbAnalysisMethod) { + this.tbAnalysisMethod = tbAnalysisMethod; + } + + public String getTbSampleAspect() { + return tbSampleAspect; + } + + public void setTbSampleAspect(String tbSampleAspect) { + this.tbSampleAspect = tbSampleAspect; + } + + public String getTbFollowupPeriodLine1() { + return tbFollowupPeriodLine1; + } + + public void setTbFollowupPeriodLine1(String tbFollowupPeriodLine1) { + this.tbFollowupPeriodLine1 = tbFollowupPeriodLine1; + } + + public String getTbFollowupPeriodLine2() { + return tbFollowupPeriodLine2; + } + + public void setTbFollowupPeriodLine2(String tbFollowupPeriodLine2) { + this.tbFollowupPeriodLine2 = tbFollowupPeriodLine2; + } + + public String getPrescriber() { + return prescriber; + } + + public void setPrescriber(String prescriber) { + this.prescriber = prescriber; + } + + } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/EIDReportData.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/EIDReportData.java index 11abd9bace..7f187e0d07 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/EIDReportData.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/EIDReportData.java @@ -141,7 +141,7 @@ public String getAccession_number() { return accession_number; } - public void setAccession_number(String accessionNumber) { + public void setAccessionNumber(String accessionNumber) { accession_number = accessionNumber; } diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/RTRIColumnBuilder.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/RTRIColumnBuilder.java new file mode 100644 index 0000000000..8f93869f01 --- /dev/null +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/RTRIColumnBuilder.java @@ -0,0 +1,145 @@ +/** +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (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.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" +* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +* License for the specific language governing rights and limitations under +* the License. +* +* The Original Code is OpenELIS code. +* +* Copyright (C) ITECH, University of Washington, Seattle WA. All Rights Reserved. +* +*/ +package org.openelisglobal.reports.action.implementation.reportBeans; + +//import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.SAMPLE_STATUS; +import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.ANALYSIS_STATUS; +import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.DATE_TIME; +import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.DICT_RAW; +import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.LOG; +import static org.openelisglobal.reports.action.implementation.reportBeans.CSVColumnBuilder.Strategy.NONE; + +import java.util.List; +import java.util.stream.Collectors; + +//import org.openelisglobal.common.services.StatusService; + +//import org.apache.commons.validator.GenericValidator; + +//import org.openelisglobal.common.services.TestService; +//import org.openelisglobal.observationhistorytype.valueholder.ObservationHistoryType; +import org.openelisglobal.reports.action.implementation.Report.DateRange; +import org.openelisglobal.reports.form.ReportForm.DateType; +import org.openelisglobal.spring.util.SpringContext; +import org.openelisglobal.test.service.TestService; +import org.openelisglobal.test.valueholder.Test; + +public class RTRIColumnBuilder extends CIStudyColumnBuilder { + private DateType dateType; + + public RTRIColumnBuilder(DateRange dateRange, String projectStr) { + super(dateRange, projectStr); + } + + public RTRIColumnBuilder(DateRange dateRange, String projectStr, DateType dateType) { + super(dateRange, projectStr); + this.dateType = dateType; + } + + // @Override + @Override + protected void defineAllReportColumns() { + defineBasicColumns(); + add("Asante HIV-1 Rapid Recency", "RECENCY TEST RESULT", Strategy.DICT); + add("type_of_sample_name", "TYPE_OF_SAMPLE", NONE); + add("analysis_status_id", "ANALYSIS_STATUS", ANALYSIS_STATUS); + add("started_date", "STARTED_DATE", DATE_TIME); + add("completed_date", "COMPLETED_DATE", DATE_TIME); + add("released_date", "RELEASED_DATE", DATE_TIME); + +// add("hivStatus", "STATVIH", DICT_RAW); + add("nameOfDoctor", "NAMEMED", NONE); + add("nameOfSampler", "NAMEPRELEV", NONE); + + add("vlPregnancy", "VL_PREGNANCY"); + add("vlSuckle", "VL_SUCKLE"); + + // addAllResultsColumns(); + + } + + /** + * @return the SQL for (nearly) one big row for each sample in the date range + * for the particular project. + */ + + @Override + public void makeSQL() { + // Switch date column according to selected DateType: PK + String dateColumn = "s.entered_date "; + switch (dateType) { + case ORDER_DATE: + dateColumn = "s.entered_date "; + break; + case RESULT_DATE: + dateColumn = "a.released_date "; + break; + case PRINT_DATE: + dateColumn = "a.released_date "; + default: + break; + } + // String validStatusId = + // StatusService.getInstance().getStatusID(StatusService.AnalysisStatus.Finalized); + // String validStatusId2 = + // StatusService.getInstance().getStatusID(StatusService.AnalysisStatus.Finalized); + + List tests = SpringContext.getBean(TestService.class).getActiveTestByName("Asante HIV-1 Rapid Recency"); + String ids = tests.stream().map(e -> { + return e.getId(); + }).collect(Collectors.joining(",")); + query = new StringBuilder(); + String lowDatePostgres = postgresDateFormat.format(dateRange.getLowDate()); + String highDatePostgres = postgresDateFormat.format(dateRange.getHighDate()); + query.append(SELECT_SAMPLE_PATIENT_ORGANIZATION); + // all crosstab generated tables need to be listed in the following list and in + // the WHERE clause at the bottom + query.append( + "\n, a.started_date,a.completed_date,a.released_date, a.status_id as analysis_status_id, r.value as \"Asante HIV-1 Rapid Recency\",a.type_of_sample_name, demo.* "); + + query.append(FROM_SAMPLE_PATIENT_ORGANIZATION); + + // -------------------------- + // all observation history values + appendObservationHistoryCrosstab(dateRange.getLowDate(), dateRange.getHighDate()); + + // result + // appendResultCrosstab(dateRange.getLowDate(), dateRange.getHighDate() ); + query.append(", clinlims.analysis as a \n"); + // ------------------------------------- + + query.append(" LEFT JOIN clinlims.result as r on r.analysis_id = a.id \n" + + " LEFT JOIN clinlims.sample_item as si on si.id = a.sampitem_id \n" + + " LEFT JOIN clinlims.sample as s on s.id = si.samp_id \n"); + + // and finally the join that puts these all together. Each cross table should be + // listed here otherwise it's not in the result and you'll get a full join + query.append(" WHERE a.test_id in (" + ids + ")\n AND a.sampitem_id = si.id" + + "\n AND s.id = si.samp_id AND s.id=sh.samp_id AND sh.patient_id=pat.id" + + "\n AND pat.person_id = per.id AND s.id=so.samp_id AND so.org_id=o.id" + + "\n AND s.id = sp.samp_id AND s.id=demo.s_id" + "\n " + "\n AND " + dateColumn + " >= date('" + + lowDatePostgres + "')" + "\n AND " + dateColumn + " <= date('" + highDatePostgres + "')" + +//-------------- + + "\n ORDER BY s.accession_number;"); + ///////// + // no don't insert another crosstab or table here, go up before the main WHERE + // clause + return; + } + +} diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/TBColumnBuilder.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/TBColumnBuilder.java new file mode 100644 index 0000000000..3e69ee32a8 --- /dev/null +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/TBColumnBuilder.java @@ -0,0 +1,148 @@ +/* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (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.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" +* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +* License for the specific language governing rights and limitations under +* the License. +* +* The Original Code is OpenELIS code. +* +* Copyright (C) The Minnesota Department of Health. All Rights Reserved. +* +* Contributor(s): CIRG, University of Washington, Seattle WA. +*/ +package org.openelisglobal.reports.action.implementation.reportBeans; + +import java.sql.Date; +import java.util.HashMap; +import java.util.List; + +import org.openelisglobal.reports.action.implementation.Report.DateRange; +import org.openelisglobal.reports.action.implementation.reportBeans.CSVRoutineColumnBuilder.SQLConstant; +import org.openelisglobal.test.service.TestServiceImpl; +import org.openelisglobal.test.valueholder.Test; +import org.openelisglobal.testresult.valueholder.TestResult; + +/** + * @author pahill (pahill@uw.edu) + * @since May 18, 2011 + */ +public class TBColumnBuilder extends RoutineColumnBuilder { + + /** + * @param dateRange + * @param projectStr + */ + public TBColumnBuilder(DateRange dateRange) { + super(dateRange); + } + + /** + * @see org.openelisglobal.reports.action.implementation.reportBeans.CIRoutineColumnBuilder#defineAllReportColumns() + */ + @Override + protected void defineAllReportColumns() { + defineBasicColumns(); + addAllResultsColumns(); + } + + @Override + @SuppressWarnings("unchecked") + protected void defineAllTestsAndResults() { + if (allTests == null) { + allTests = testService.getTbTest(); + } + if (testResultsByTestName == null) { + testResultsByTestName = new HashMap<>(); + List allTestResults = testResultService.getAllTestResults(); + for (TestResult testResult : allTestResults) { + String key = TestServiceImpl.getLocalizedTestNameWithType(testResult.getTest()); + testResultsByTestName.put(key, testResult); + } + } + } + + @Override + protected void appendResultCrosstab(java.sql.Date lowDate, java.sql.Date highDate) { + // A list of analytes which should not show up in the regular results, + // String excludeAnalytes = getExcludedAnalytesSet(); + SQLConstant listName = SQLConstant.RESULT; + query.append(", \n\n ( SELECT si.samp_id, si.id AS sampleItem_id, si.sort_order AS sampleItemNo, " + listName + + ".* " + " FROM sample_item AS si JOIN \n "); + + // Begin cross tab / pivot table + query.append(" crosstab( " + "\n 'SELECT si.id, t.description, replace(replace(replace(replace(r.value ,E''\\n'', '' ''), E''\\t'', '' ''), E''\\r'', '' ''),'','',''.'') " + + "\n FROM clinlims.result AS r join clinlims.analysis AS a on a.id = r.analysis_id \n " + + " join clinlims.sample_item AS si on si.id = a.sampitem_id \n " + + " join clinlims.sample AS s on s.id = si.samp_id \n" + + " join clinlims.test_result AS tr on r.test_result_id = tr.id \n" + + " join clinlims.test AS t on tr.test_id = t.id \n" + + " JOIN test_section ts ON t.test_section_id = ts.id \n" + + " left join sample_projects sp on si.samp_id = sp.samp_id \n" + + "\n WHERE sp.id IS NULL AND ts.name = ''TB'' AND s.entered_date >= date(''" + + formatDateForDatabaseSql(lowDate) + "'') AND s.entered_date <= date(''" + + formatDateForDatabaseSql(highDate) + " '') " + "\n " + // sql injection safe as user cannot overwrite validStatusId in database + + ((validStatusId == null) ? "" : " AND a.status_id = " + validStatusId) + // + (( excludeAnalytes == null)?"": + // " AND r.analyte_id NOT IN ( " + excludeAnalytes) + ")" + // + " AND a.test_id = t.id " + + "\n ORDER BY 1, 2 " + + "\n ', 'SELECT t.description FROM test t JOIN test_section ts ON t.test_section_id = ts.id where t.is_active = ''Y'' AND ts.name = ''TB'' ORDER BY 1' ) "); + // end of cross tab + + // Name the test pivot table columns . We'll name them all after the + // resource name, because some tests have fancy characters in them and + // somewhere + // between iReport, Java and postgres a complex name (e.g. one including + // a beta, " HCG Quant") get messed up and isn't found. + query.append("\n as " + listName + " ( " // inner use of the list name + + "\"si_id\" numeric(10) "); + for (Test col : allTests) { + String testName = TestServiceImpl.getLocalizedTestNameWithType(col); + query.append("\n, " + prepareColumnName(testName) + " varchar(200) "); + } + query.append(" ) \n"); + // left join all sample Items from the right sample range to the results table. + query.append("\n ON si.id = " + listName + ".si_id " // the inner use a few lines above + + "\n ORDER BY si.samp_id, si.id " + "\n) AS " + listName + "\n "); // outer re-use the list name to + // name this sparse matrix of + // results. + } + + /** + * @see org.openelisglobal.reports.action.implementation.reportBeans.CIRoutineColumnBuilder#makeSQL() + */ + @Override + public void makeSQL() { + query = new StringBuilder(); + Date lowDate = dateRange.getLowDate(); + Date highDate = dateRange.getHighDate(); + query.append(SELECT_SAMPLE_PATIENT_ORGANIZATION); + // more cross tabulation of other columns goes where + query.append(SELECT_ALL_DEMOGRAPHIC_AND_RESULTS); + + // FROM clause for ordinary lab (sample and patient) tables + query.append(FROM_SAMPLE_PATIENT_ORGANIZATION); + + // all observation history from expressions + appendObservationHistoryCrosstab(lowDate, highDate); + + appendResultCrosstab(lowDate, highDate); + + // and finally the join that puts these all together. Each cross table should be + // listed here otherwise it's not in the result and you'll get a full join + query.append(buildWhereSamplePatienOrgSQL(lowDate, highDate) + // insert joining of any other crosstab here. + + "\n AND s.id = demo.samp_id " + "\n AND s.id = result.samp_id " + "\n ORDER BY s.accession_number "); + // no don't insert another crosstab or table here, go up before the main WHERE + // clause + System.out.println("query.toString(): "+query.toString()); + return; + } + +} diff --git a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/VLReportData.java b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/VLReportData.java index 6e78969d39..9f6caadfa3 100644 --- a/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/VLReportData.java +++ b/src/main/java/org/openelisglobal/reports/action/implementation/reportBeans/VLReportData.java @@ -50,6 +50,7 @@ public class VLReportData { private String servicename; private String doctor; private String compleationdate; + private String releasedate; private String vlPregnancy; private String vlSuckle; private String PTME; @@ -137,7 +138,7 @@ public String getAccession_number() { return accession_number; } - public void setAccession_number(String accessionNumber) { + public void setAccessionNumber(String accessionNumber) { accession_number = accessionNumber; } @@ -348,4 +349,12 @@ public static String getNoteForSampleQaEvent(SampleQaEvent sampleQaEvent) { } } + public String getReleasedate() { + return releasedate; + } + + public void setReleasedate(String releasedate) { + this.releasedate = releasedate; + } + } diff --git a/src/main/java/org/openelisglobal/reports/controller/ReportController.java b/src/main/java/org/openelisglobal/reports/controller/ReportController.java index 01119389cc..035cd20e63 100644 --- a/src/main/java/org/openelisglobal/reports/controller/ReportController.java +++ b/src/main/java/org/openelisglobal/reports/controller/ReportController.java @@ -59,8 +59,8 @@ public class ReportController extends BaseController { @Autowired private ServletContext context; - private static String reportPath = null; - private static String imagesPath = null; + private String reportPath = null; + private String imagesPath = null; @ModelAttribute("form") public BaseForm form() { diff --git a/src/main/java/org/openelisglobal/reports/form/ReportForm.java b/src/main/java/org/openelisglobal/reports/form/ReportForm.java index c1cd34c8a9..b4868c7123 100644 --- a/src/main/java/org/openelisglobal/reports/form/ReportForm.java +++ b/src/main/java/org/openelisglobal/reports/form/ReportForm.java @@ -138,10 +138,18 @@ public enum ReceptionTime { private boolean useSiteSearch; + private boolean useArvOrganizationSearch; + private String referringSiteId; private List referringSiteList; + private List arvOrganizationList; + + private String arvSiteId; + + private List arvSiteList; + private String referringSiteDepartmentId; private List referringSiteDepartmentList; @@ -812,4 +820,36 @@ public String getNumberOfcancerNuclei() { public void setNumberOfcancerNuclei(String numberOfcancerNuclei) { this.numberOfcancerNuclei = numberOfcancerNuclei; } + + public String getArvSiteId() { + return arvSiteId; + } + + public void setArvSiteId(String arvSiteId) { + this.arvSiteId = arvSiteId; + } + + public List getArvSiteList() { + return arvSiteList; + } + + public void setArvSiteList(List arvSiteList) { + this.arvSiteList = arvSiteList; + } + + public boolean isUseArvOrganizationSearch() { + return useArvOrganizationSearch; + } + + public void setUseArvOrganizationSearch(boolean useArvOrganizationSearch) { + this.useArvOrganizationSearch = useArvOrganizationSearch; + } + + public List getArvOrganizationList() { + return arvOrganizationList; + } + + public void setArvOrganizationList(List arvOrganizationList) { + this.arvOrganizationList = arvOrganizationList; + } } diff --git a/src/main/java/org/openelisglobal/result/controller/AnalyzerResultsController.java b/src/main/java/org/openelisglobal/result/controller/AnalyzerResultsController.java index b2dc23085e..16e993548a 100644 --- a/src/main/java/org/openelisglobal/result/controller/AnalyzerResultsController.java +++ b/src/main/java/org/openelisglobal/result/controller/AnalyzerResultsController.java @@ -719,15 +719,16 @@ public ModelAndView showAnalyzerResultsSave(HttpServletRequest request, } redirectAttibutes.addFlashAttribute(FWD_SUCCESS, true); - if (GenericValidator.isBlankOrNull(form.getType())) { - return findForward(FWD_SUCCESS_INSERT, form); - } else { - Map params = new HashMap<>(); - params.put("type", form.getType()); - // params.put("page", form.getPaging().getCurrentPage()); - params.put("forward", FWD_SUCCESS_INSERT); - return getForwardWithParameters(findForward(FWD_SUCCESS_INSERT, form), params); - } + return findForward(FWD_SUCCESS_INSERT, form); +// if (GenericValidator.isBlankOrNull(form.getType())) { +// return findForward(FWD_SUCCESS_INSERT, form); +// } else { +// Map params = new HashMap<>(); +// params.put("type", form.getType()); +// // params.put("page", form.getPaging().getCurrentPage()); +// params.put("forward", FWD_SUCCESS_INSERT); +// return getForwardWithParameters(findForward(FWD_SUCCESS_INSERT, form), params); +// } } private Errors validateSavableItems(List savableResults, Errors errors) { diff --git a/src/main/java/org/openelisglobal/result/controller/rest/LogbookResultsRestController.java b/src/main/java/org/openelisglobal/result/controller/rest/LogbookResultsRestController.java index 72ae1aded3..e7930d0141 100644 --- a/src/main/java/org/openelisglobal/result/controller/rest/LogbookResultsRestController.java +++ b/src/main/java/org/openelisglobal/result/controller/rest/LogbookResultsRestController.java @@ -395,24 +395,6 @@ private String getCurrentDate() { } - @PostMapping(value = "ReactLogbookResultsUpdateTest", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) - @ResponseBody - public void showReactLogbookResultsUpdateTest(HttpServletRequest request, - @Validated(LogbookResultsForm.LogbookResults.class) @RequestBody LogbookResultsForm Form, - BindingResult result) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - - ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); - String jsonString = new String(); - - try { - jsonString = mapper.writeValueAsString(Form); - } catch (Exception e) { - System.out.println("Post:LogbookResultsRestController:ERROR:" + e.toString()); - } - - System.out.println("Post:LogbookResultsRestController:SUCCESS" + jsonString); - - } @PostMapping(value = "ReactLogbookResultsUpdate", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) @ResponseBody @@ -420,8 +402,6 @@ public void showReactLogbookResultsUpdateTest(HttpServletRequest request, @Validated(LogbookResultsForm.LogbookResults.class) @RequestBody LogbookResultsForm form, BindingResult result) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - System.out.println("Post:LogbookResultsRestController:SUCCESS"); - boolean useTechnicianName = ConfigurationProperties.getInstance() .isPropertyValueEqual(Property.resultTechnicianName, "true"); boolean alwaysValidate = ConfigurationProperties.getInstance() @@ -549,6 +529,8 @@ private void createResultsFromItems(ResultsUpdateDataSet actionDataSet, boolean testResultItem.getNote(), RESULT_SUBJECT, getSysUserId(request))); if (testResultItem.isShadowRejected()) { + testResultItem.setResultValue(""); + testResultItem.setShadowResultValue(""); String rejectedReasonId = testResultItem.getRejectReasonId(); for (IdValuePair rejectReason : DisplayListService.getInstance().getList(ListType.REJECTION_REASONS)) { if (rejectedReasonId.equals(rejectReason.getId())) { diff --git a/src/main/java/org/openelisglobal/result/service/ResultServiceImpl.java b/src/main/java/org/openelisglobal/result/service/ResultServiceImpl.java index 6cef30e37b..d42368f30d 100644 --- a/src/main/java/org/openelisglobal/result/service/ResultServiceImpl.java +++ b/src/main/java/org/openelisglobal/result/service/ResultServiceImpl.java @@ -197,7 +197,7 @@ public String getResultValue(Result result, String separator, boolean printable, if (TypeOfTestResultServiceImpl.ResultType.DICTIONARY.matches(getTestType(result))) { if (!printable) { - return result.getValue(printable); + return result.getValue(); } String reportResult = ""; List resultList = baseObjectDAO.getResultsByAnalysis(result.getAnalysis()); @@ -218,13 +218,13 @@ public String getResultValue(Result result, String separator, boolean printable, } for (Result sibResult : dictionaryResults) { - Dictionary dictionary = dictionaryService.getDictionaryById(sibResult.getValue(printable)); + Dictionary dictionary = dictionaryService.getDictionaryById(sibResult.getValue()); reportResult = (dictionary != null && dictionary.getId() != null) ? dictionary.getLocalizedName() : ""; if (quantification != null && quantification.getParentResult().getId().equals(sibResult.getId())) { - reportResult += separator + quantification.getValue(printable); + reportResult += separator + quantification.getValue(); } } } @@ -252,26 +252,26 @@ public String getResultValue(Result result, String separator, boolean printable, } else { buffer.append(separator); } - buffer.append(dictionaryService.getDataForId(multiResult.getValue(printable)).getDictEntry()); + buffer.append(dictionaryService.getDataForId(multiResult.getValue()).getDictEntry()); } } return buffer.toString(); } else if (TypeOfTestResultServiceImpl.ResultType.NUMERIC.matches(getTestType(result))) { int significantPlaces = result.getSignificantDigits(); if (significantPlaces == -1) { - return result.getValue(printable) + appendUOM(result, includeUOM); + return result.getValue() + appendUOM(result, includeUOM); } if (significantPlaces == 0) { - return result.getValue(printable).split("\\.")[0] + appendUOM(result, includeUOM); + return result.getValue().split("\\.")[0] + appendUOM(result, includeUOM); } StringBuilder value = new StringBuilder(); - value.append(result.getValue(printable)); + value.append(result.getValue()); int startFill = 0; - if (!result.getValue(printable).contains(".")) { + if (!result.getValue().contains(".")) { value.append("."); } else { - startFill = result.getValue(printable).length() - result.getValue(printable).lastIndexOf(".") - 1; + startFill = result.getValue(true).length() - result.getValue(true).lastIndexOf(".") - 1; } for (int i = startFill; i < significantPlaces; i++) { @@ -281,9 +281,9 @@ public String getResultValue(Result result, String separator, boolean printable, return value.toString() + appendUOM(result, includeUOM); } else if (TypeOfTestResultServiceImpl.ResultType.ALPHA.matches(result.getResultType()) && !GenericValidator.isBlankOrNull(result.getValue())) { - return result.getValue(printable).split("\\(")[0].trim(); + return result.getValue().split("\\(")[0].trim(); } else { - return result.getValue(printable); + return result.getValue(); } } @@ -296,7 +296,7 @@ public String getResultValueForDisplay(Result result, String separator, boolean if (TypeOfTestResultServiceImpl.ResultType.DICTIONARY.matches(getTestType(result))) { if (!printable) { - return result.getValue(printable); + return result.getValue(); } String reportResult = ""; List resultList = baseObjectDAO.getResultsByAnalysis(result.getAnalysis()); @@ -317,13 +317,13 @@ public String getResultValueForDisplay(Result result, String separator, boolean } for (Result sibResult : dictionaryResults) { - Dictionary dictionary = dictionaryService.getDictionaryById(sibResult.getValue(printable)); + Dictionary dictionary = dictionaryService.getDictionaryById(sibResult.getValue()); reportResult = (dictionary != null && dictionary.getId() != null) ? dictionary.getLocalizedName() : ""; if (quantification != null && quantification.getParentResult().getId().equals(sibResult.getId())) { - reportResult += separator + quantification.getValue(printable); + reportResult += separator + quantification.getValue(); } } } @@ -344,33 +344,33 @@ public String getResultValueForDisplay(Result result, String separator, boolean List results = new ResultDAOImpl().getResultsByAnalysis(result.getAnalysis()); for (Result multiResult : results) { - if (!GenericValidator.isBlankOrNull(multiResult.getValue(printable)) + if (!GenericValidator.isBlankOrNull(multiResult.getValue()) && TypeOfTestResultServiceImpl.ResultType.isMultiSelectVariant(multiResult.getResultType())) { if (firstPass) { firstPass = false; } else { buffer.append(separator); } - buffer.append(dictionaryService.getDataForId(multiResult.getValue(printable)).getDictEntry()); + buffer.append(dictionaryService.getDataForId(multiResult.getValue()).getDictEntry()); } } return buffer.toString(); } else if (TypeOfTestResultServiceImpl.ResultType.NUMERIC.matches(getTestType(result))) { int significantPlaces = result.getSignificantDigits(); if (significantPlaces == -1) { - return result.getValue(printable) + appendUOM(result, includeUOM); + return result.getValue() + appendUOM(result, includeUOM); } if (significantPlaces == 0) { - return result.getValue(printable).split("\\.")[0] + appendUOM(result, includeUOM); + return result.getValue().split("\\.")[0] + appendUOM(result, includeUOM); } StringBuilder value = new StringBuilder(); - value.append(result.getValue(printable)); + value.append(result.getValue()); int startFill = 0; - if (!result.getValue(printable).contains(".")) { + if (!result.getValue().contains(".")) { value.append("."); } else { - startFill = result.getValue(printable).length() - result.getValue(printable).lastIndexOf(".") - 1; + startFill = result.getValue(true).length() - result.getValue(true).lastIndexOf(".") - 1; } for (int i = startFill; i < significantPlaces; i++) { @@ -380,9 +380,9 @@ public String getResultValueForDisplay(Result result, String separator, boolean return value.toString() + appendUOM(result, includeUOM); } else if (TypeOfTestResultServiceImpl.ResultType.ALPHA.matches(result.getResultType()) && !GenericValidator.isBlankOrNull(result.getValue())) { - return result.getValue(printable).split("\\(")[0].trim(); + return result.getValue().split("\\(")[0].trim(); } else { - return result.getValue(printable); + return result.getValue(); } } diff --git a/src/main/java/org/openelisglobal/result/valueholder/Result.java b/src/main/java/org/openelisglobal/result/valueholder/Result.java index 6f2002ce0d..0218e53bd6 100644 --- a/src/main/java/org/openelisglobal/result/valueholder/Result.java +++ b/src/main/java/org/openelisglobal/result/valueholder/Result.java @@ -25,6 +25,7 @@ import org.openelisglobal.common.valueholder.ValueHolderInterface; import org.openelisglobal.dataexchange.orderresult.OrderResponseWorker.Event; import org.openelisglobal.testresult.valueholder.TestResult; +import com.fasterxml.jackson.annotation.JsonIgnore; public class Result extends EnumValueItemImpl { @@ -110,14 +111,33 @@ public String getValue() { } public String getValue(Boolean getActualNumericValue) { - if (getActualNumericValue && this.resultType != null) { - if ((this.resultType.equals("N") || this.resultType.equals("D") || this.resultType.equals("A")) + if (getActualNumericValue) { + if ((this.resultType.equals("N")) && this.value != null) { return StringUtil.getActualNumericValue(value); } } return value; } + + @JsonIgnore + public long getVLValueAsNumber() { + long finalResult = 0; + String workingResult = value.split("\\(")[0].trim(); + if (workingResult.toLowerCase().contains("log7") || workingResult.contains(">")) { + finalResult = 1000000; + } else if (workingResult.toUpperCase().contains("L") || workingResult.contains("<")) { + finalResult = 20; + } else { + try { + finalResult = Long.parseLong(workingResult.replaceAll("[^0-9]", "")); + } catch (Exception e) { + finalResult = -1; + } + } + + return finalResult; + } public void setValue(String value) { this.value = value; diff --git a/src/main/java/org/openelisglobal/resultvalidation/bean/AnalysisItem.java b/src/main/java/org/openelisglobal/resultvalidation/bean/AnalysisItem.java index 56b160932b..aa290aa0b8 100644 --- a/src/main/java/org/openelisglobal/resultvalidation/bean/AnalysisItem.java +++ b/src/main/java/org/openelisglobal/resultvalidation/bean/AnalysisItem.java @@ -15,6 +15,7 @@ */ package org.openelisglobal.resultvalidation.bean; +import java.io.Serializable; import java.sql.Timestamp; import java.util.List; @@ -26,9 +27,11 @@ import org.openelisglobal.validation.annotations.SafeHtml; import org.openelisglobal.validation.annotations.ValidAccessionNumber; -public class AnalysisItem { +public class AnalysisItem implements Serializable{ - private String id; + private static final long serialVersionUID = 1L; + + private String id; private String units; diff --git a/src/main/java/org/openelisglobal/resultvalidation/controller/AccessionValidationController.java b/src/main/java/org/openelisglobal/resultvalidation/controller/AccessionValidationController.java index a3db6e1f54..c46f80f628 100644 --- a/src/main/java/org/openelisglobal/resultvalidation/controller/AccessionValidationController.java +++ b/src/main/java/org/openelisglobal/resultvalidation/controller/AccessionValidationController.java @@ -67,9 +67,9 @@ public AccessionValidationController(RoleService roleService) { } @RequestMapping(value = "/AccessionValidation", method = RequestMethod.GET) - public ModelAndView showAccessionValidation(HttpServletRequest request) + public ModelAndView showAccessionValidation(HttpServletRequest request,AccessionValidationForm form) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - AccessionValidationForm form = new AccessionValidationForm(); + //AccessionValidationForm form = new AccessionValidationForm(); request.getSession().setAttribute(SAVE_DISABLED, TRUE); form.setReferralReasons(DisplayListService.getInstance().getList(DisplayListService.ListType.REFERRAL_REASONS)); diff --git a/src/main/java/org/openelisglobal/resultvalidation/controller/ResultValidationRetroCController.java b/src/main/java/org/openelisglobal/resultvalidation/controller/ResultValidationRetroCController.java index 5042390fb8..ff68de8f31 100644 --- a/src/main/java/org/openelisglobal/resultvalidation/controller/ResultValidationRetroCController.java +++ b/src/main/java/org/openelisglobal/resultvalidation/controller/ResultValidationRetroCController.java @@ -39,14 +39,14 @@ public void initBinder(WebDataBinder binder) { binder.setAllowedFields(ALLOWED_FIELDS); } - @RequestMapping(value = "/ResultValidationRetroC", method = RequestMethod.GET) - public ModelAndView showResultValidationRetroC(HttpServletRequest request) + @RequestMapping(value = "/ResultValidationRetroC") + public ModelAndView showResultValidationRetroC(HttpServletRequest request,ResultValidationForm form) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - ResultValidationForm form = new ResultValidationForm(); request.getSession().setAttribute(SAVE_DISABLED, "true"); String testSectionName = (request.getParameter("type")); String testName = (request.getParameter("test")); + form.setTestSection(testSectionName); ResultValidationPaging paging = new ResultValidationPaging(); String newPage = request.getParameter("page"); @@ -60,13 +60,14 @@ public ModelAndView showResultValidationRetroC(HttpServletRequest request) if (!GenericValidator.isBlankOrNull(testSectionName)) { String sectionName = Character.toUpperCase(testSectionName.charAt(0)) + testSectionName.substring(1); sectionName = getDBSectionName(sectionName); - List resultList = resultsValidationUtility.getResultValidationList(sectionName, testName, - getValidationStatus(testSectionName)); - form.setSearchFinished(true); - paging.setDatabaseResults(request, form, resultList); + List resultList = resultsValidationUtility.getResultValidationList(sectionName, testName, + getValidationStatus(testSectionName)); + form.setSearchFinished(true); + paging.setDatabaseResults(request, form, resultList); } } else { + form.setSearchFinished(true); paging.page(request, form, Integer.parseInt(newPage)); } diff --git a/src/main/java/org/openelisglobal/resultvalidation/controller/rest/AccessionValidationRestController.java b/src/main/java/org/openelisglobal/resultvalidation/controller/rest/AccessionValidationRestController.java index 70ad03996c..4a39b719a8 100644 --- a/src/main/java/org/openelisglobal/resultvalidation/controller/rest/AccessionValidationRestController.java +++ b/src/main/java/org/openelisglobal/resultvalidation/controller/rest/AccessionValidationRestController.java @@ -245,8 +245,6 @@ public ResultValidationForm showAccessionValidationRangeSave(HttpServletRequest BindingResult result) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - System.out.println("Post:LogbookResultsRestController:SUCCESS"); - System.out.println("Post:LogbookResultsRestController:" + form); if ("true".equals(request.getParameter("pageResults"))) { return getResultValidation(request, form ,false); diff --git a/src/main/java/org/openelisglobal/resultvalidation/util/ResultsValidationUtility.java b/src/main/java/org/openelisglobal/resultvalidation/util/ResultsValidationUtility.java index f83a4c461c..1f79ed53f4 100644 --- a/src/main/java/org/openelisglobal/resultvalidation/util/ResultsValidationUtility.java +++ b/src/main/java/org/openelisglobal/resultvalidation/util/ResultsValidationUtility.java @@ -698,7 +698,7 @@ public final AnalysisItem testResultItemToAnalysisItem(ResultValidationItem test } protected final String getFormattedResult(ResultValidationItem testResultItem) { - String result = testResultItem.getResult().getValue(false); + String result = testResultItem.getResult().getValue(); if (TestIdentityService.getInstance().isTestNumericViralLoad(testResultItem.getTestId()) && !GenericValidator.isBlankOrNull(result)) { return result.split("\\(")[0].trim(); diff --git a/src/main/java/org/openelisglobal/sample/controller/SampleEntryByProjectController.java b/src/main/java/org/openelisglobal/sample/controller/SampleEntryByProjectController.java index 3f26c64ae6..48b8166beb 100644 --- a/src/main/java/org/openelisglobal/sample/controller/SampleEntryByProjectController.java +++ b/src/main/java/org/openelisglobal/sample/controller/SampleEntryByProjectController.java @@ -6,29 +6,60 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.validator.GenericValidator; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.ServiceRequest; +import org.hl7.fhir.r4.model.Specimen; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.ParameterComponent; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.DateTimeType; +import org.hl7.fhir.r4.model.DecimalType; +import org.openelisglobal.common.log.LogEvent; import org.openelisglobal.common.services.DisplayListService; import org.openelisglobal.common.services.DisplayListService.ListType; import org.openelisglobal.common.services.IStatusService; +import org.openelisglobal.common.services.StatusService.ExternalOrderStatus; import org.openelisglobal.common.services.StatusService.SampleStatus; import org.openelisglobal.common.util.DateUtil; import org.openelisglobal.common.util.IdValuePair; +import org.openelisglobal.dataexchange.fhir.FhirConfig; +import org.openelisglobal.dataexchange.fhir.FhirUtil; +import org.openelisglobal.dataexchange.fhir.service.FhirPersistanceService; +import org.openelisglobal.dataexchange.order.valueholder.ElectronicOrder; +import org.openelisglobal.dataexchange.service.order.ElectronicOrderService; import org.openelisglobal.dictionary.ObservationHistoryList; +import org.openelisglobal.dictionary.service.DictionaryService; import org.openelisglobal.dictionary.valueholder.Dictionary; +import org.openelisglobal.organization.service.OrganizationService; import org.openelisglobal.organization.util.OrganizationTypeList; import org.openelisglobal.organization.valueholder.Organization; import org.openelisglobal.patient.saving.ISampleEntry; import org.openelisglobal.patient.saving.ISampleEntryAfterPatientEntry; import org.openelisglobal.patient.saving.ISampleSecondEntry; +import org.openelisglobal.patient.valueholder.ObservationData; +import org.openelisglobal.sample.form.ProjectData; import org.openelisglobal.sample.form.SampleEntryByProjectForm; import org.openelisglobal.sample.valueholder.Sample; import org.openelisglobal.sampleitem.valueholder.SampleItem; import org.openelisglobal.spring.util.SpringContext; import org.openelisglobal.typeofsample.valueholder.TypeOfSample; import org.owasp.encoder.Encode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; @@ -39,207 +70,614 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import ca.uhn.fhir.rest.client.api.IGenericClient; + @Controller public class SampleEntryByProjectController extends BaseSampleEntryController { - private static final String[] ALLOWED_FIELDS = new String[] { "currentDate", "domain", "project", - "patientLastUpdated", "personLastUpdated", "patientUpdateStatus", "patientPK", "samplePK", - "observations.projectFormName", "ProjectData.ARVcenterName", "ProjectData.ARVcenterCode", - "observations.nameOfDoctor", "receivedDateForDisplay", "receivedTimeForDisplay", "interviewDate", - "interviewTime", "subjectNumber", "siteSubjectNumber", "labNo", "gender", "birthDateForDisplay", - "ProjectData.dryTubeTaken", "ProjectData.edtaTubeTaken", "ProjectData.serologyHIVTest", - "ProjectData.glycemiaTest", "ProjectData.creatinineTest", "ProjectData.transaminaseTest", - "ProjectData.nfsTest", "ProjectData.cd4cd8Test", "ProjectData.viralLoadTest", "ProjectData.genotypingTest", - "observations.underInvestigation", "ProjectData.underInvestigationNote", "observations.hivStatus", - "ProjectData.EIDSiteName", "projectData.EIDsiteCode", "observations.whichPCR", - "observations.reasonForSecondPCRTest", "observations.nameOfRequestor", "observations.nameOfSampler", - "observations.eidInfantPTME", "observations.eidTypeOfClinic", "observations.eidHowChildFed", - "observations.eidStoppedBreastfeeding", "observations.eidInfantSymptomatic", "observations.eidInfantsARV", - "observations.eidInfantCotrimoxazole", "observations.eidMothersHIVStatus", "observations.eidMothersARV", - "ProjectData.dbsTaken","ProjectData.dbsvlTaken", "ProjectData.pscvlTaken", "ProjectData.dnaPCR", "ProjectData.INDsiteName", "ProjectData.address", - "ProjectData.phoneNumber", "ProjectData.faxNumber", "ProjectData.email", "observations.indFirstTestDate", - "observations.indFirstTestName", "observations.indFirstTestResult", "observations.indSecondTestDate", - "observations.indSecondTestName", "observations.indSecondTestResult", "observations.indSiteFinalResult", - "observations.reasonForRequest", "ProjectData.murexTest", "ProjectData.integralTest", - "ProjectData.vironostikaTest", "ProjectData.innoliaTest", "ProjectData.transaminaseALTLTest", - "ProjectData.transaminaseASTLTest", "ProjectData.gbTest", "ProjectData.lymphTest", "ProjectData.monoTest", - "ProjectData.eoTest", "ProjectData.basoTest", "ProjectData.grTest", "ProjectData.hbTest", - "ProjectData.hctTest", "ProjectData.vgmTest", "ProjectData.tcmhTest", "ProjectData.ccmhTest", - "ProjectData.plqTest", "ProjectData.cd3CountTest", "ProjectData.cd4CountTest", "observations.vlPregnancy", - "observations.vlSuckle", "observations.currentARVTreatment", "observations.arvTreatmentInitDate", - "observations.arvTreatmentRegime", "observations.currentARVTreatmentINNsList*", - "observations.vlReasonForRequest", "observations.vlOtherReasonForRequest", "observations.initcd4Count", - "observations.initcd4Percent", "observations.initcd4Date", "observations.demandcd4Count", - "observations.demandcd4Percent", "observations.demandcd4Date", "observations.vlBenefit", - "observations.priorVLValue", "observations.priorVLDate" }; - - @InitBinder - public void initBinder(WebDataBinder binder) { - binder.setAllowedFields(ALLOWED_FIELDS); - } - - @RequestMapping(value = "/SampleEntryByProject", method = RequestMethod.GET) - public ModelAndView showSampleEntryByProject(HttpServletRequest request) { - SampleEntryByProjectForm form = new SampleEntryByProjectForm(); - - Date today = Calendar.getInstance().getTime(); - String dateAsText = DateUtil.formatDateAsText(today); - form.setReceivedDateForDisplay(dateAsText); - form.setInterviewDate(dateAsText); - - setDisplayLists(form); - addFlashMsgsToRequest(request); - - return findForward(FWD_SUCCESS, form); - } - - @RequestMapping(value = "/SampleEntryByProject", method = RequestMethod.POST) - public ModelAndView postSampleEntryByProject(HttpServletRequest request, - @ModelAttribute("form") @Valid SampleEntryByProjectForm form, BindingResult result, - RedirectAttributes redirectAttributes) { - if (result.hasErrors()) { - saveErrors(result); - setDisplayLists(form); - return findForward(FWD_FAIL_INSERT, form); - } - - String forward; - - ISampleSecondEntry sampleSecondEntry = SpringContext.getBean(ISampleSecondEntry.class); - sampleSecondEntry.setFieldsFromForm(form); - sampleSecondEntry.setSysUserId(getSysUserId(request)); - sampleSecondEntry.setRequest(request); - if (sampleSecondEntry.canAccession()) { - forward = handleSave(request, sampleSecondEntry, form); - if (forward != null) { - if (FWD_SUCCESS_INSERT.equals(forward)) { - redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); - } else { - setDisplayLists(form); - } - return findForward(forward, form); - } - } - ISampleEntry sampleEntry = SpringContext.getBean(ISampleEntry.class); - sampleEntry.setFieldsFromForm(form); - sampleEntry.setSysUserId(getSysUserId(request)); - sampleEntry.setRequest(request); - if (sampleEntry.canAccession()) { - forward = handleSave(request, sampleEntry, form); - if (forward != null) { - if (FWD_SUCCESS_INSERT.equals(forward)) { - redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); - } else { - setDisplayLists(form); - } - return findForward(forward, form); - } - } - ISampleEntryAfterPatientEntry sampleEntryAfterPatientEntry = SpringContext - .getBean(ISampleEntryAfterPatientEntry.class); - sampleEntryAfterPatientEntry.setFieldsFromForm(form); - sampleEntryAfterPatientEntry.setSysUserId(getSysUserId(request)); - sampleEntryAfterPatientEntry.setRequest(request); - if (sampleEntryAfterPatientEntry.canAccession()) { - forward = handleSave(request, sampleEntryAfterPatientEntry, form); - if (forward != null) { - if (FWD_SUCCESS_INSERT.equals(forward)) { - redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); - } else { - setDisplayLists(form); - } - return findForward(forward, form); - } - } - logAndAddMessage(request, "postSampleEntryByProject", "errors.UpdateException"); - - setDisplayLists(form); - return findForward(FWD_FAIL_INSERT, form); - } - - public SampleItem getSampleItem(Sample sample, TypeOfSample typeofsample) { - SampleItem item = new SampleItem(); - item.setSample(sample); - item.setTypeOfSample(typeofsample); - item.setSortOrder(Integer.toString(1)); - item.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(SampleStatus.Entered)); - - return item; - } - - private void setDisplayLists(SampleEntryByProjectForm form) { - Map> formListsMapOfLists = new HashMap<>(); - List listOfDictionary = new ArrayList<>(); - List genders = DisplayListService.getInstance().getList(ListType.GENDERS); - - for (IdValuePair i : genders) { - Dictionary dictionary = new Dictionary(); - dictionary.setId(i.getId()); - dictionary.setDictEntry(i.getValue()); - listOfDictionary.add(dictionary); - } - - formListsMapOfLists.put("GENDERS", listOfDictionary); - form.setFormLists(formListsMapOfLists); - - // Get Lists - Map> observationHistoryMapOfLists = new HashMap<>(); - observationHistoryMapOfLists.put("EID_WHICH_PCR", ObservationHistoryList.EID_WHICH_PCR.getList()); - observationHistoryMapOfLists.put("EID_SECOND_PCR_REASON", - ObservationHistoryList.EID_SECOND_PCR_REASON.getList()); - observationHistoryMapOfLists.put("EID_TYPE_OF_CLINIC", ObservationHistoryList.EID_TYPE_OF_CLINIC.getList()); - observationHistoryMapOfLists.put("EID_HOW_CHILD_FED", ObservationHistoryList.EID_HOW_CHILD_FED.getList()); - observationHistoryMapOfLists.put("EID_STOPPED_BREASTFEEDING", - ObservationHistoryList.EID_STOPPED_BREASTFEEDING.getList()); - observationHistoryMapOfLists.put("YES_NO", ObservationHistoryList.YES_NO.getList()); - observationHistoryMapOfLists.put("EID_INFANT_PROPHYLAXIS_ARV", - ObservationHistoryList.EID_INFANT_PROPHYLAXIS_ARV.getList()); - observationHistoryMapOfLists.put("YES_NO_UNKNOWN", ObservationHistoryList.YES_NO_UNKNOWN.getList()); - observationHistoryMapOfLists.put("EID_MOTHERS_HIV_STATUS", - ObservationHistoryList.EID_MOTHERS_HIV_STATUS.getList()); - observationHistoryMapOfLists.put("EID_MOTHERS_ARV_TREATMENT", - ObservationHistoryList.EID_MOTHERS_ARV_TREATMENT.getList()); - observationHistoryMapOfLists.put("HIV_STATUSES", ObservationHistoryList.HIV_STATUSES.getList()); - observationHistoryMapOfLists.put("HIV_TYPES", ObservationHistoryList.HIV_TYPES.getList()); - observationHistoryMapOfLists.put("SPECIAL_REQUEST_REASONS", - ObservationHistoryList.SPECIAL_REQUEST_REASONS.getList()); - observationHistoryMapOfLists.put("ARV_REGIME", ObservationHistoryList.ARV_REGIME.getList()); - observationHistoryMapOfLists.put("ARV_REASON_FOR_VL_DEMAND", - ObservationHistoryList.ARV_REASON_FOR_VL_DEMAND.getList()); - - form.setDictionaryLists(observationHistoryMapOfLists); - - // Get EID Sites - Map> organizationTypeMapOfLists = new HashMap<>(); - organizationTypeMapOfLists.put("ARV_ORGS", OrganizationTypeList.ARV_ORGS.getList()); - organizationTypeMapOfLists.put("ARV_ORGS_BY_NAME", OrganizationTypeList.ARV_ORGS_BY_NAME.getList()); - organizationTypeMapOfLists.put("EID_ORGS_BY_NAME", OrganizationTypeList.EID_ORGS_BY_NAME.getList()); - organizationTypeMapOfLists.put("EID_ORGS", OrganizationTypeList.EID_ORGS.getList()); - form.setOrganizationTypeLists(organizationTypeMapOfLists); - } - - @Override - protected String findLocalForward(String forward) { - if (FWD_SUCCESS.equals(forward)) { - return "sampleEntryByProjectDefinition"; - } else if (FWD_FAIL.equals(forward)) { - return "homePageDefinition"; - } else if (FWD_SUCCESS_INSERT.equals(forward)) { - return "redirect:/SampleEntryByProject?type=" + Encode.forUriComponent(request.getParameter("type")); - } else if (FWD_FAIL_INSERT.equals(forward)) { - return "sampleEntryByProjectDefinition"; - } else { - return "PageNotFound"; - } - } - - @Override - protected String getPageTitleKey() { - return null; - } - - @Override - protected String getPageSubtitleKey() { - return null; - } + @Value("${org.openelisglobal.requester.identifier:}") + private String requestFhirUuid; + + @Autowired + private ElectronicOrderService electronicOrderService; + @Autowired + private FhirPersistanceService fhirPersistanceService; + + @Autowired + private FhirConfig fhirConfig; + @Autowired + private FhirUtil fhirUtil; + + private Task task = null; + private Practitioner requesterPerson = null; + private Practitioner collector = null; + private org.hl7.fhir.r4.model.Organization referringOrganization = null; + private Location location = null; + private ServiceRequest serviceRequest = null; + private Specimen specimen = null; + private Patient fhirPatient = null; + private static String OPENMRS_SYSTEM_URL = "https://openmrs.org"; + + private static final String[] ALLOWED_FIELDS = new String[] { "currentDate", "domain", "project", + "patientLastUpdated", "personLastUpdated", "patientUpdateStatus", "patientPK", "patientFhirUuid", + "samplePK", "observations.projectFormName", "ProjectData.ARVcenterName", "ProjectData.ARVcenterCode", + "observations.nameOfDoctor", "receivedDateForDisplay", "receivedTimeForDisplay", "interviewDate", + "interviewTime", "subjectNumber", "siteSubjectNumber", "upidCode", "labNo", "gender", "birthDateForDisplay", + "ProjectData.dryTubeTaken", "ProjectData.edtaTubeTaken", "ProjectData.serologyHIVTest", + "ProjectData.glycemiaTest", "ProjectData.creatinineTest", "ProjectData.transaminaseTest", + "ProjectData.nfsTest", "ProjectData.cd4cd8Test", "ProjectData.viralLoadTest", "ProjectData.genotypingTest", + "observations.underInvestigation", "ProjectData.underInvestigationNote", "observations.hivStatus", + "ProjectData.EIDSiteName", "projectData.EIDsiteCode", "observations.whichPCR", + "observations.reasonForSecondPCRTest", "observations.nameOfRequestor", "observations.nameOfSampler", + "observations.eidInfantPTME", "observations.eidTypeOfClinic", "observations.eidHowChildFed", + "observations.eidStoppedBreastfeeding", "observations.eidInfantSymptomatic", "observations.eidInfantsARV", + "observations.eidInfantCotrimoxazole", "observations.eidMothersHIVStatus", "observations.eidMothersARV", + "ProjectData.dbsTaken", "ProjectData.dbsvlTaken", "ProjectData.pscvlTaken", "ProjectData.dnaPCR", + "ProjectData.INDsiteName", "ProjectData.address", "ProjectData.phoneNumber", "ProjectData.faxNumber", + "ProjectData.email", "observations.indFirstTestDate", "observations.indFirstTestName", + "observations.indFirstTestResult", "observations.indSecondTestDate", "observations.indSecondTestName", + "observations.indSecondTestResult", "observations.indSiteFinalResult", "observations.reasonForRequest", + "ProjectData.murexTest", "ProjectData.integralTest", "ProjectData.vironostikaTest", + "ProjectData.innoliaTest", "ProjectData.transaminaseALTLTest", "ProjectData.transaminaseASTLTest", + "ProjectData.gbTest", "ProjectData.lymphTest", "ProjectData.monoTest", "ProjectData.eoTest", + "ProjectData.basoTest", "ProjectData.grTest", "ProjectData.hbTest", "ProjectData.hctTest", + "ProjectData.vgmTest", "ProjectData.tcmhTest", "ProjectData.ccmhTest", "ProjectData.plqTest", + "ProjectData.cd3CountTest", "ProjectData.cd4CountTest", "observations.vlPregnancy", "observations.vlSuckle", + "observations.currentARVTreatment", "observations.arvTreatmentInitDate", "observations.arvTreatmentRegime", + "observations.currentARVTreatmentINNsList*", "observations.vlReasonForRequest", + "observations.vlOtherReasonForRequest", "observations.initcd4Count", "observations.initcd4Percent", + "observations.initcd4Date", "observations.demandcd4Count", "observations.demandcd4Percent", + "observations.demandcd4Date", "observations.vlBenefit", "observations.priorVLValue", + "observations.priorVLDate", "electronicOrder.externalId", "ProjectData.asanteTest", + "ProjectData.plasmaTaken", "ProjectData.serumTaken"}; + + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.setAllowedFields(ALLOWED_FIELDS); + } + + @RequestMapping(value = "/SampleEntryByProject", method = RequestMethod.GET) + public ModelAndView showSampleEntryByProject(HttpServletRequest request) { + SampleEntryByProjectForm form = new SampleEntryByProjectForm(); + + Date today = Calendar.getInstance().getTime(); + String dateAsText = DateUtil.formatDateAsText(today); + form.setReceivedDateForDisplay(dateAsText); + form.setInterviewDate(dateAsText); + + setupFormData(request, form); + + setDisplayLists(form); + addFlashMsgsToRequest(request); + + return findForward(FWD_SUCCESS, form); + } + + private void setupFormData(HttpServletRequest request, SampleEntryByProjectForm form) { + try { + String externalOrderNumber = request.getParameter("ID"); + if (StringUtils.isNotBlank(externalOrderNumber)) { + ElectronicOrder eOrder = null; + List eOrders = electronicOrderService + .getElectronicOrdersByExternalId(externalOrderNumber); + if (eOrders.size() > 0) + eOrder = eOrders.get(eOrders.size() - 1); + if (eOrder != null) { + form.setElectronicOrder(eOrder); + IGenericClient localFhirClient = fhirUtil.getLocalFhirClient(); + for (String remotePath : fhirConfig.getRemoteStorePaths()) { + Bundle srBundle = (Bundle) localFhirClient.search().forResource(ServiceRequest.class) + .where(ServiceRequest.RES_ID.exactly().code(externalOrderNumber)) + .include(ServiceRequest.INCLUDE_SPECIMEN).execute(); + for (BundleEntryComponent bundleComponent : srBundle.getEntry()) { + if (bundleComponent.hasResource() && ResourceType.ServiceRequest + .equals(bundleComponent.getResource().getResourceType())) { + serviceRequest = (ServiceRequest) bundleComponent.getResource(); + } + if (bundleComponent.hasResource() + && ResourceType.Specimen.equals(bundleComponent.getResource().getResourceType())) { + specimen = (Specimen) bundleComponent.getResource(); + } + } + srBundle = (Bundle) localFhirClient + .search().forResource(ServiceRequest.class).where(ServiceRequest.IDENTIFIER.exactly() + .systemAndIdentifier(remotePath, externalOrderNumber)) + .include(ServiceRequest.INCLUDE_SPECIMEN).execute(); + for (BundleEntryComponent bundleComponent : srBundle.getEntry()) { + if (bundleComponent.hasResource() && ResourceType.ServiceRequest + .equals(bundleComponent.getResource().getResourceType())) { + serviceRequest = (ServiceRequest) bundleComponent.getResource(); + } + if (bundleComponent.hasResource() + && ResourceType.Specimen.equals(bundleComponent.getResource().getResourceType())) { + specimen = (Specimen) bundleComponent.getResource(); + } + } + } + if (serviceRequest != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching serviceRequest " + serviceRequest.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching serviceRequest"); + } + fhirPatient = localFhirClient.read()// + .resource(Patient.class)// + .withId(serviceRequest.getSubject().getReferenceElement().getIdPart())// + .execute(); + if (fhirPatient != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching patient " + fhirPatient.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching patient"); + } + task = fhirPersistanceService.getTaskBasedOnServiceRequest(externalOrderNumber).orElseThrow(); + if (task != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching task " + task.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching task"); + } + if (!GenericValidator.isBlankOrNull( + task.getRestriction().getRecipientFirstRep().getReferenceElement().getIdPart())) { + referringOrganization = localFhirClient.read()// + .resource(org.hl7.fhir.r4.model.Organization.class)// + .withId(task.getRestriction().getRecipientFirstRep().getReferenceElement().getIdPart())// + .execute(); + if (referringOrganization != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching organization " + referringOrganization.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching organization"); + } + } + if (!GenericValidator.isBlankOrNull( + serviceRequest.getLocationReferenceFirstRep().getReferenceElement().getIdPart())) { + location = localFhirClient.read()// + .resource(Location.class)// + .withId(serviceRequest.getLocationReferenceFirstRep().getReferenceElement().getIdPart())// + .execute(); + if (location != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching location " + location.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching location"); + } + } + if (!GenericValidator.isBlankOrNull(serviceRequest.getRequester().getReferenceElement().getIdPart()) + && serviceRequest.getRequester().getReference() + .contains(ResourceType.Practitioner.toString())) { + requesterPerson = localFhirClient.read()// + .resource(Practitioner.class)// + .withId(serviceRequest.getRequester().getReferenceElement().getIdPart())// + .execute(); + + if (requesterPerson != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching requester " + requesterPerson.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching requester"); + } + } + if (specimen != null && !GenericValidator + .isBlankOrNull(specimen.getCollection().getCollector().getReferenceElement().getIdPart())) { + collector = localFhirClient.read()// + .resource(Practitioner.class)// + .withId(specimen.getCollection().getCollector().getReferenceElement().getIdPart())// + .execute(); + + if (collector != null) { + LogEvent.logDebug(this.getClass().getName(), "processRequest", + "found matching collector " + collector.getIdElement().getIdPart()); + } else { + LogEvent.logDebug(this.getClass().getName(), "processRequest", "no matching collector"); + } + } + loadDataInForm(form); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void loadDataInForm(SampleEntryByProjectForm form) { + ProjectData projectData = new ProjectData(); + ObservationData observationData = new ObservationData(); + form.setBirthDateForDisplay(DateUtil.formatDateAsText(fhirPatient.getBirthDate())); + form.setGender(fhirPatient.getGender().getDisplay().substring(0, 1).toUpperCase()); + if (ObjectUtils.isNotEmpty(fhirPatient.getIdElement())) { + form.setPatientFhirUuid(fhirPatient.getIdElement().getIdPart()); + } + for (Identifier identifier : fhirPatient.getIdentifier()) { + if ((fhirConfig.getOeFhirSystem() + "/pat_subjectNumber").equals(identifier.getSystem())) { + form.setSubjectNumber(identifier.getValue()); + } + if ((fhirConfig.getOeFhirSystem() + "/pat_nationalId").equals(identifier.getSystem())) { + form.setSiteSubjectNumber(identifier.getValue()); + } + if ((OPENMRS_SYSTEM_URL + "/UPI").equals(identifier.getSystem())) { + form.setUpidCode(identifier.getValue()); + } + } + for (ParameterComponent parameter : task.getInput()) { + if (parameter.getType().getCodingFirstRep().getCode().equals("160533AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// currentARVTreatment + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType onARTTreatment = (StringType) parameter.getValue(); + if (onARTTreatment.getValue().equalsIgnoreCase("true")) { + observationData.setCurrentARVTreatment("1253"); + } else if (onARTTreatment.getValue().equalsIgnoreCase("false")) { + observationData.setCurrentARVTreatment("1251"); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("CI0050001AAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vlOtherReasonForRequest + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType vlOtherReasonForRequestType = (StringType) parameter.getValue(); + observationData.setVlOtherReasonForRequest(vlOtherReasonForRequestType.getValue()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("CI0050007AAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// sampleType + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType sampleTypeType = (StringType) parameter.getValue(); + if (sampleTypeType.getValue().equalsIgnoreCase("Plasma")) { + projectData.setEdtaTubeTaken(true); + } else if (sampleTypeType.getValue().equalsIgnoreCase("DBS")) { + projectData.setdbsvlTaken(true); + } else if (sampleTypeType.getValue().equalsIgnoreCase("PSC")) { + projectData.setPscvlTaken(true); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("166073AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// arvTreatmentRegime + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType arvTreatmentRegimeType = (StringType) parameter.getValue(); + if (arvTreatmentRegimeType.getValue().equalsIgnoreCase("Première")) { + observationData.setArvTreatmentRegime("1206"); + } else if (arvTreatmentRegimeType.getValue().equalsIgnoreCase("Deuxième")) { + observationData.setArvTreatmentRegime("1213"); + } else if (arvTreatmentRegimeType.getValue().equalsIgnoreCase("Troisième")) { + observationData.setArvTreatmentRegime("1219"); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("164792AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.initcd4Percent + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DecimalType) { + DecimalType initcd4PercentType = (DecimalType) parameter.getValue(); + observationData.setInitcd4Percent(initcd4PercentType.getValue().toString()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("730AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.demandcd4Percent + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DecimalType) { + DecimalType demandcd4PercentType = (DecimalType) parameter.getValue(); + observationData.setDemandcd4Percent(demandcd4PercentType.getValue().toString()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("163545AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.priorVLValue + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DecimalType) { + DecimalType priorVLValueType = (DecimalType) parameter.getValue(); + observationData.setPriorVLValue(priorVLValueType.getValue().toString()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("CI0030001AAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.hivStatus + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType hivStatusType = (StringType) parameter.getValue(); + if (hivStatusType.getValue().equalsIgnoreCase("VIH-1")) { + observationData.setHivStatus("1264"); + } else if (hivStatusType.getValue().equalsIgnoreCase("VIH-1+2")) { + observationData.setHivStatus("1263"); + } else if (hivStatusType.getValue().equalsIgnoreCase("VIH-2")) { + observationData.setHivStatus("1265"); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("159599AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.arvTreatmentInitDate + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DateTimeType) { + DateTimeType dateValue = (DateTimeType) parameter.getValue(); + observationData.setArvTreatmentInitDate(DateUtil.formatDateAsText(dateValue.getValue())); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("160103AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.demandcd4Date + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DateTimeType) { + DateTimeType dateValue = (DateTimeType) parameter.getValue(); + observationData.setDemandcd4Date(DateUtil.formatDateAsText(dateValue.getValue())); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("163281AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.priorVLDate + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DateTimeType) { + DateTimeType dateValue = (DateTimeType) parameter.getValue(); + observationData.setPriorVLDate(DateUtil.formatDateAsText(dateValue.getValue())); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("164429AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.initcd4Count + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DecimalType) { + DecimalType initcd4CountType = (DecimalType) parameter.getValue(); + observationData.setInitcd4Count(initcd4CountType.getValue().toString()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("5497AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.demandcd4Count + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DecimalType) { + DecimalType demandcd4CountType = (DecimalType) parameter.getValue(); + observationData.setDemandcd4Count(demandcd4CountType.getValue().toString()); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("159376AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.initcd4Date + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof DateTimeType) { + DateTimeType dateValue = (DateTimeType) parameter.getValue(); + observationData.setInitcd4Date(DateUtil.formatDateAsText(dateValue.getValue())); + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("CI0050004AAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// vl.vlBenefit + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType vlBenefitType = (StringType) parameter.getValue(); + if (vlBenefitType.getValue().equalsIgnoreCase("Oui") + || vlBenefitType.getValue().equalsIgnoreCase("Yes")) { + observationData.setVlBenefit("1253"); + } else if (vlBenefitType.getValue().equalsIgnoreCase("Non") + || vlBenefitType.getValue().equalsIgnoreCase("No")) { + observationData.setVlBenefit("1251"); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("162240AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// ARV + // Treatment + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType regimenType = (StringType) parameter.getValue(); + String regimen = regimenType.getValue(); + String[] regimenParts = regimen.split(" "); + for (int i = 0; i < regimenParts.length && i < 3; i++) { + observationData.setCurrentARVTreatmentINNs(i, regimenParts[i].trim()); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("5272AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// Pregnancy + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType vlPregnancyType = (StringType) parameter.getValue(); + if (vlPregnancyType.getValue().equalsIgnoreCase("Oui") + || vlPregnancyType.getValue().equalsIgnoreCase("Yes")) { + observationData.setVlPregnancy(("1253")); + } else if (vlPregnancyType.getValue().equalsIgnoreCase("Non") + || vlPregnancyType.getValue().equalsIgnoreCase("No")) { + observationData.setVlPregnancy("1251"); + } + } + } + } + if (parameter.getType().getCodingFirstRep().getCode().equals("5632AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) {// Breastfeeding + if (ObjectUtils.isNotEmpty(parameter.getValue())) { + if (parameter.getValue() instanceof StringType) { + StringType vlBreastFeedingType = (StringType) parameter.getValue(); + if (vlBreastFeedingType.getValue().equalsIgnoreCase("Oui") + || vlBreastFeedingType.getValue().equalsIgnoreCase("Yes")) { + observationData.setVlSuckle(("1253")); + } else if (vlBreastFeedingType.getValue().equalsIgnoreCase("Non") + || vlBreastFeedingType.getValue().equalsIgnoreCase("No")) { + observationData.setVlSuckle("1251"); + } + } + } + } + } + if (ObjectUtils.isNotEmpty(serviceRequest)) { + if (ObjectUtils.isNotEmpty(serviceRequest.getOccurrencePeriod())) { + Date startDate = serviceRequest.getOccurrencePeriod().getStart(); + form.setInterviewDate(DateUtil.formatDateAsText(startDate)); + } + } + + requesterPerson.getName().forEach(humanName -> { + String lastName = humanName.getFamily(); + String firstName = String.join("", + humanName.getGiven().stream().map(e -> e.asStringValue()).collect(Collectors.toList())); + observationData.setNameOfDoctor(lastName + " " + firstName); + }); + + projectData.setViralLoadTest(true); + form.setProjectData(projectData); + form.setObservations(observationData); + } + + @RequestMapping(value = "/SampleEntryByProject", method = RequestMethod.POST) + public ModelAndView postSampleEntryByProject(HttpServletRequest request, + @ModelAttribute("form") @Valid SampleEntryByProjectForm form, BindingResult result, + RedirectAttributes redirectAttributes) { + if (result.hasErrors()) { + saveErrors(result); + setDisplayLists(form); + return findForward(FWD_FAIL_INSERT, form); + } + String forward; + + + ISampleSecondEntry sampleSecondEntry = SpringContext.getBean(ISampleSecondEntry.class); + sampleSecondEntry.setFieldsFromForm(form); + sampleSecondEntry.setSysUserId(getSysUserId(request)); + sampleSecondEntry.setRequest(request); + if (sampleSecondEntry.canAccession()) { + forward = handleSave(request, sampleSecondEntry, form); + updateElectronicOrderStatus(form); + if (forward != null) { + if (FWD_SUCCESS_INSERT.equals(forward)) { + redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); + } else { + setDisplayLists(form); + } + return findForward(forward, form); + } + } + ISampleEntry sampleEntry = SpringContext.getBean(ISampleEntry.class); + sampleEntry.setFieldsFromForm(form); + sampleEntry.setSysUserId(getSysUserId(request)); + sampleEntry.setRequest(request); + if (sampleEntry.canAccession()) { + forward = handleSave(request, sampleEntry, form); + updateElectronicOrderStatus(form); + if (forward != null) { + if (FWD_SUCCESS_INSERT.equals(forward)) { + redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); + } else { + setDisplayLists(form); + } + return findForward(forward, form); + } + } + ISampleEntryAfterPatientEntry sampleEntryAfterPatientEntry = SpringContext + .getBean(ISampleEntryAfterPatientEntry.class); + sampleEntryAfterPatientEntry.setFieldsFromForm(form); + sampleEntryAfterPatientEntry.setSysUserId(getSysUserId(request)); + sampleEntryAfterPatientEntry.setRequest(request); + if (sampleEntryAfterPatientEntry.canAccession()) { + forward = handleSave(request, sampleEntryAfterPatientEntry, form); + updateElectronicOrderStatus(form); + if (forward != null) { + if (FWD_SUCCESS_INSERT.equals(forward)) { + redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); + } else { + setDisplayLists(form); + } + return findForward(forward, form); + } + } + logAndAddMessage(request, "postSampleEntryByProject", "errors.UpdateException"); + + setDisplayLists(form); + return findForward(FWD_FAIL_INSERT, form); + } + + private void updateElectronicOrderStatus(SampleEntryByProjectForm form) { + try { + if (ObjectUtils.isNotEmpty(form.getElectronicOrder())) { + String externalOrderId = form.getElectronicOrder().getExternalId(); + List eOrders = electronicOrderService.getElectronicOrdersByExternalId(externalOrderId); + if (eOrders.size() > 0) { + ElectronicOrder eOrder = eOrders.get(eOrders.size() - 1); + eOrder.setStatusId( + SpringContext.getBean(IStatusService.class).getStatusID(ExternalOrderStatus.Realized)); + electronicOrderService.update(eOrder); + form.setElectronicOrder(eOrder); + } + } + } catch (Exception e) { + e.printStackTrace(); + LogEvent.logError(e); + } + } + + public SampleItem getSampleItem(Sample sample, TypeOfSample typeofsample) { + SampleItem item = new SampleItem(); + item.setSample(sample); + item.setTypeOfSample(typeofsample); + item.setSortOrder(Integer.toString(1)); + item.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(SampleStatus.Entered)); + + return item; + } + + private void setDisplayLists(SampleEntryByProjectForm form) { + Map> formListsMapOfLists = new HashMap<>(); + List listOfDictionary = new ArrayList<>(); + List genders = DisplayListService.getInstance().getList(ListType.GENDERS); + + for (IdValuePair i : genders) { + Dictionary dictionary = new Dictionary(); + dictionary.setId(i.getId()); + dictionary.setDictEntry(i.getValue()); + listOfDictionary.add(dictionary); + } + + formListsMapOfLists.put("GENDERS", listOfDictionary); + form.setFormLists(formListsMapOfLists); + + // Get Lists + Map> observationHistoryMapOfLists = new HashMap<>(); + observationHistoryMapOfLists.put("EID_WHICH_PCR", ObservationHistoryList.EID_WHICH_PCR.getList()); + observationHistoryMapOfLists.put("EID_SECOND_PCR_REASON", + ObservationHistoryList.EID_SECOND_PCR_REASON.getList()); + observationHistoryMapOfLists.put("EID_TYPE_OF_CLINIC", ObservationHistoryList.EID_TYPE_OF_CLINIC.getList()); + observationHistoryMapOfLists.put("EID_HOW_CHILD_FED", ObservationHistoryList.EID_HOW_CHILD_FED.getList()); + observationHistoryMapOfLists.put("EID_STOPPED_BREASTFEEDING", + ObservationHistoryList.EID_STOPPED_BREASTFEEDING.getList()); + observationHistoryMapOfLists.put("YES_NO", ObservationHistoryList.YES_NO.getList()); + observationHistoryMapOfLists.put("EID_INFANT_PROPHYLAXIS_ARV", + ObservationHistoryList.EID_INFANT_PROPHYLAXIS_ARV.getList()); + observationHistoryMapOfLists.put("YES_NO_UNKNOWN", ObservationHistoryList.YES_NO_UNKNOWN.getList()); + observationHistoryMapOfLists.put("EID_MOTHERS_HIV_STATUS", + ObservationHistoryList.EID_MOTHERS_HIV_STATUS.getList()); + observationHistoryMapOfLists.put("EID_MOTHERS_ARV_TREATMENT", + ObservationHistoryList.EID_MOTHERS_ARV_TREATMENT.getList()); + observationHistoryMapOfLists.put("HIV_STATUSES", ObservationHistoryList.HIV_STATUSES.getList()); + observationHistoryMapOfLists.put("HIV_TYPES", ObservationHistoryList.HIV_TYPES.getList()); + observationHistoryMapOfLists.put("SPECIAL_REQUEST_REASONS", + ObservationHistoryList.SPECIAL_REQUEST_REASONS.getList()); + observationHistoryMapOfLists.put("ARV_REGIME", ObservationHistoryList.ARV_REGIME.getList()); + observationHistoryMapOfLists.put("ARV_REASON_FOR_VL_DEMAND", + ObservationHistoryList.ARV_REASON_FOR_VL_DEMAND.getList()); + + form.setDictionaryLists(observationHistoryMapOfLists); + + // Get EID Sites + Map> organizationTypeMapOfLists = new HashMap<>(); + organizationTypeMapOfLists.put("ARV_ORGS", OrganizationTypeList.ARV_ORGS.getList()); + organizationTypeMapOfLists.put("ARV_ORGS_BY_NAME", OrganizationTypeList.ARV_ORGS_BY_NAME.getList()); + organizationTypeMapOfLists.put("EID_ORGS_BY_NAME", OrganizationTypeList.EID_ORGS_BY_NAME.getList()); + organizationTypeMapOfLists.put("EID_ORGS", OrganizationTypeList.EID_ORGS.getList()); + form.setOrganizationTypeLists(organizationTypeMapOfLists); + } + + @Override + protected String findLocalForward(String forward) { + if (FWD_SUCCESS.equals(forward)) { + return "sampleEntryByProjectDefinition"; + } else if (FWD_FAIL.equals(forward)) { + return "homePageDefinition"; + } else if (FWD_SUCCESS_INSERT.equals(forward)) { + return "redirect:/SampleEntryByProject?type=" + Encode.forUriComponent(request.getParameter("type")); + } else if (FWD_FAIL_INSERT.equals(forward)) { + return "sampleEntryByProjectDefinition"; + } else { + return "PageNotFound"; + } + } + + @Override + protected String getPageTitleKey() { + return null; + } + + @Override + protected String getPageSubtitleKey() { + return null; + } } diff --git a/src/main/java/org/openelisglobal/sample/controller/SamplePatientEntryController.java b/src/main/java/org/openelisglobal/sample/controller/SamplePatientEntryController.java index 77b36f183e..8e601cc519 100644 --- a/src/main/java/org/openelisglobal/sample/controller/SamplePatientEntryController.java +++ b/src/main/java/org/openelisglobal/sample/controller/SamplePatientEntryController.java @@ -220,7 +220,7 @@ private void setupReferralOption(SamplePatientEntryForm form) { if (!org.apache.commons.validator.GenericValidator.isBlankOrNull(sampleOrder.getReceivedTime())) { receivedDateForDisplay += " " + sampleOrder.getReceivedTime(); } else { - receivedDateForDisplay += " 00:00"; + receivedDateForDisplay += " 09:00"; } updateData.setCollectionDateFromRecieveDateIfNeeded(receivedDateForDisplay); diff --git a/src/main/java/org/openelisglobal/sample/controller/SampleTbEntryController.java b/src/main/java/org/openelisglobal/sample/controller/SampleTbEntryController.java new file mode 100644 index 0000000000..c2960bbba2 --- /dev/null +++ b/src/main/java/org/openelisglobal/sample/controller/SampleTbEntryController.java @@ -0,0 +1,277 @@ +package org.openelisglobal.sample.controller; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.validator.GenericValidator; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.ServiceRequest; +import org.hl7.fhir.r4.model.Specimen; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.ParameterComponent; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.DateTimeType; +import org.openelisglobal.common.action.IActionConstants; +import org.openelisglobal.common.constants.Constants; +import org.openelisglobal.common.log.LogEvent; +import org.openelisglobal.common.services.DisplayListService; +import org.openelisglobal.common.services.DisplayListService.ListType; +import org.openelisglobal.common.services.IStatusService; +import org.openelisglobal.common.services.StatusService.ExternalOrderStatus; +import org.openelisglobal.common.services.StatusService.OrderStatus; +import org.openelisglobal.common.services.StatusService.SampleStatus; +import org.openelisglobal.common.util.DateUtil; +import org.openelisglobal.common.util.IdValuePair; +import org.openelisglobal.dataexchange.fhir.FhirConfig; +import org.openelisglobal.dataexchange.fhir.FhirUtil; +import org.openelisglobal.dataexchange.fhir.service.FhirPersistanceService; +import org.openelisglobal.dataexchange.fhir.service.FhirTransformService; +import org.openelisglobal.dataexchange.order.valueholder.ElectronicOrder; +import org.openelisglobal.dataexchange.service.order.ElectronicOrderService; +import org.openelisglobal.dictionary.ObservationHistoryList; +import org.openelisglobal.dictionary.valueholder.Dictionary; +import org.openelisglobal.internationalization.MessageUtil; +import org.openelisglobal.organization.service.OrganizationService; +import org.openelisglobal.organization.util.OrganizationTypeList; +import org.openelisglobal.organization.valueholder.Organization; +import org.openelisglobal.panel.service.PanelService; +import org.openelisglobal.panel.valueholder.Panel; +import org.openelisglobal.panelitem.service.PanelItemService; +import org.openelisglobal.panelitem.valueholder.PanelItem; +import org.openelisglobal.patient.form.PatientEntryByProjectForm; +import org.openelisglobal.patient.saving.ISampleEntry; +import org.openelisglobal.patient.saving.ISampleEntryAfterPatientEntry; +import org.openelisglobal.patient.saving.ISampleSecondEntry; +import org.openelisglobal.patient.valueholder.ObservationData; +import org.openelisglobal.provider.service.ProviderService; +import org.openelisglobal.sample.form.ProjectData; +import org.openelisglobal.sample.form.SampleEntryByProjectForm; +import org.openelisglobal.sample.form.SampleTbEntryForm; +import org.openelisglobal.sample.service.TbSampleService; +import org.openelisglobal.sample.valueholder.Sample; +import org.openelisglobal.sampleitem.valueholder.SampleItem; +import org.openelisglobal.spring.util.SpringContext; +import org.openelisglobal.statusofsample.valueholder.StatusOfSample; +import org.openelisglobal.systemuser.service.UserService; +import org.openelisglobal.test.service.TestService; +import org.openelisglobal.test.valueholder.Test; +import org.openelisglobal.typeofsample.valueholder.TypeOfSample; +import org.owasp.encoder.Encode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import ca.uhn.fhir.rest.client.api.IGenericClient; + +@Controller +public class SampleTbEntryController extends BaseSampleEntryController { + + @Value("${org.openelisglobal.requester.identifier:}") + private String requestFhirUuid; + + @Autowired + private ElectronicOrderService electronicOrderService; + @Autowired + private OrganizationService organizationService; + @Autowired + private FhirPersistanceService fhirPersistanceService; + + @Autowired + private FhirConfig fhirConfig; + @Autowired + private FhirUtil fhirUtil; + @Autowired + private UserService userService; + @Autowired + private TestService testService; + @Autowired + private PanelService panelService; + @Autowired + private TbSampleService tbSampleService; + + @Autowired + private PanelItemService panelItemService; + + private Task task = null; + private Practitioner requesterPerson = null; + private Practitioner collector = null; + private org.hl7.fhir.r4.model.Organization referringOrganization = null; + private Location location = null; + private ServiceRequest serviceRequest = null; + private Specimen specimen = null; + private Patient fhirPatient = null; + + private static final String[] ALLOWED_FIELDS = new String[] {}; + + @InitBinder + public void initBinder(WebDataBinder binder) { + binder.setAllowedFields(ALLOWED_FIELDS); + } + + @RequestMapping(value = "/MicrobiologyTb", method = RequestMethod.GET) + public ModelAndView showSampleEntryByProject(HttpServletRequest request) { + SampleTbEntryForm form = new SampleTbEntryForm(); + request.setAttribute(IActionConstants.PAGE_SUBTITLE_KEY, MessageUtil.getMessage("add.tb.sample.title")); + + Date today = Calendar.getInstance().getTime(); + String dateAsText = DateUtil.formatDateAsText(today); + form.setReceivedDate(dateAsText); + + setDisplayLists(form); + addFlashMsgsToRequest(request); + + return findForward(FWD_SUCCESS, form); + } + + @RequestMapping(value = "/MicrobiologyTb", method = RequestMethod.POST) + public ModelAndView postTbSampleEntryByProject(HttpServletRequest request, + @ModelAttribute("form") @Valid SampleTbEntryForm form, BindingResult result, + RedirectAttributes redirectAttributes) { + if (result.hasErrors()) { + saveErrors(result); + setDisplayLists(form); + return findForward(FWD_FAIL_INSERT, form); + } + form.setSysUserId(this.getSysUserId(request)); + if (tbSampleService.persistTbData(form, request)) { + redirectAttributes.addFlashAttribute(FWD_SUCCESS, true); + setDisplayLists(form); + return findForward(FWD_SUCCESS_INSERT, form); + } + logAndAddMessage(request, "postTbSampleEntryByProject", "errors.UpdateException"); + + return findForward(FWD_FAIL_INSERT, form); + } + + private void setDisplayLists(SampleTbEntryForm form) { + List listOfDictionary = new ArrayList<>(); + List genders = DisplayListService.getInstance().getList(ListType.GENDERS); + + for (IdValuePair i : genders) { + Dictionary dictionary = new Dictionary(); + dictionary.setId(i.getId()); + dictionary.setDictEntry(i.getValue()); + listOfDictionary.add(dictionary); + } + + form.setGenders(genders); + form.setReferralOrganizations( + DisplayListService.getInstance().getList(ListType.SAMPLE_PATIENT_REFERRING_CLINIC)); + form.setTbSpecimenNatures( + userService.getUserSampleTypes(getSysUserId(request), Constants.ROLE_RECEPTION, "TB")); + form.setTestSectionList(DisplayListService.getInstance().getList(ListType.TEST_SECTION_ACTIVE)); + form.setCurrentDate(DateUtil.getCurrentDateAsText()); + form.setRejectReasonList(DisplayListService.getInstance().getList(ListType.REJECTION_REASONS)); + form.setTbOrderReasons(DisplayListService.getInstance().getList(ListType.TB_ORDER_REASONS)); + form.setTbDiagnosticReasons(DisplayListService.getInstance().getList(ListType.TB_DIAGNOSTIC_REASONS)); + form.setTbFollowupReasons(DisplayListService.getInstance().getList(ListType.TB_FOLLOWUP_REASONS)); + form.setTbDiagnosticMethods(DisplayListService.getInstance().getList(ListType.TB_ANALYSIS_METHODS)); + form.setTbAspects(DisplayListService.getInstance().getList(ListType.TB_SAMPLE_ASPECTS)); + form.setTbFollowupPeriodsLine1(DisplayListService.getInstance().getList(ListType.TB_FOLLOWUP_LINE1)); + form.setTbFollowupPeriodsLine2(DisplayListService.getInstance().getList(ListType.TB_FOLLOWUP_LINE2)); + + } + + @GetMapping(value = "MicrobiologyTb/panel_test") + public ResponseEntity> getPanelTestsElement(@RequestParam("method") String method) { + Map response = new HashMap(); + try { + List tests = testService.getTbTestByMethod(method); + List panels = testService.getTbPanelsByMethod(method); + List> testsList = new ArrayList>(); + List> panelsList = new ArrayList>(); + tests.forEach(test -> { + Map el = new HashMap(); + el.put("id", test.getId()); + el.put("name", test.getLocalizedName()); + List pItems = panelItemService.getPanelItemByTestId(test.getId()); + pItems.forEach(item -> { + int idxPanel = 0; + Map sPanel = new HashMap(); + for (int k = 0; k < panelsList.size(); k++) { + if (panelsList.get(k).get("name").equals(item.getPanel().getLocalizedName())) { + sPanel = panelsList.get(k); + idxPanel = k; + break; + } + } + if (ObjectUtils.isEmpty(sPanel)) { + sPanel.put("name", item.getPanel().getLocalizedName()); + sPanel.put("id", item.getPanel().getId()); + sPanel.put("test_ids", "" + test.getId()); + panelsList.add(sPanel); + } else { + sPanel.put("test_ids", sPanel.get("test_ids") + "," + test.getId()); + panelsList.set(idxPanel, sPanel); + } + }); + testsList.add(el); + }); + + List> newPanelsList = new ArrayList>(); + List realPanelIds = panels.stream().map(p -> p.getId()).collect(Collectors.toList()); + panelsList.forEach(elm -> { + if (realPanelIds.contains(elm.get("id"))) { + newPanelsList.add(elm); + } + }); + + response.put("tests", testsList); + response.put("panels", newPanelsList); + } catch (Exception e) { + e.printStackTrace(); + } + return new ResponseEntity<>(response, HttpStatus.OK); + } + + @Override + protected String findLocalForward(String forward) { + if (FWD_SUCCESS.equals(forward)) { + return "sampleTbEntryDefinition"; + } else if (FWD_SUCCESS_INSERT.equals(forward)) { + return "redirect:/MicrobiologyTb"; + } else if (FWD_FAIL_INSERT.equals(forward)) { + return "homePageDefinition"; + } else { + return "PageNotFound"; + } + } + + @Override + protected String getPageTitleKey() { + return null; + } + + @Override + protected String getPageSubtitleKey() { + return null; + } +} diff --git a/src/main/java/org/openelisglobal/sample/form/ProjectData.java b/src/main/java/org/openelisglobal/sample/form/ProjectData.java index a9e175ffca..bd35fee731 100644 --- a/src/main/java/org/openelisglobal/sample/form/ProjectData.java +++ b/src/main/java/org/openelisglobal/sample/form/ProjectData.java @@ -66,6 +66,9 @@ public ProjectData() { private boolean dbsTaken; private boolean dbsvlTaken; private boolean pscvlTaken; + private boolean asanteTest; + private boolean plasmaTaken; + private boolean serumTaken; // ARV private String doctor; @@ -671,4 +674,36 @@ public boolean isPscvlTaken() { public void setPscvlTaken(boolean pscvlTaken) { this.pscvlTaken = pscvlTaken; } + + public boolean isDbsvlTaken() { + return dbsvlTaken; + } + + public void setDbsvlTaken(boolean dbsvlTaken) { + this.dbsvlTaken = dbsvlTaken; + } + + public boolean isPlasmaTaken() { + return plasmaTaken; + } + + public void setPlasmaTaken(boolean plasmaTaken) { + this.plasmaTaken = plasmaTaken; + } + + public boolean isSerumTaken() { + return serumTaken; + } + + public void setSerumTaken(boolean serumTaken) { + this.serumTaken = serumTaken; + } + + public boolean isAsanteTest() { + return asanteTest; + } + + public void setAsanteTest(boolean asanteTest) { + this.asanteTest = asanteTest; + } } diff --git a/src/main/java/org/openelisglobal/sample/form/SampleEntryByProjectForm.java b/src/main/java/org/openelisglobal/sample/form/SampleEntryByProjectForm.java index 648b7a059c..ec5b5833bd 100644 --- a/src/main/java/org/openelisglobal/sample/form/SampleEntryByProjectForm.java +++ b/src/main/java/org/openelisglobal/sample/form/SampleEntryByProjectForm.java @@ -15,6 +15,7 @@ import org.openelisglobal.common.util.IdValuePair; import org.openelisglobal.common.util.validator.CustomDateValidator.DateRelation; import org.openelisglobal.common.validator.ValidationHelper; +import org.openelisglobal.dataexchange.order.valueholder.ElectronicOrder; import org.openelisglobal.dictionary.valueholder.Dictionary; import org.openelisglobal.organization.valueholder.Organization; import org.openelisglobal.patient.action.IPatientUpdate.PatientUpdateStatus; @@ -27,316 +28,350 @@ public class SampleEntryByProjectForm extends BaseForm implements IAccessionerForm { - @ValidDate(relative = DateRelation.TODAY) - private String currentDate = ""; + private static final long serialVersionUID = 1L; - @ValidDate(relative = DateRelation.PAST) - private String receivedDateForDisplay = ""; + @ValidDate(relative = DateRelation.TODAY) + private String currentDate = ""; - @ValidDate(relative = DateRelation.PAST) - private String receivedTimeForDisplay = ""; + @ValidDate(relative = DateRelation.PAST) + private String receivedDateForDisplay = ""; - @ValidDate(relative = DateRelation.PAST) - private String interviewDate = ""; + @ValidTime + private String receivedTimeForDisplay = ""; - @ValidTime - private String interviewTime = ""; + @ValidDate(relative = DateRelation.PAST) + private String interviewDate = ""; - @SafeHtml(level = SafeHtml.SafeListLevel.NONE) - private String project = ""; + @ValidTime + private String interviewTime = ""; - @ValidAccessionNumber(format = AccessionFormat.PROGRAMNUM/* , dateValidate = true */) - private String labNo = ""; + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String project = ""; - @SafeHtml(level = SafeHtml.SafeListLevel.NONE) - private String doctor = ""; + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String patientFhirUuid = ""; - // @NotBlank - @Size(max = 7) - @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) - private String subjectNumber = ""; + @ValidAccessionNumber(format = AccessionFormat.PROGRAMNUM/* , dateValidate = true */) + private String labNo = ""; - @NotBlank - @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) - private String siteSubjectNumber = ""; + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String doctor = ""; - @NotBlank - @Pattern(regexp = ValidationHelper.GENDER_REGEX) - private String gender = ""; + // @NotBlank + @Size(max = 10) + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String subjectNumber = ""; - @ValidDate(relative = DateRelation.PAST) - private String birthDateForDisplay = ""; + //@NotBlank may be subjectNumber or siteSubjectNumber + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String siteSubjectNumber = ""; - @Pattern(regexp = ValidationHelper.ID_REGEX) - private String samplePK = ""; + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String upidCode = ""; - @Pattern(regexp = ValidationHelper.ID_REGEX) - private String patientPK = ""; + @NotBlank + @Pattern(regexp = ValidationHelper.GENDER_REGEX) + private String gender = ""; - private PatientUpdateStatus patientUpdateStatus = PatientUpdateStatus.ADD; + @ValidDate(relative = DateRelation.PAST) + private String birthDateForDisplay = ""; - @SafeHtml(level = SafeHtml.SafeListLevel.NONE) - private String patientLastUpdated = ""; + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String samplePK = ""; - @SafeHtml(level = SafeHtml.SafeListLevel.NONE) - private String personLastUpdated = ""; + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String patientPK = ""; - @Valid - private ProjectData ProjectData; + private PatientUpdateStatus patientUpdateStatus = PatientUpdateStatus.ADD; - @Valid - private ObservationData observations; + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String patientLastUpdated = ""; - @Min(0) - private Integer centerCode; + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String personLastUpdated = ""; - // for display - private Map> organizationTypeLists; + @Valid + private ProjectData ProjectData; - // for display - private Map> dictionaryLists; + @Valid + private ObservationData observations; - // for display - private Map> formLists; + private ElectronicOrder electronicOrder = null; - // for display - private List genders; + @Min(0) + private Integer centerCode; - // for display - private PatientSearch patientSearch; + // for display + private Map> organizationTypeLists; - @SafeHtml(level = SafeHtml.SafeListLevel.NONE) - private String domain = ""; + // for display + private Map> dictionaryLists; - public SampleEntryByProjectForm() { - setFormName("sampleEntryByProjectForm"); - } + // for display + private Map> formLists; - public String getDomain() { - return domain; - } + // for display + private List genders; - public void setDomain(String domain) { - this.domain = domain; - } + // for display + private PatientSearch patientSearch; - public String getCurrentDate() { - return currentDate; - } + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String domain = ""; - public void setCurrentDate(String currentDate) { - this.currentDate = currentDate; - } + public SampleEntryByProjectForm() { + setFormName("sampleEntryByProjectForm"); + } - @Override - public String getReceivedDateForDisplay() { - return receivedDateForDisplay; - } + public String getDomain() { + return domain; + } - public void setReceivedDateForDisplay(String receivedDateForDisplay) { - this.receivedDateForDisplay = receivedDateForDisplay; - } + public void setDomain(String domain) { + this.domain = domain; + } - @Override - public String getReceivedTimeForDisplay() { - return receivedTimeForDisplay; - } + public String getCurrentDate() { + return currentDate; + } - public void setReceivedTimeForDisplay(String receivedTimeForDisplay) { - this.receivedTimeForDisplay = receivedTimeForDisplay; - } + public void setCurrentDate(String currentDate) { + this.currentDate = currentDate; + } - @Override - public String getInterviewDate() { - return interviewDate; - } + @Override + public String getReceivedDateForDisplay() { + return receivedDateForDisplay; + } - public void setInterviewDate(String interviewDate) { - this.interviewDate = interviewDate; - } + public void setReceivedDateForDisplay(String receivedDateForDisplay) { + this.receivedDateForDisplay = receivedDateForDisplay; + } - @Override - public String getInterviewTime() { - return interviewTime; - } + @Override + public String getReceivedTimeForDisplay() { + return receivedTimeForDisplay; + } - public void setInterviewTime(String interviewTime) { - this.interviewTime = interviewTime; - } + public void setReceivedTimeForDisplay(String receivedTimeForDisplay) { + this.receivedTimeForDisplay = receivedTimeForDisplay; + } - public String getProject() { - return project; - } + @Override + public String getInterviewDate() { + return interviewDate; + } - public void setProject(String project) { - this.project = project; - } + public void setInterviewDate(String interviewDate) { + this.interviewDate = interviewDate; + } - @Override - public String getLabNo() { - return labNo; - } - - @Override - public void setLabNo(String labNo) { - this.labNo = labNo; - } - - public String getDoctor() { - return doctor; - } - - public void setDoctor(String doctor) { - this.doctor = doctor; - } - - @Override - public String getSubjectNumber() { - return subjectNumber; - } - - @Override - public void setSubjectNumber(String subjectNumber) { - this.subjectNumber = subjectNumber; - } - - @Override - public String getSiteSubjectNumber() { - return siteSubjectNumber; - } - - @Override - public void setSiteSubjectNumber(String siteSubjectNumber) { - this.siteSubjectNumber = siteSubjectNumber; - } - - public String getGender() { - return gender; - } - - public void setGender(String gender) { - this.gender = gender; - } - - public List getGenders() { - return genders; - } - - public void setGenders(List genders) { - this.genders = genders; - } - - @Override - public String getBirthDateForDisplay() { - return birthDateForDisplay; - } - - @Override - public void setBirthDateForDisplay(String birthDateForDisplay) { - this.birthDateForDisplay = birthDateForDisplay; - } - - @Override - public String getSamplePK() { - return samplePK; - } - - public void setSamplePK(String samplePK) { - this.samplePK = samplePK; - } - - @Override - public String getPatientPK() { - return patientPK; - } - - public void setPatientPK(String patientPK) { - this.patientPK = patientPK; - } - - public PatientUpdateStatus getPatientUpdateStatus() { - return patientUpdateStatus; - } - - public void setPatientUpdateStatus(PatientUpdateStatus patientUpdateStatus) { - this.patientUpdateStatus = patientUpdateStatus; - } - - public String getPatientLastUpdated() { - return patientLastUpdated; - } - - public void setPatientLastUpdated(String patientLastUpdated) { - this.patientLastUpdated = patientLastUpdated; - } - - public String getPersonLastUpdated() { - return personLastUpdated; - } - - public void setPersonLastUpdated(String personLastUpdated) { - this.personLastUpdated = personLastUpdated; - } - - @Override - public ProjectData getProjectData() { - return ProjectData; - } - - @Override - public void setProjectData(ProjectData projectData) { - ProjectData = projectData; - } - - @Override - public ObservationData getObservations() { - return observations; - } - - @Override - public void setObservations(ObservationData observations) { - this.observations = observations; - } - - public Map> getOrganizationTypeLists() { - return organizationTypeLists; - } - - public void setOrganizationTypeLists(Map> organizationTypeLists) { - this.organizationTypeLists = organizationTypeLists; - } - - public Map> getDictionaryLists() { - return dictionaryLists; - } - - public void setDictionaryLists(Map> dictionaryLists) { - this.dictionaryLists = dictionaryLists; - } - - public Map> getFormLists() { - return formLists; - } - - public void setFormLists(Map> formLists) { - this.formLists = formLists; - } - - public PatientSearch getPatientSearch() { - return patientSearch; - } - - public void setPatientSearch(PatientSearch patientSearch) { - this.patientSearch = patientSearch; - } - - @Override - public Integer getCenterCode() { - return centerCode; - } - - public void setCenterCode(Integer centerCode) { - this.centerCode = centerCode; - } + @Override + public String getInterviewTime() { + return interviewTime; + } + + public void setInterviewTime(String interviewTime) { + this.interviewTime = interviewTime; + } + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + + @Override + public String getLabNo() { + return labNo; + } + + @Override + public void setLabNo(String labNo) { + this.labNo = labNo; + } + + public String getDoctor() { + return doctor; + } + + public void setDoctor(String doctor) { + this.doctor = doctor; + } + + @Override + public String getSubjectNumber() { + return subjectNumber; + } + + @Override + public void setSubjectNumber(String subjectNumber) { + this.subjectNumber = subjectNumber; + } + + @Override + public String getSiteSubjectNumber() { + return siteSubjectNumber; + } + + @Override + public void setSiteSubjectNumber(String siteSubjectNumber) { + this.siteSubjectNumber = siteSubjectNumber; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public List getGenders() { + return genders; + } + + public void setGenders(List genders) { + this.genders = genders; + } + + @Override + public String getBirthDateForDisplay() { + return birthDateForDisplay; + } + + @Override + public void setBirthDateForDisplay(String birthDateForDisplay) { + this.birthDateForDisplay = birthDateForDisplay; + } + + @Override + public String getSamplePK() { + return samplePK; + } + + public void setSamplePK(String samplePK) { + this.samplePK = samplePK; + } + + @Override + public String getPatientPK() { + return patientPK; + } + + public void setPatientPK(String patientPK) { + this.patientPK = patientPK; + } + + public PatientUpdateStatus getPatientUpdateStatus() { + return patientUpdateStatus; + } + + public void setPatientUpdateStatus(PatientUpdateStatus patientUpdateStatus) { + this.patientUpdateStatus = patientUpdateStatus; + } + + public String getPatientLastUpdated() { + return patientLastUpdated; + } + + public void setPatientLastUpdated(String patientLastUpdated) { + this.patientLastUpdated = patientLastUpdated; + } + + public String getPersonLastUpdated() { + return personLastUpdated; + } + + public void setPersonLastUpdated(String personLastUpdated) { + this.personLastUpdated = personLastUpdated; + } + + @Override + public ProjectData getProjectData() { + return ProjectData; + } + + @Override + public void setProjectData(ProjectData projectData) { + ProjectData = projectData; + } + + @Override + public ObservationData getObservations() { + return observations; + } + + @Override + public void setObservations(ObservationData observations) { + this.observations = observations; + } + + public Map> getOrganizationTypeLists() { + return organizationTypeLists; + } + + public void setOrganizationTypeLists(Map> organizationTypeLists) { + this.organizationTypeLists = organizationTypeLists; + } + + public Map> getDictionaryLists() { + return dictionaryLists; + } + + public void setDictionaryLists(Map> dictionaryLists) { + this.dictionaryLists = dictionaryLists; + } + + public Map> getFormLists() { + return formLists; + } + + public void setFormLists(Map> formLists) { + this.formLists = formLists; + } + + public PatientSearch getPatientSearch() { + return patientSearch; + } + + public void setPatientSearch(PatientSearch patientSearch) { + this.patientSearch = patientSearch; + } + + @Override + public Integer getCenterCode() { + return centerCode; + } + + public void setCenterCode(Integer centerCode) { + this.centerCode = centerCode; + } + + public ElectronicOrder getElectronicOrder() { + return electronicOrder; + } + + public void setElectronicOrder(ElectronicOrder electronicOrder) { + this.electronicOrder = electronicOrder; + } + + public String getPatientFhirUuid() { + return patientFhirUuid; + } + + public void setPatientFhirUuid(String patientFhirUuid) { + this.patientFhirUuid = patientFhirUuid; + } + + public String getUpidCode() { + return upidCode; + } + + public void setUpidCode(String upidCode) { + this.upidCode = upidCode; + } } diff --git a/src/main/java/org/openelisglobal/sample/form/SampleTbEntryForm.java b/src/main/java/org/openelisglobal/sample/form/SampleTbEntryForm.java new file mode 100644 index 0000000000..e30838f246 --- /dev/null +++ b/src/main/java/org/openelisglobal/sample/form/SampleTbEntryForm.java @@ -0,0 +1,608 @@ +package org.openelisglobal.sample.form; + +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +import org.openelisglobal.common.form.BaseForm; +import org.openelisglobal.common.util.IdValuePair; +import org.openelisglobal.common.util.validator.CustomDateValidator.DateRelation; +import org.openelisglobal.common.validator.ValidationHelper; +import org.openelisglobal.validation.annotations.SafeHtml; +import org.openelisglobal.validation.annotations.SafeHtml.SafeListLevel; +import org.openelisglobal.validation.annotations.ValidAccessionNumber; +import org.openelisglobal.validation.annotations.ValidDate; +import org.openelisglobal.validation.annotations.ValidName; +import org.openelisglobal.validation.annotations.ValidTime; +import org.openelisglobal.validation.constraintvalidator.NameValidator.NameType; + +public class SampleTbEntryForm extends BaseForm { + + private static final long serialVersionUID = 1L; + + private Boolean rememberSiteAndRequester; + + private String sysUserId; + + @ValidDate(relative = DateRelation.TODAY) + private String currentDate = ""; + + // for display + private List referralOrganizations; + + private List genders; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String tbOrderReason; + + private List tbOrderReasons; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String tbDiagnosticReason; + + private List tbDiagnosticReasons; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String tbFollowupReason; + + private List tbFollowupReasons; + + @SafeHtml(level = SafeListLevel.NONE) + private String tbFollowupPeriodLine1; + + @SafeHtml(level = SafeListLevel.NONE) + private String tbFollowupPeriodLine2; + + private List tbFollowupPeriodsLine1; + + private List tbFollowupPeriodsLine2; + + private List tbDiagnosticMethods; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String tbAspect; + + private List tbAspects; + + // for display + private List sampleTypes; + + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String patientPK; + + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String guid; +// private UUID fhirUuid; + + @NotBlank() + @Pattern(regexp = ValidationHelper.GENDER_REGEX) + private String patientGender; + // ages are display only + private String patientAge; + + @ValidDate(relative = DateRelation.PAST) + private String patientBirthDate = ""; + + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String requesterName; + + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String externalOrderNumber; + + @NotBlank() + @ValidAccessionNumber() + private String labNo; + + @ValidDate(relative = DateRelation.PAST) + private String requestDate; + + @NotEmpty() + private List newSelectedTests; + + @NotBlank() + private String selectedTbMethod; + + //for updates + private List selectedTestToRemove; + + //for updates + private String selectedMethodToRemove; + + @NotBlank() + @ValidDate(relative = DateRelation.PAST) + private String receivedDate; + + @ValidTime() + private String receivedTime; + + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String referringPatientNumber; + + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String referringSiteCode; + + @SafeHtml() + private String referringSiteName; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String providerPersonId; + + @ValidName(nameType = NameType.FIRST_NAME) + private String providerFirstName; + + @ValidName(nameType = NameType.LAST_NAME) + private String providerLastName; + + @ValidName(nameType = NameType.FIRST_NAME) + private String patientFirstName; + + @ValidName(nameType = NameType.LAST_NAME) + private String patientLastName; + + @Pattern(regexp = ValidationHelper.PHONE_REGEX) + private String patientPhone; + + @SafeHtml(level = SafeHtml.SafeListLevel.NONE) + private String patientAddress; + + @Pattern(regexp = ValidationHelper.PATIENT_ID_REGEX) + private String tbSubjectNumber; + + @NotNull() + private Boolean modified = false; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String sampleId; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String tbSpecimenNature; + + private List tbSpecimenNatures; + + @Pattern(regexp = ValidationHelper.ID_REGEX) + private String rejectReason; + + + private boolean readOnly = false; + + // for display + private List testSectionList; + + // for display + private List rejectReasonList; + + public SampleTbEntryForm() { + setFormName("sampleTbEntryForm"); + } + + public Boolean getRememberSiteAndRequester() { + return rememberSiteAndRequester; + } + + public void setRememberSiteAndRequester(Boolean rememberSiteAndRequester) { + this.rememberSiteAndRequester = rememberSiteAndRequester; + } + + public String getCurrentDate() { + return currentDate; + } + + public void setCurrentDate(String currentDate) { + this.currentDate = currentDate; + } + + public List getReferralOrganizations() { + return referralOrganizations; + } + + public void setReferralOrganizations(List referralOrganizations) { + this.referralOrganizations = referralOrganizations; + } + + public List getSampleTypes() { + return sampleTypes; + } + + public void setSampleTypes(List sampleTypes) { + this.sampleTypes = sampleTypes; + } + + public String getPatientPK() { + return patientPK; + } + + public void setPatientPK(String patientPK) { + this.patientPK = patientPK; + } + + public String getGuid() { + return guid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + + public String getExternalOrderNumber() { + return externalOrderNumber; + } + + public void setExternalOrderNumber(String externalOrderNumber) { + this.externalOrderNumber = externalOrderNumber; + } + + public String getLabNo() { + return labNo; + } + + public void setLabNo(String labNo) { + this.labNo = labNo; + } + + public String getRequestDate() { + return requestDate; + } + + public void setRequestDate(String requestDate) { + this.requestDate = requestDate; + } + + public String getReceivedTime() { + return receivedTime; + } + + public void setReceivedTime(String receivedTime) { + this.receivedTime = receivedTime; + } + + public String getReferringPatientNumber() { + return referringPatientNumber; + } + + public void setReferringPatientNumber(String referringPatientNumber) { + this.referringPatientNumber = referringPatientNumber; + } + + public String getReferringSiteCode() { + return referringSiteCode; + } + + public void setReferringSiteCode(String referringSiteCode) { + this.referringSiteCode = referringSiteCode; + } + + public String getReferringSiteName() { + return referringSiteName; + } + + public void setReferringSiteName(String referringSiteName) { + this.referringSiteName = referringSiteName; + } + + public String getProviderPersonId() { + return providerPersonId; + } + + public void setProviderPersonId(String providerPersonId) { + this.providerPersonId = providerPersonId; + } + + public String getProviderFirstName() { + return providerFirstName; + } + + public void setProviderFirstName(String providerFirstName) { + this.providerFirstName = providerFirstName; + } + + public String getProviderLastName() { + return providerLastName; + } + + public void setProviderLastName(String providerLastName) { + this.providerLastName = providerLastName; + } + + public Boolean getModified() { + return modified; + } + + public void setModified(Boolean modified) { + this.modified = modified; + } + + public String getSampleId() { + return sampleId; + } + + public void setSampleId(String sampleId) { + this.sampleId = sampleId; + } + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public List getTestSectionList() { + return testSectionList; + } + + public void setTestSectionList(List testSectionList) { + this.testSectionList = testSectionList; + } + + public List getRejectReasonList() { + return rejectReasonList; + } + + public void setRejectReasonList(List rejectReasonList) { + this.rejectReasonList = rejectReasonList; + } + + public List getGenders() { + return genders; + } + + public void setGenders(List genders) { + this.genders = genders; + } + + public String getTbOrderReason() { + return tbOrderReason; + } + + public void setTbOrderReason(String tbOrderReason) { + this.tbOrderReason = tbOrderReason; + } + + public List getTbOrderReasons() { + return tbOrderReasons; + } + + public void setTbOrderReasons(List tbOrderReasons) { + this.tbOrderReasons = tbOrderReasons; + } + + public String getTbDiagnosticReason() { + return tbDiagnosticReason; + } + + public void setTbDiagnosticReason(String tbDiagnosticReason) { + this.tbDiagnosticReason = tbDiagnosticReason; + } + + public List getTbDiagnosticReasons() { + return tbDiagnosticReasons; + } + + public void setTbDiagnosticReasons(List tbDiagnosticReasons) { + this.tbDiagnosticReasons = tbDiagnosticReasons; + } + + public String getTbFollowupReason() { + return tbFollowupReason; + } + + public void setTbFollowupReason(String tbFollowupReason) { + this.tbFollowupReason = tbFollowupReason; + } + + public List getTbFollowupReasons() { + return tbFollowupReasons; + } + + public void setTbFollowupReasons(List tbFollowupReasons) { + this.tbFollowupReasons = tbFollowupReasons; + } + + public List getTbDiagnosticMethods() { + return tbDiagnosticMethods; + } + + public void setTbDiagnosticMethods(List tbDiagnosticMethods) { + this.tbDiagnosticMethods = tbDiagnosticMethods; + } + + public String getTbAspect() { + return tbAspect; + } + + public void setTbAspect(String tbAspect) { + this.tbAspect = tbAspect; + } + + public List getTbAspects() { + return tbAspects; + } + + public void setTbAspects(List tbAspects) { + this.tbAspects = tbAspects; + } + + public String getPatientGender() { + return patientGender; + } + + public void setPatientGender(String patientGender) { + this.patientGender = patientGender; + } + + public String getPatientAge() { + return patientAge; + } + + public void setPatientAge(String patientAge) { + this.patientAge = patientAge; + } + + public String getPatientBirthDate() { + return patientBirthDate; + } + + public void setPatientBirthDate(String patientBirthDate) { + this.patientBirthDate = patientBirthDate; + } + + public String getRequesterName() { + return requesterName; + } + + public void setRequesterName(String requesterName) { + this.requesterName = requesterName; + } + + public String getReceivedDate() { + return receivedDate; + } + + public void setReceivedDate(String receivedDate) { + this.receivedDate = receivedDate; + } + + public String getPatientFirstName() { + return patientFirstName; + } + + public void setPatientFirstName(String patientFirstName) { + this.patientFirstName = patientFirstName; + } + + public String getPatientLastName() { + return patientLastName; + } + + public void setPatientLastName(String patientLastName) { + this.patientLastName = patientLastName; + } + + public String getPatientPhone() { + return patientPhone; + } + + public void setPatientPhone(String patientPhone) { + this.patientPhone = patientPhone; + } + + public String getPatientAddress() { + return patientAddress; + } + + public void setPatientAddress(String patientAddress) { + this.patientAddress = patientAddress; + } + + public String getTbSubjectNumber() { + return tbSubjectNumber; + } + + public void setTbSubjectNumber(String tbSubjectNumber) { + this.tbSubjectNumber = tbSubjectNumber; + } + + public String getTbSpecimenNature() { + return tbSpecimenNature; + } + + public void setTbSpecimenNature(String tbSpecimenNature) { + this.tbSpecimenNature = tbSpecimenNature; + } + + public List getTbSpecimenNatures() { + return tbSpecimenNatures; + } + + public void setTbSpecimenNatures(List tbSpecimenNatures) { + this.tbSpecimenNatures = tbSpecimenNatures; + } + + public String getRejectReason() { + return rejectReason; + } + + public void setRejectReason(String rejectReason) { + this.rejectReason = rejectReason; + } + + public String getTbFollowupPeriodLine1() { + return tbFollowupPeriodLine1; + } + + public void setTbFollowupPeriodLine1(String tbFollowupPeriodLine1) { + this.tbFollowupPeriodLine1 = tbFollowupPeriodLine1; + } + + public String getTbFollowupPeriodLine2() { + return tbFollowupPeriodLine2; + } + + public void setTbFollowupPeriodLine2(String tbFollowupPeriodLine2) { + this.tbFollowupPeriodLine2 = tbFollowupPeriodLine2; + } + + public List getTbFollowupPeriodsLine1() { + return tbFollowupPeriodsLine1; + } + + public void setTbFollowupPeriodsLine1(List tbFollowupPeriodsLine1) { + this.tbFollowupPeriodsLine1 = tbFollowupPeriodsLine1; + } + + public List getTbFollowupPeriodsLine2() { + return tbFollowupPeriodsLine2; + } + + public void setTbFollowupPeriodsLine2(List tbFollowupPeriodsLine2) { + this.tbFollowupPeriodsLine2 = tbFollowupPeriodsLine2; + } + + public List getNewSelectedTests() { + return newSelectedTests; + } + + public void setNewSelectedTests(List newSelectedTests) { + this.newSelectedTests = newSelectedTests; + } + + public List getSelectedTestToRemove() { + return selectedTestToRemove; + } + + public void setSelectedTestToRemove(List selectedTestToRemove) { + this.selectedTestToRemove = selectedTestToRemove; + } + + public String getSysUserId() { + return sysUserId; + } + + public void setSysUserId(String sysUserId) { + this.sysUserId = sysUserId; + } + + public String getSelectedTbMethod() { + return selectedTbMethod; + } + + public void setSelectedTbMethod(String selectedTbMethod) { + this.selectedTbMethod = selectedTbMethod; + } + + public String getSelectedMethodToRemove() { + return selectedMethodToRemove; + } + + public void setSelectedMethodToRemove(String selectedMethodToRemove) { + this.selectedMethodToRemove = selectedMethodToRemove; + } + + + +} diff --git a/src/main/java/org/openelisglobal/sample/service/TbSampleService.java b/src/main/java/org/openelisglobal/sample/service/TbSampleService.java new file mode 100644 index 0000000000..aa4e0a35de --- /dev/null +++ b/src/main/java/org/openelisglobal/sample/service/TbSampleService.java @@ -0,0 +1,9 @@ +package org.openelisglobal.sample.service; + +import javax.servlet.http.HttpServletRequest; + +import org.openelisglobal.sample.form.SampleTbEntryForm; + +public interface TbSampleService { + boolean persistTbData(SampleTbEntryForm form, HttpServletRequest request); +} diff --git a/src/main/java/org/openelisglobal/sample/service/TbSampleServiceImpl.java b/src/main/java/org/openelisglobal/sample/service/TbSampleServiceImpl.java new file mode 100644 index 0000000000..561707f240 --- /dev/null +++ b/src/main/java/org/openelisglobal/sample/service/TbSampleServiceImpl.java @@ -0,0 +1,416 @@ +package org.openelisglobal.sample.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.ObjectUtils; +import org.openelisglobal.address.service.AddressPartService; +import org.openelisglobal.address.service.PersonAddressService; +import org.openelisglobal.address.valueholder.PersonAddress; +import org.openelisglobal.analysis.service.AnalysisService; +import org.openelisglobal.analysis.valueholder.Analysis; +import org.openelisglobal.common.services.IStatusService; +import org.openelisglobal.common.services.StatusService.AnalysisStatus; +import org.openelisglobal.common.services.StatusService.OrderStatus; +import org.openelisglobal.common.services.StatusService.SampleStatus; +import org.openelisglobal.common.util.DateUtil; +import org.openelisglobal.observationhistory.service.ObservationHistoryService; +import org.openelisglobal.observationhistory.valueholder.ObservationHistory; +import org.openelisglobal.observationhistory.valueholder.ObservationHistory.ValueType; +import org.openelisglobal.observationhistorytype.service.ObservationHistoryTypeService; +import org.openelisglobal.observationhistorytype.valueholder.ObservationHistoryType; +import org.openelisglobal.organization.service.OrganizationService; +import org.openelisglobal.patient.service.PatientService; +import org.openelisglobal.patient.valueholder.Patient; +import org.openelisglobal.patientidentity.service.PatientIdentityService; +import org.openelisglobal.patientidentity.valueholder.PatientIdentity; +import org.openelisglobal.patientidentitytype.service.PatientIdentityTypeService; +import org.openelisglobal.patientidentitytype.util.PatientIdentityTypeMap; +import org.openelisglobal.person.service.PersonService; +import org.openelisglobal.person.valueholder.Person; +import org.openelisglobal.provider.service.ProviderService; +import org.openelisglobal.provider.valueholder.Provider; +import org.openelisglobal.sample.form.SampleTbEntryForm; +import org.openelisglobal.sample.valueholder.OrderPriority; +import org.openelisglobal.sample.valueholder.Sample; +import org.openelisglobal.samplehuman.service.SampleHumanService; +import org.openelisglobal.samplehuman.valueholder.SampleHuman; +import org.openelisglobal.sampleitem.service.SampleItemService; +import org.openelisglobal.sampleitem.valueholder.SampleItem; +import org.openelisglobal.sampleorganization.service.SampleOrganizationService; +import org.openelisglobal.sampleorganization.valueholder.SampleOrganization; +import org.openelisglobal.spring.util.SpringContext; +import org.openelisglobal.test.service.TestSectionService; +import org.openelisglobal.test.service.TestService; +import org.openelisglobal.test.valueholder.Test; +import org.openelisglobal.typeofsample.service.TypeOfSampleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class TbSampleServiceImpl implements TbSampleService { + + private static final String DEFAULT_ANALYSIS_TYPE = "MANUAL"; + + @Autowired + private TestSectionService testSectionService; + @Autowired + private ObservationHistoryService observationHistoryService; + @Autowired + private ObservationHistoryTypeService observationHistoryTypeService; + @Autowired + private PersonService personService; + @Autowired + private PersonAddressService personAddressService; + @Autowired + private AddressPartService addressPartService; + @Autowired + private PatientIdentityService patientIdentityService; + @Autowired + private PatientService patientService; + @Autowired + private ProviderService providerService; + @Autowired + private SampleService sampleService; + @Autowired + private SampleHumanService sampleHumanService; + @Autowired + private SampleItemService sampleItemService; + @Autowired + private TypeOfSampleService typeOfSampleService; + @Autowired + private AnalysisService analysisService; + @Autowired + private TestService testService; + @Autowired + private OrganizationService organizationService; + @Autowired + private SampleOrganizationService sampleOrganizationService; + + private String sampleId; + private String patientId; + private String sampleItemId; + + @Transactional + @Override + public boolean persistTbData(SampleTbEntryForm form, HttpServletRequest request) { + boolean isOK = false; + try { + persistPatientData(form); + createPatientIdentity(form, patientId); + sampleId = persistSampleData(form); + persistSampleHumanData(form); + sampleItemId = persistSampleItemData(form); + persistAnalysisData(form); + persistSampleOrganizationData(form); + persistObservations(form); + isOK = true; + } catch (Exception e) { + isOK = false; + throw e; + } + return isOK; + } + + private List persistObservations(SampleTbEntryForm formData) { + List obervations = new ArrayList(); + + //tb order reason + ObservationHistory orderReason = new ObservationHistory(); + orderReason.setSampleId(sampleId); + orderReason.setPatientId(patientId); + orderReason.setLastupdated(DateUtil.getNowAsTimestamp()); + orderReason.setSysUserId(formData.getSysUserId()); + orderReason.setValueType(ValueType.DICTIONARY); + orderReason.setValue(formData.getTbOrderReason()); + orderReason.setObservationHistoryTypeId(getObservationHistoryTypeId("TbOrderReason")); + obervations.add(orderReason); + //tb diagnostic reason + ObservationHistory diagnosticReason = new ObservationHistory(); + diagnosticReason.setSampleId(sampleId); + diagnosticReason.setPatientId(patientId); + diagnosticReason.setLastupdated(DateUtil.getNowAsTimestamp()); + diagnosticReason.setSysUserId(formData.getSysUserId()); + diagnosticReason.setValueType(ValueType.DICTIONARY); + diagnosticReason.setValue(formData.getTbDiagnosticReason()); + diagnosticReason.setObservationHistoryTypeId(getObservationHistoryTypeId("TbDiagnosticReason")); + obervations.add(diagnosticReason); + //tb followup reason + ObservationHistory tbFollowupReason = new ObservationHistory(); + tbFollowupReason.setSampleId(sampleId); + tbFollowupReason.setPatientId(patientId); + tbFollowupReason.setLastupdated(DateUtil.getNowAsTimestamp()); + tbFollowupReason.setSysUserId(formData.getSysUserId()); + tbFollowupReason.setValueType(ValueType.DICTIONARY); + tbFollowupReason.setValue(formData.getTbFollowupReason()); + tbFollowupReason.setObservationHistoryTypeId(getObservationHistoryTypeId("TbFollowupReason")); + obervations.add(tbFollowupReason); + //tb sample aspect + ObservationHistory tbAspect = new ObservationHistory(); + tbAspect.setSampleId(sampleId); + tbAspect.setPatientId(patientId); + tbAspect.setLastupdated(DateUtil.getNowAsTimestamp()); + tbAspect.setSysUserId(formData.getSysUserId()); + tbAspect.setValueType(ValueType.DICTIONARY); + tbAspect.setValue(formData.getTbAspect()); + tbAspect.setObservationHistoryTypeId(getObservationHistoryTypeId("TbSampleAspects")); + obervations.add(tbAspect); + //tb follwup period Line 1 + ObservationHistory tbFollowupReasonPeriodLine1 = new ObservationHistory(); + tbFollowupReasonPeriodLine1.setSampleId(sampleId); + tbFollowupReasonPeriodLine1.setPatientId(patientId); + tbFollowupReasonPeriodLine1.setLastupdated(DateUtil.getNowAsTimestamp()); + tbFollowupReasonPeriodLine1.setSysUserId(formData.getSysUserId()); + tbFollowupReasonPeriodLine1.setValueType(ValueType.LITERAL); + tbFollowupReasonPeriodLine1.setValue(formData.getTbFollowupPeriodLine1()); + tbFollowupReasonPeriodLine1.setObservationHistoryTypeId(getObservationHistoryTypeId("TbFollowupReasonPeriodLine1")); + obervations.add(tbFollowupReasonPeriodLine1); + //tb follwup period Line 2 + ObservationHistory tbFollowupReasonPeriodLine2 = new ObservationHistory(); + tbFollowupReasonPeriodLine2.setSampleId(sampleId); + tbFollowupReasonPeriodLine2.setPatientId(patientId); + tbFollowupReasonPeriodLine2.setLastupdated(DateUtil.getNowAsTimestamp()); + tbFollowupReasonPeriodLine2.setSysUserId(formData.getSysUserId()); + tbFollowupReasonPeriodLine2.setValueType(ValueType.LITERAL); + tbFollowupReasonPeriodLine2.setValue(formData.getTbFollowupPeriodLine2()); + tbFollowupReasonPeriodLine2.setObservationHistoryTypeId(getObservationHistoryTypeId("TbFollowupReasonPeriodLine2")); + obervations.add(tbFollowupReasonPeriodLine2); + //tb Analysis Method + ObservationHistory analysisMethod = new ObservationHistory(); + analysisMethod.setSampleId(sampleId); + analysisMethod.setPatientId(patientId); + analysisMethod.setLastupdated(DateUtil.getNowAsTimestamp()); + analysisMethod.setSysUserId(formData.getSysUserId()); + analysisMethod.setValueType(ValueType.DICTIONARY); + analysisMethod.setValue(formData.getSelectedTbMethod()); + analysisMethod.setObservationHistoryTypeId(getObservationHistoryTypeId("TbAnalysisMethod")); + obervations.add(analysisMethod); + return observationHistoryService.insertAll(obervations); + } + + private Patient persistPatientData(SampleTbEntryForm formData) { + Patient patient = new Patient(); + Patient oldPatient = patientService.getByExternalId(formData.getTbSubjectNumber()); + if (ObjectUtils.isEmpty(oldPatient)) { + patient.setPerson(createPersonAndAddress(formData)); + patient.setExternalId(formData.getTbSubjectNumber()); + patient.setNationalId(formData.getTbSubjectNumber()); + patient.setBirthDateForDisplay(formData.getPatientBirthDate()); + patient.setBirthDate(DateUtil.convertStringDateToTruncatedTimestamp(formData.getPatientBirthDate())); + patient.setGender(formData.getPatientGender()); + patient.setSysUserId(formData.getSysUserId()); + patientId = patientService.insert(patient); + patient.setId(patientId); + return patient; + } else { + // update + oldPatient.setPerson(createPersonAndAddress(formData)); + oldPatient.setBirthDateForDisplay(formData.getPatientBirthDate()); + oldPatient.setBirthDate(DateUtil.convertStringDateToTimestamp(formData.getPatientBirthDate() + " 00:00")); + oldPatient.setGender(formData.getPatientGender()); + oldPatient.setSysUserId(formData.getSysUserId()); + oldPatient = patientService.update(oldPatient); + patientId = oldPatient.getId(); + return oldPatient; + } + + } + + // create a new Person + private Person createPersonAndAddress(SampleTbEntryForm formData) { + Person person = new Person(); + person.setFirstName(formData.getPatientFirstName()); + person.setLastName(formData.getPatientLastName()); + person.setLastupdatedFields(); + person.setSysUserId(formData.getSysUserId()); + String personId = personService.insert(person); + person.setId(personId); + createPersonAddresses(formData, personId); + return person; + } + + // create a new Person + private String createPatientIdentity(SampleTbEntryForm formData,String patientId) { + String typeID = PatientIdentityTypeMap.getInstance().getIDForType("SUBJECT"); + PatientIdentity patientIdentity = patientIdentityService.getPatitentIdentityForPatientAndType(patientId, typeID); + if(ObjectUtils.isEmpty(patientIdentity)) { + patientIdentity = new PatientIdentity(); + patientIdentity.setPatientId(patientId); + patientIdentity.setIdentityData(formData.getTbSubjectNumber()); + patientIdentity.setLastupdated(DateUtil.getNowAsTimestamp()); + patientIdentity.setIdentityTypeId(typeID); + return patientIdentityService.insert(patientIdentity); + } + else { + return patientIdentity.getId(); + } + } + + private String createPersonAndProvider(SampleTbEntryForm formData) { + Person person = new Person(); + person.setFirstName(formData.getProviderFirstName()); + person.setLastName(formData.getProviderLastName()); + person.setLastupdatedFields(); + person.setSysUserId(formData.getSysUserId()); + String personId = personService.insert(person); + person.setId(personId); + Provider provider = new Provider(); + provider.setPerson(person); + provider.setLastupdated(DateUtil.getNowAsTimestamp()); + return providerService.insert(provider); + } + + // create a new Person + private void createPersonAddresses(SampleTbEntryForm formData, String personId) { + // define addresses + List existingAddresses = personAddressService.getAddressPartsByPersonId(personId); + if (ObjectUtils.isEmpty(existingAddresses)) { + PersonAddress patientPhone = new PersonAddress(); + patientPhone.setPersonId(personId); + patientPhone.setAddressPartId(addressPartService.getAddresPartByName("phone").getId()); + patientPhone.setType("T"); + patientPhone.setValue(formData.getPatientPhone()); + patientPhone.setSysUserId(formData.getSysUserId()); + patientPhone.setLastupdatedFields(); + personAddressService.insert(patientPhone); + PersonAddress patientStreetAddress = new PersonAddress(); + patientStreetAddress.setPersonId(personId); + patientStreetAddress.setAddressPartId(addressPartService.getAddresPartByName("street").getId()); + patientStreetAddress.setType("T"); + patientStreetAddress.setValue(formData.getPatientAddress()); + patientStreetAddress.setSysUserId(formData.getSysUserId()); + patientStreetAddress.setLastupdatedFields(); + personAddressService.insert(patientStreetAddress); + } else { + // update adresses + existingAddresses.forEach(address -> { + if (address.getAddressPartId().equals(addressPartService.getAddresPartByName("phone").getId())) { + address.setValue(formData.getPatientPhone()); + } + if (address.getAddressPartId().equals(addressPartService.getAddresPartByName("street").getId())) { + address.setValue(formData.getPatientAddress()); + } + personAddressService.update(address); + }); + } + } + + private String persistSampleData(SampleTbEntryForm formData) { + Sample sample = new Sample(); + if (ObjectUtils.isEmpty(formData.getSampleId())) { + // create a new Sample + sample.setAccessionNumber(formData.getLabNo()); + sample.setCollectionDateForDisplay(formData.getRequestDate()); + sample.setCollectionDate(DateUtil.convertStringDateToTruncatedTimestamp(formData.getRequestDate())); + sample.setReceivedDateForDisplay(formData.getReceivedDate()); + sample.setReceivedDate(DateUtil.convertStringDateToSqlDate(formData.getReceivedDate())); + sample.setEnteredDate(DateUtil.getNowAsSqlDate()); + sample.setDomain("H"); + sample.setSysUserId(formData.getSysUserId()); + sample.setLastupdated(DateUtil.getNowAsTimestamp()); + sample.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(OrderStatus.Entered)); + sample.setPriority(OrderPriority.ROUTINE); + return sampleService.insert(sample); + } else { + // update + sample.setCollectionDateForDisplay(formData.getRequestDate()); + sample.setCollectionDate(DateUtil.convertStringDateToTruncatedTimestamp(formData.getRequestDate())); + sample.setReceivedDateForDisplay(formData.getReceivedDate()); + sample.setReceivedDate(DateUtil.convertStringDateToSqlDate(formData.getReceivedDate())); + sample.setEnteredDate(DateUtil.getNowAsSqlDate()); + sample.setSysUserId(formData.getSysUserId()); + sample.setLastupdated(DateUtil.getNowAsTimestamp()); + sample.setPriority(OrderPriority.ROUTINE); + return sampleService.update(sample).getId(); + } + } + + private String persistSampleHumanData(SampleTbEntryForm formData) { + SampleHuman sampleHuman = new SampleHuman(); + sampleHuman.setSampleId(sampleId); + sampleHuman.setPatientId(patientId); + sampleHuman.setLastupdated(DateUtil.getNowAsTimestamp()); + sampleHuman.setSysUserId(formData.getSysUserId()); + sampleHuman.setProviderId(createPersonAndProvider(formData)); + return sampleHumanService.insert(sampleHuman); + } + + private String persistSampleItemData(SampleTbEntryForm formData) { + SampleItem item = new SampleItem(); + if (!ObjectUtils.isEmpty(sampleId)) { + List oldSampleItems = sampleItemService.getSampleItemsBySampleId(sampleId); + if (!ObjectUtils.isEmpty(oldSampleItems)) { + SampleItem oldSampleItem = oldSampleItems.get(0); + oldSampleItem.setSample(sampleService.get(sampleId)); + oldSampleItem.setLastupdated(DateUtil.getNowAsTimestamp()); + oldSampleItem.setSysUserId(formData.getSysUserId()); + oldSampleItem.setTypeOfSample(typeOfSampleService.get(formData.getTbSpecimenNature())); + return sampleItemService.update(oldSampleItem).getId(); + } + } + item.setSample(sampleService.get(sampleId)); + item.setLastupdated(DateUtil.getNowAsTimestamp()); + item.setTypeOfSample(typeOfSampleService.get(formData.getTbSpecimenNature())); + item.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(SampleStatus.Entered)); + item.setSortOrder(Integer.toString(1)); + item.setSysUserId(formData.getSysUserId()); + return sampleItemService.insert(item); + } + + private List persistAnalysisData(SampleTbEntryForm formData) { + List analysisItems = new ArrayList(); + for (String testId : formData.getNewSelectedTests()) { + Analysis analysis = new Analysis(); + Test test = testService.get(testId); + SampleItem sampleItem = sampleItemService.get(sampleItemId); + analysis.setSampleItem(sampleItem); + analysis.setTest(test); + analysis.setRevision("0"); + analysis.setTestSection(testSectionService.getTestSectionByName("TB")); + analysis.setEnteredDate(DateUtil.getNowAsTimestamp()); + analysis.setIsReportable(test.getIsReportable()); + analysis.setAnalysisType(DEFAULT_ANALYSIS_TYPE); + analysis.setStartedDate(DateUtil.getNowAsSqlDate()); + analysis.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted)); + analysis.setSysUserId(formData.getSysUserId()); + analysis.setFhirUuid(UUID.randomUUID()); + analysis.setSampleTypeName(typeOfSampleService.get(formData.getTbSpecimenNature()).getDescription()); + analysisItems.add(analysis); + } + return analysisService.insertAll(analysisItems); + } + + private String persistSampleOrganizationData(SampleTbEntryForm formData) { + SampleOrganization sampleOrganization = new SampleOrganization(); + if (ObjectUtils.isNotEmpty(formData.getSampleId())) { + sampleOrganization = sampleOrganizationService.getDataBySample(sampleService.get(formData.getSampleId())); + if (ObjectUtils.isNotEmpty(sampleOrganization)) { + sampleOrganization.setLastupdated(DateUtil.getNowAsTimestamp()); + sampleOrganization.setSysUserId(formData.getSysUserId()); + sampleOrganization.setSample(sampleService.get(sampleId)); + sampleOrganization.setSysUserId(formData.getSysUserId()); + sampleOrganization.setOrganization(organizationService.get(formData.getReferringSiteCode())); + return sampleOrganizationService.update(sampleOrganization).getId(); + } + } + sampleOrganization.setLastupdated(DateUtil.getNowAsTimestamp()); + sampleOrganization.setSysUserId(formData.getSysUserId()); + sampleOrganization.setSample(sampleService.get(sampleId)); + sampleOrganization.setSysUserId(formData.getSysUserId()); + sampleOrganization.setOrganization(organizationService.get(formData.getReferringSiteCode())); + return sampleOrganizationService.insert(sampleOrganization); + } + + private String getObservationHistoryTypeId(String name) { + ObservationHistoryType oht; + oht = observationHistoryTypeService.getByName(name); + if (oht != null) { + return oht.getId(); + } + return null; + } +} diff --git a/src/main/java/org/openelisglobal/sample/util/CI/ARVFormMapper.java b/src/main/java/org/openelisglobal/sample/util/CI/ARVFormMapper.java index abae2d0dae..ea8d5da898 100644 --- a/src/main/java/org/openelisglobal/sample/util/CI/ARVFormMapper.java +++ b/src/main/java/org/openelisglobal/sample/util/CI/ARVFormMapper.java @@ -44,13 +44,13 @@ public List getDryTubeTests() { if (projectData.getSerologyHIVTest()) { CollectionUtils.addIgnoreNull(testList, createTest("Vironostika", true)); CollectionUtils.addIgnoreNull(testList, createTest("Murex", true)); - CollectionUtils.addIgnoreNull(testList, createTest("Integral", true)); + //CollectionUtils.addIgnoreNull(testList, createTest("Integral", true)); } if (projectData.getCreatinineTest()) { - CollectionUtils.addIgnoreNull(testList, createTest("Cr\u0065atinin\u0065mie", true)); + CollectionUtils.addIgnoreNull(testList, createTest("Créatininémie", true)); } if (projectData.getGlycemiaTest()) { - CollectionUtils.addIgnoreNull(testList, createTest("Glyc\u0065mie", true)); + CollectionUtils.addIgnoreNull(testList, createTest("Glycémie", true)); } if (projectData.getTransaminaseTest()) { @@ -87,7 +87,7 @@ public List getEDTATubeTests(IProjectForm form) { } if (projectData.getGenotypingTest()) { - CollectionUtils.addIgnoreNull(testList, createTest("G\u0065notypage", true)); + CollectionUtils.addIgnoreNull(testList, createTest("Génotypage", true)); } return testList; diff --git a/src/main/java/org/openelisglobal/sample/util/CI/BaseProjectFormMapper.java b/src/main/java/org/openelisglobal/sample/util/CI/BaseProjectFormMapper.java index 13726e2f04..6d84e76d8a 100644 --- a/src/main/java/org/openelisglobal/sample/util/CI/BaseProjectFormMapper.java +++ b/src/main/java/org/openelisglobal/sample/util/CI/BaseProjectFormMapper.java @@ -448,7 +448,7 @@ public String getSiteSubjectNumber() { @Override public String getOrganizationId() { if (patientForm) { - if (getProjectForm().equals(ProjectForm.VL)) { + if (getProjectForm().equals(ProjectForm.VL) || getProjectForm().equals(ProjectForm.RECENCY_TESTING)) { return getSampleCenterCode(); } else { return form.getCenterCode().toString(); diff --git a/src/main/java/org/openelisglobal/sample/util/CI/ProjectForm.java b/src/main/java/org/openelisglobal/sample/util/CI/ProjectForm.java index 5c9a9cf332..0a73f01b71 100644 --- a/src/main/java/org/openelisglobal/sample/util/CI/ProjectForm.java +++ b/src/main/java/org/openelisglobal/sample/util/CI/ProjectForm.java @@ -37,7 +37,7 @@ public enum ProjectForm { ARV_FOLLOWUP("FollowUpARV_Id", "Antiretroviral Followup Study"), ROUTINE_HIV("RTN_Id", "Routine HIV Testing"), EID("EID_Id", "Early Infant Diagnosis for HIV Study"), VL("VL_Id", "Viral Load Results"), INDETERMINATE("Indeterminate_Id", "Indeterminate Results"), - SPECIAL_REQUEST("Special_Request_Id", "Special Request"); + SPECIAL_REQUEST("Special_Request_Id", "Special Request"),RECENCY_TESTING("Recency_Id", "Recency Testing"); private ProjectForm(String projectFormId, String projectName) { this.projectFormId = projectFormId; diff --git a/src/main/java/org/openelisglobal/sample/util/CI/ProjectFormMapperFactory.java b/src/main/java/org/openelisglobal/sample/util/CI/ProjectFormMapperFactory.java index 1af946d9a1..08f273d5f2 100644 --- a/src/main/java/org/openelisglobal/sample/util/CI/ProjectFormMapperFactory.java +++ b/src/main/java/org/openelisglobal/sample/util/CI/ProjectFormMapperFactory.java @@ -23,30 +23,33 @@ public class ProjectFormMapperFactory { - private static final String InitialARV = "InitialARV_Id"; - private static final String FollowUpARV = "FollowUpARV_Id"; - private static final String EID = "EID_Id"; - private static final String VL = "VL_Id"; - private static final String RTN = "RTN_Id"; - private static final String IND = "Indeterminate_Id"; - private static final String SPE = "Special_Request_Id"; + private static final String InitialARV = "InitialARV_Id"; + private static final String FollowUpARV = "FollowUpARV_Id"; + private static final String EID = "EID_Id"; + private static final String VL = "VL_Id"; + private static final String RTN = "RTN_Id"; + private static final String IND = "Indeterminate_Id"; + private static final String SPE = "Special_Request_Id"; + private static final String RT = "Recency_Id"; - public IProjectFormMapper getProjectInitializer(String projectFormId, IProjectForm form) - throws LIMSRuntimeException { + public IProjectFormMapper getProjectInitializer(String projectFormId, IProjectForm form) + throws LIMSRuntimeException { - if (projectFormId.equals(InitialARV) || projectFormId.equals(FollowUpARV) || projectFormId.equals(VL)) { - return new ARVFormMapper(projectFormId, form); - } else if (projectFormId.equals(EID)) { - return new EIDFormMapper(projectFormId, form); - } else if (projectFormId.equals(RTN)) { - return new RTNFormMapper(projectFormId, form); - } else if (projectFormId.equals(IND)) { - return new INDFormMapper(projectFormId, form); - } else if (projectFormId.equals(SPE)) { - return new SPEFormMapper(projectFormId, form); - } + if (projectFormId.equals(InitialARV) || projectFormId.equals(FollowUpARV) || projectFormId.equals(VL)) { + return new ARVFormMapper(projectFormId, form); + } else if (projectFormId.equals(EID)) { + return new EIDFormMapper(projectFormId, form); + } else if (projectFormId.equals(RTN)) { + return new RTNFormMapper(projectFormId, form); + } else if (projectFormId.equals(IND)) { + return new INDFormMapper(projectFormId, form); + } else if (projectFormId.equals(SPE)) { + return new SPEFormMapper(projectFormId, form); + } else if (projectFormId.equals(RT)) { + return new RecencyFormMapper(projectFormId, form); + } - throw new LIMSRuntimeException( - "ProjectFormMapperFactory: Unable to find project initializer for " + projectFormId); - } + throw new LIMSRuntimeException( + "ProjectFormMapperFactory: Unable to find project initializer for " + projectFormId); + } } diff --git a/src/main/java/org/openelisglobal/sample/util/CI/RecencyFormMapper.java b/src/main/java/org/openelisglobal/sample/util/CI/RecencyFormMapper.java new file mode 100644 index 0000000000..8618091946 --- /dev/null +++ b/src/main/java/org/openelisglobal/sample/util/CI/RecencyFormMapper.java @@ -0,0 +1,87 @@ +/** +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (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.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" +* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +* License for the specific language governing rights and limitations under +* the License. +* +* The Original Code is OpenELIS code. +* +* Copyright (C) The Minnesota Department of Health. All Rights Reserved. +* +* Contributor(s): CIRG, University of Washington, Seattle WA. +*/ +package org.openelisglobal.sample.util.CI; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.collections4.CollectionUtils; +import org.openelisglobal.internationalization.MessageUtil; +import org.openelisglobal.sample.util.CI.form.IProjectForm; +import org.openelisglobal.test.valueholder.Test; + +public class RecencyFormMapper extends BaseProjectFormMapper implements IProjectFormMapper { + + private final String projectCode = MessageUtil.getMessage("sample.entry.project.RT"); + private final String projectName = "Recency Testing"; + + public RecencyFormMapper(String projectFormId, IProjectForm form) { + super(projectFormId, form); + } + + public String getProjectName() { + return projectName; + } + + @Override + public String getProjectCode() { + return projectCode; + } + + public List getPlasmaTests() { + List testList = new ArrayList<>(); + + if (projectData.isAsanteTest()) { + CollectionUtils.addIgnoreNull(testList, createTest("Asante HIV-1 Rapid Recency", true)); + } + return testList; + } + + public List getSerumTests() { + List testList = new ArrayList<>(); + + if (projectData.isAsanteTest()) { + CollectionUtils.addIgnoreNull(testList, createTest("Asante HIV-1 Rapid Recency", true)); + } + return testList; + } + + @Override + public ArrayList getTypeOfSampleTests() { + ArrayList sItemTests = new ArrayList<>(); + + // Check for Plasma Tests + if (projectData.isPlasmaTaken()) { + sItemTests.add(new TypeOfSampleTests(getTypeOfSample("Plasma"), getPlasmaTests())); + } + + if (projectData.isSerumTaken()) { + sItemTests.add(new TypeOfSampleTests(getTypeOfSample("Serum"), getSerumTests())); + } + + return sItemTests; + } + + /** + * @see org.openelisglobal.sample.util.CI.BaseProjectFormMapper#getSampleCenterCode() + */ + @Override + public String getSampleCenterCode() { + return projectData.getARVcenterCode(); + } +} diff --git a/src/main/java/org/openelisglobal/sample/util/CI/form/IProjectForm.java b/src/main/java/org/openelisglobal/sample/util/CI/form/IProjectForm.java index 26751d3370..69bb76269b 100644 --- a/src/main/java/org/openelisglobal/sample/util/CI/form/IProjectForm.java +++ b/src/main/java/org/openelisglobal/sample/util/CI/form/IProjectForm.java @@ -1,45 +1,58 @@ package org.openelisglobal.sample.util.CI.form; +import org.openelisglobal.dataexchange.order.valueholder.ElectronicOrder; import org.openelisglobal.patient.valueholder.ObservationData; import org.openelisglobal.sample.form.ProjectData; public interface IProjectForm { - ProjectData getProjectData(); + ProjectData getProjectData(); - void setProjectData(ProjectData projectData); + void setProjectData(ProjectData projectData); - ObservationData getObservations(); + ObservationData getObservations(); - void setObservations(ObservationData observationData); + void setObservations(ObservationData observationData); - String getBirthDateForDisplay(); + String getBirthDateForDisplay(); - void setBirthDateForDisplay(String birthDateForDisplay); + void setBirthDateForDisplay(String birthDateForDisplay); - String getSiteSubjectNumber(); + String getSiteSubjectNumber(); - void setSiteSubjectNumber(String siteSubjectNumber); + void setSiteSubjectNumber(String siteSubjectNumber); - String getSubjectNumber(); + String getSubjectNumber(); - void setSubjectNumber(String subjectNumber); + void setSubjectNumber(String subjectNumber); - String getInterviewDate(); + String getInterviewDate(); - String getReceivedDateForDisplay(); + String getReceivedDateForDisplay(); - String getInterviewTime(); + String getInterviewTime(); - String getReceivedTimeForDisplay(); + String getReceivedTimeForDisplay(); - Integer getCenterCode(); + Integer getCenterCode(); - String getPatientPK(); + String getPatientPK(); - String getSamplePK(); + String getSamplePK(); - String getLabNo(); + String getLabNo(); - void setLabNo(String labNo); + void setLabNo(String labNo); + + ElectronicOrder getElectronicOrder(); + + void setElectronicOrder(ElectronicOrder electronicOrder); + + String getPatientFhirUuid(); + + void setPatientFhirUuid(String patientFhirUuid); + + String getUpidCode(); + + void setUpidCode(String upidCode); } diff --git a/src/main/java/org/openelisglobal/statusofsample/util/StatusRules.java b/src/main/java/org/openelisglobal/statusofsample/util/StatusRules.java index 3fe223a9a2..2bac96253e 100644 --- a/src/main/java/org/openelisglobal/statusofsample/util/StatusRules.java +++ b/src/main/java/org/openelisglobal/statusofsample/util/StatusRules.java @@ -36,6 +36,8 @@ public void setAllowableStatusForLoadingResults(ResultsLoadUtility resultsLoadUt resultsLoadUtility.addIncludedAnalysisStatus(AnalysisStatus.BiologistRejected); resultsLoadUtility.addIncludedAnalysisStatus(AnalysisStatus.NotStarted); resultsLoadUtility.addIncludedAnalysisStatus(AnalysisStatus.NonConforming_depricated); + resultsLoadUtility.addIncludedAnalysisStatus(AnalysisStatus.TechnicalRejected); + resultsLoadUtility.addIncludedAnalysisStatus(AnalysisStatus.TechnicalAcceptance); resultsLoadUtility.addIncludedSampleStatus(OrderStatus.Entered); resultsLoadUtility.addIncludedSampleStatus(OrderStatus.Started); resultsLoadUtility.addIncludedSampleStatus(OrderStatus.NonConforming_depricated); diff --git a/src/main/java/org/openelisglobal/systemuser/service/UserService.java b/src/main/java/org/openelisglobal/systemuser/service/UserService.java index bb01cde9f1..8dcad12c4b 100644 --- a/src/main/java/org/openelisglobal/systemuser/service/UserService.java +++ b/src/main/java/org/openelisglobal/systemuser/service/UserService.java @@ -39,5 +39,7 @@ List filterAnalysesByLabUnitRoles(String SystemUserId, List List filterResultsByLabUnitRoles(String SystemUserId, List results, String roleName); - List getUserPrograms(String systemUserId, String userRole); + List getUserPrograms(String systemUserId, String userRole); + + List getUserSampleTypes(String systemUserId, String roleName, String testSectionName); } diff --git a/src/main/java/org/openelisglobal/systemuser/service/UserServiceImpl.java b/src/main/java/org/openelisglobal/systemuser/service/UserServiceImpl.java index 72b8388fb5..bd94a5f367 100644 --- a/src/main/java/org/openelisglobal/systemuser/service/UserServiceImpl.java +++ b/src/main/java/org/openelisglobal/systemuser/service/UserServiceImpl.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.stream.Collectors; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.openelisglobal.analysis.valueholder.Analysis; import org.openelisglobal.common.services.DisplayListService; @@ -21,7 +22,9 @@ import org.openelisglobal.systemuser.valueholder.SystemUser; import org.openelisglobal.test.beanItems.TestResultItem; import org.openelisglobal.test.service.TestService; +import org.openelisglobal.test.service.TestSectionService; import org.openelisglobal.test.valueholder.Test; +import org.openelisglobal.test.valueholder.TestSection; import org.openelisglobal.typeofsample.service.TypeOfSampleService; import org.openelisglobal.typeofsample.valueholder.TypeOfSample; import org.openelisglobal.userrole.service.UserRoleService; @@ -46,9 +49,11 @@ public class UserServiceImpl implements UserService { @Autowired private TypeOfSampleService typeOfSampleService; @Autowired - ProgramService programService; + private ProgramService programService; @Autowired - TestService testService; + private TestService testService; + @Autowired + private TestSectionService testSectionService; @Override @Transactional @@ -206,6 +211,53 @@ public List getUserSampleTypes(String systemUserId, String roleName return userSampleTypes; } + + @Override + public List getUserSampleTypes(String systemUserId, String roleName, String testSectionName) { + String resultsRoleId = roleService.getRoleByName(roleName).getId(); + List testSections = getUserTestSections(systemUserId, resultsRoleId); + TestSection testSection = testSectionService.getTestSectionByName(testSectionName); + //List testUnitIds = new ArrayList<>(); + List testUnitIds = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(testSection)) { + testSections.forEach(testSection2 -> testUnitIds.add(Integer.valueOf(testSection2.getId()))); + //testUnitIds= testSections.stream().filter(el->el.getId().equals(testSection.getId())).map(e->e.getId()).collect(Collectors.toList()); + } + List allTests = testService.getTestsByTestSectionIds(testUnitIds); + // List allTBTestIds = typeOfSampleService.getAllActiveTestsByTestUnit(true, testUnitIds).stream().map(e->e.getId()).collect(Collectors.toList()); + // List allSampleTypes = DisplayListService.getInstance().getList(ListType.SAMPLE_TYPE_ACTIVE); + Set sampleIds = new HashSet<>(); + + List userSampleTypes = new ArrayList<>(); + if (allTests != null ) { + typeOfSampleService.clearCache(); + allTests.forEach(test -> sampleIds.addAll(typeOfSampleService.getTypeOfSampleForTest(test.getId()).stream() + .map(e -> e.getId()).collect(Collectors.toList()))); + + } + + sampleIds.forEach( id -> { + TypeOfSample type = typeOfSampleService.get(id); + if(type != null){ + userSampleTypes.add(new IdValuePair(type.getId(), type.getLocalizedName())); + } + }); + + // clear cache to create a fresh Map of testId To TypeOfSample + // typeOfSampleService.clearCache(); + + // List allSampleTypesIds = DisplayListService.getInstance().getList(ListType.SAMPLE_TYPE_ACTIVE).stream().map(e->e.getId()).collect(Collectors.toList()); + // allSampleTypesIds.forEach(sid->{ + // List testIds = typeOfSampleService.getActiveTestsBySampleTypeId(sid, false).stream().map(e->e.getId()).collect(Collectors.toList()); + // if(allTBTestIds.stream().anyMatch(testIds::contains)) { + // sampleIds.add(sid); + // } + // }); + + // List userSampleTypes = allSampleTypes.stream().filter(type -> sampleIds.contains(type.getId())) + // .collect(Collectors.toList()); + return userSampleTypes; + } @Override public List filterResultsByLabUnitRoles(String systemUserId, List results, diff --git a/src/main/java/org/openelisglobal/test/beanItems/TestResultItem.java b/src/main/java/org/openelisglobal/test/beanItems/TestResultItem.java index 5a1df0129a..dd2d48a551 100644 --- a/src/main/java/org/openelisglobal/test/beanItems/TestResultItem.java +++ b/src/main/java/org/openelisglobal/test/beanItems/TestResultItem.java @@ -18,6 +18,7 @@ package org.openelisglobal.test.beanItems; import java.io.Serializable; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -550,6 +551,16 @@ public void setResultValue(String results) { resultValue = results; setShadowResultValue(results); } + + public String getResultValueLog() { + try { + DecimalFormat df = new DecimalFormat("###.##"); + double val = Double.parseDouble(this.resultValue); + return df.format(Math.log10(val)); + }catch(Exception e) { + return "--"; + } + } public String getShadowResultValue() { return shadowResultValue; diff --git a/src/main/java/org/openelisglobal/test/dao/TestDAO.java b/src/main/java/org/openelisglobal/test/dao/TestDAO.java index 36812866a2..33c4a518e8 100644 --- a/src/main/java/org/openelisglobal/test/dao/TestDAO.java +++ b/src/main/java/org/openelisglobal/test/dao/TestDAO.java @@ -21,6 +21,7 @@ import org.openelisglobal.common.dao.BaseDAO; import org.openelisglobal.common.exception.LIMSRuntimeException; import org.openelisglobal.method.valueholder.Method; +import org.openelisglobal.panel.valueholder.Panel; import org.openelisglobal.test.valueholder.Test; /** @@ -114,5 +115,11 @@ public interface TestDAO extends BaseDAO { List getTestsByName(String testName) throws LIMSRuntimeException; List getActiveTestsByName(String testName) throws LIMSRuntimeException; + + List getTbTestByMethod(String method) throws LIMSRuntimeException; + + List getTbTest() throws LIMSRuntimeException; + + List getTbPanelsByMethod(String method) throws LIMSRuntimeException; } diff --git a/src/main/java/org/openelisglobal/test/daoimpl/TestDAOImpl.java b/src/main/java/org/openelisglobal/test/daoimpl/TestDAOImpl.java index 3449a5591b..8f7765a553 100644 --- a/src/main/java/org/openelisglobal/test/daoimpl/TestDAOImpl.java +++ b/src/main/java/org/openelisglobal/test/daoimpl/TestDAOImpl.java @@ -19,9 +19,11 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Vector; +import java.util.stream.Collectors; import org.apache.commons.beanutils.PropertyUtils; import org.hibernate.HibernateException; @@ -33,6 +35,7 @@ import org.openelisglobal.common.util.StringUtil; import org.openelisglobal.common.util.SystemConfiguration; import org.openelisglobal.method.valueholder.Method; +import org.openelisglobal.panel.valueholder.Panel; import org.openelisglobal.test.dao.TestDAO; import org.openelisglobal.test.valueholder.Test; import org.springframework.stereotype.Component; @@ -707,4 +710,49 @@ public List getTestsByTestSectionIds(List ids) throws LIMSRuntime return null; } + @Override + public List getTbTestByMethod(String method) throws LIMSRuntimeException { + List methodIds = Arrays.asList(method.split(",")).stream().map(e->Integer.parseInt(e)).collect(Collectors.toList()); + String sql = "SELECT t.* From test t JOIN tb_method_test tm ON t.id = tm.test_id where tm.method_id in (:method) and t.is_active='Y' ORDER BY t.name"; + try { + Query query = entityManager.unwrap(Session.class).createNativeQuery(sql, Test.class); + query.setParameter("method", methodIds); + List tests = query.list(); + return tests; + } catch (HibernateException e) { + handleException(e, "getTbTestByMethod"); + } + + return null; + } + + @Override + public List getTbTest() throws LIMSRuntimeException { + String sql = "SELECT t.* From test t JOIN test_section ts ON t.test_section_id = ts.id where t.is_active='Y' AND ts.name = 'TB' ORDER BY t.name"; + try { + Query query = entityManager.unwrap(Session.class).createNativeQuery(sql, Test.class); + List tests = query.list(); + return tests; + } catch (HibernateException e) { + handleException(e, "getTbTest"); + } + + return null; + } + @Override + public List getTbPanelsByMethod(String method) throws LIMSRuntimeException { + List methodIds = Arrays.asList(method.split(",")).stream().map(e->Integer.parseInt(e)).collect(Collectors.toList()); + + String sql = "SELECT p.* From panel p JOIN tb_method_panel tm ON p.id = tm.panel_id where tm.method_id in (:method) and p.is_active='Y' ORDER BY p.name"; + try { + Query query = entityManager.unwrap(Session.class).createNativeQuery(sql, Panel.class); + query.setParameter("method", methodIds); + List panels = query.list(); + return panels; + } catch (HibernateException e) { + handleException(e, "getTbPanelByMethod"); + } + + return null; + } } \ No newline at end of file diff --git a/src/main/java/org/openelisglobal/test/service/TestService.java b/src/main/java/org/openelisglobal/test/service/TestService.java index 6e0522f59d..791d31f702 100644 --- a/src/main/java/org/openelisglobal/test/service/TestService.java +++ b/src/main/java/org/openelisglobal/test/service/TestService.java @@ -118,6 +118,12 @@ public interface TestService extends BaseObjectService { Test getTestByName(String testName); List getActiveTestByName(String testName); + + List getTbTestByMethod(String method); + + List getTbTest(); + + List getTbPanelsByMethod(String method); Optional getActiveTestByLoincCodeAndSampleType(String loincCode, String sampleTypeId); diff --git a/src/main/java/org/openelisglobal/test/service/TestServiceImpl.java b/src/main/java/org/openelisglobal/test/service/TestServiceImpl.java index aaa186b065..00d08a4e3b 100644 --- a/src/main/java/org/openelisglobal/test/service/TestServiceImpl.java +++ b/src/main/java/org/openelisglobal/test/service/TestServiceImpl.java @@ -725,5 +725,20 @@ public void activateTestsAndDeactivateOthers(List testNames) { public List getTestsByTestSectionIds(List ids) { return getBaseObjectDAO().getTestsByTestSectionIds(ids); } + + @Override + public List getTbTestByMethod(String method) { + return getBaseObjectDAO().getTbTestByMethod(method); + } + + @Override + public List getTbTest() { + return getBaseObjectDAO().getTbTest(); + } + + @Override + public List getTbPanelsByMethod(String method) { + return getBaseObjectDAO().getTbPanelsByMethod(method); + } } diff --git a/src/main/java/org/openelisglobal/test/validator/BatchTestReassignmentFormValidator.java b/src/main/java/org/openelisglobal/test/validator/BatchTestReassignmentFormValidator.java index 35d5f68b0d..b13d049d1d 100644 --- a/src/main/java/org/openelisglobal/test/validator/BatchTestReassignmentFormValidator.java +++ b/src/main/java/org/openelisglobal/test/validator/BatchTestReassignmentFormValidator.java @@ -1,5 +1,6 @@ package org.openelisglobal.test.validator; +import org.apache.commons.lang3.ObjectUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.ParseException; @@ -38,9 +39,11 @@ public void validate(Object target, Errors errors) { // true); JSONArray replacements = JSONUtils.getAsArray(batchTest.get("replace")); - for (int i = 0; i < replacements.size(); ++i) { - ValidationHelper.validateIdField(StringUtil.nullSafeToString(replacements.get(i)), "JsonWad", - "replace[" + i + "]", errors, true); + if(ObjectUtils.isNotEmpty(replacements)) { + for (int i = 0; i < replacements.size(); ++i) { + ValidationHelper.validateIdField(StringUtil.nullSafeToString(replacements.get(i)), "JsonWad", + "replace[" + i + "]", errors, true); + } } JSONArray changesNotStarted = JSONUtils.getAsArray(batchTest.get("changeNotStarted")); diff --git a/src/main/java/org/openelisglobal/test/valueholder/TbMethodPanel.java b/src/main/java/org/openelisglobal/test/valueholder/TbMethodPanel.java new file mode 100644 index 0000000000..ffc911df6b --- /dev/null +++ b/src/main/java/org/openelisglobal/test/valueholder/TbMethodPanel.java @@ -0,0 +1,88 @@ +/** +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (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.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" +* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +* License for the specific language governing rights and limitations under +* the License. +* +* The Original Code is OpenELIS code. +* +* Copyright (C) The Minnesota Department of Health. All Rights Reserved. +*/ +package org.openelisglobal.test.valueholder; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +import org.openelisglobal.common.valueholder.EnumValueItemImpl; + +@Entity +@Table(name = "tb_method_panel") +public class TbMethodPanel extends EnumValueItemImpl { + + private static final long serialVersionUID = -1574344492809195601L; + + @Id + @SequenceGenerator(name="tb_method_panel_seq",allocationSize = 1,initialValue = 1 ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="tb_method_panel_seq") + @Column + private String id; + + @Column(name = "panel_id",nullable = false) + private String panelId; + + @Column(name = "method_id",nullable = false) + private String methodId; + + @Column(name="is_active") + private String isActive; + + public TbMethodPanel() { + super(); + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getIsActive() { + return isActive; + } + + @Override + public void setIsActive(String isActive) { + this.isActive = isActive; + } + + public String getPanelId() { + return panelId; + } + + public void setPanelId(String testId) { + this.panelId = testId; + } + + public String getMethodId() { + return methodId; + } + + public void setMethodId(String methodId) { + this.methodId = methodId; + } +} diff --git a/src/main/java/org/openelisglobal/test/valueholder/TbMethodTest.java b/src/main/java/org/openelisglobal/test/valueholder/TbMethodTest.java new file mode 100644 index 0000000000..03de8a82e2 --- /dev/null +++ b/src/main/java/org/openelisglobal/test/valueholder/TbMethodTest.java @@ -0,0 +1,88 @@ +/** +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (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.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" +* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +* License for the specific language governing rights and limitations under +* the License. +* +* The Original Code is OpenELIS code. +* +* Copyright (C) The Minnesota Department of Health. All Rights Reserved. +*/ +package org.openelisglobal.test.valueholder; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +import org.openelisglobal.common.valueholder.EnumValueItemImpl; + +@Entity +@Table(name = "tb_method_test") +public class TbMethodTest extends EnumValueItemImpl { + + private static final long serialVersionUID = -1574344492809195601L; + + @Id + @SequenceGenerator(name="tb_method_test_seq",allocationSize = 1,initialValue = 1 ) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="tb_method_test_seq") + @Column + private String id; + + @Column(name = "test_id",nullable = false) + private String testId; + + @Column(name = "method_id",nullable = false) + private String methodId; + + @Column(name="is_active") + private String isActive; + + public TbMethodTest() { + super(); + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getIsActive() { + return isActive; + } + + @Override + public void setIsActive(String isActive) { + this.isActive = isActive; + } + + public String getTestId() { + return testId; + } + + public void setTestId(String testId) { + this.testId = testId; + } + + public String getMethodId() { + return methodId; + } + + public void setMethodId(String methodId) { + this.methodId = methodId; + } +} diff --git a/src/main/java/org/openelisglobal/testcalculated/action/util/TestCalculatedUtil.java b/src/main/java/org/openelisglobal/testcalculated/action/util/TestCalculatedUtil.java index 494ed82415..55d1e86102 100644 --- a/src/main/java/org/openelisglobal/testcalculated/action/util/TestCalculatedUtil.java +++ b/src/main/java/org/openelisglobal/testcalculated/action/util/TestCalculatedUtil.java @@ -376,7 +376,13 @@ private Analysis createCalculatedAnalysis(Analysis existingAnalysis, Test test, generatedAnalysis.setAnalysisType(currentAnalysis.getAnalysisType()); generatedAnalysis.setRevision(currentAnalysis.getRevision()); generatedAnalysis.setStartedDate(DateUtil.getNowAsSqlDate()); - generatedAnalysis.setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted)); + if (resultCalculated) { + generatedAnalysis.setStatusId( + SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.TechnicalAcceptance)); + } else { + generatedAnalysis + .setStatusId(SpringContext.getBean(IStatusService.class).getStatusID(AnalysisStatus.NotStarted)); + } generatedAnalysis.setParentAnalysis(currentAnalysis); generatedAnalysis.setParentResult(result); generatedAnalysis.setSampleItem(currentAnalysis.getSampleItem()); diff --git a/src/main/java/org/openelisglobal/testconfiguration/controller/TestCatalogController.java b/src/main/java/org/openelisglobal/testconfiguration/controller/TestCatalogController.java index abfb9a809b..1715ceaa31 100644 --- a/src/main/java/org/openelisglobal/testconfiguration/controller/TestCatalogController.java +++ b/src/main/java/org/openelisglobal/testconfiguration/controller/TestCatalogController.java @@ -183,7 +183,7 @@ private List createDictionaryValues(TestService testService, Test test) } private String getDictionaryValue(TestResult testResult) { - + if (TypeOfTestResultServiceImpl.ResultType.isDictionaryVariant(testResult.getTestResultType())) { Dictionary dictionary = dictionaryService.getDataForId(testResult.getValue()); String displayValue = dictionary.getLocalizedName(); diff --git a/src/main/java/org/openelisglobal/workplan/controller/rest/PrintWorkplanReportRestController.java b/src/main/java/org/openelisglobal/workplan/controller/rest/PrintWorkplanReportRestController.java index 5360390ca3..00d2853cab 100644 --- a/src/main/java/org/openelisglobal/workplan/controller/rest/PrintWorkplanReportRestController.java +++ b/src/main/java/org/openelisglobal/workplan/controller/rest/PrintWorkplanReportRestController.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.HashMap; import java.util.List; @@ -9,6 +11,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.openelisglobal.common.exception.LIMSRuntimeException; import org.openelisglobal.common.log.LogEvent; import org.openelisglobal.common.rest.BaseRestController; import org.openelisglobal.test.service.TestServiceImpl; @@ -19,9 +22,8 @@ import org.openelisglobal.workplan.reports.TestWorkplanReport; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; 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.RestController; import net.sf.jasperreports.engine.JRDataSource; @@ -32,8 +34,9 @@ @RestController("PrintWorkplanReportRestController") public class PrintWorkplanReportRestController extends BaseRestController { + private String reportPath = null; - @RequestMapping(value = "/rest/printWorkplanReport", method = RequestMethod.POST) + @PostMapping(value = "/rest/printWorkplanReport") public void showRestPrintWorkplanReport(HttpServletRequest request, HttpServletResponse response, @RequestBody @Validated(PrintWorkplan.class) WorkplanForm form, BindingResult result) { @@ -61,15 +64,12 @@ public void showRestPrintWorkplanReport(HttpServletRequest request, HttpServletR // set Jasper report file name String reportFileName = workplanReport.getFileName(); - ClassLoader classLoader = getClass().getClassLoader(); - File reportFile = new File(classLoader.getResource("reports/" + reportFileName + ".jasper").getFile()); - try { byte[] bytes = null; JRDataSource dataSource = createReportDataSource(workplanRows); - bytes = JasperRunManager.runReportToPdf(reportFile.getAbsolutePath(), parameterMap, dataSource); + bytes = JasperRunManager.runReportToPdf(getReportPath() + reportFileName + ".jasper", parameterMap, dataSource); ServletOutputStream servletOutputStream = response.getOutputStream(); response.setContentType("application/pdf"); @@ -112,9 +112,26 @@ public IWorkplanReport getWorkplanReport(String testType, String name) { return workplan; } - public String getReportPath() { - ClassLoader classLoader = getClass().getClassLoader(); - File reportFile = new File(classLoader.getResource("reports/").getFile()); - return reportFile.getAbsolutePath(); + private String getReportPath() { + String reportPath = getReportPathValue(); + if (reportPath.endsWith(File.separator)) { + return reportPath; + } else { + return reportPath + File.separator; + } + } + + private String getReportPathValue() { + if (reportPath == null) { + ClassLoader classLoader = getClass().getClassLoader(); + reportPath = classLoader.getResource("reports").getPath(); + try { + reportPath = URLDecoder.decode(reportPath, "UTF-8"); + } catch (UnsupportedEncodingException e) { + LogEvent.logError(e); + throw new LIMSRuntimeException(e); + } + } + return reportPath; } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c0fb575752..ba6fc4fb5b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,11 +13,11 @@ facilitylist.schedule.fixedRate=864000000 #Local FHIR server #org.openelisglobal.server.uri=https://oe.openelis.org:8443/OpenELIS-Global/fhir/ #org.openelisglobal.datasubscriber.uri=https://datasubscriber.openelis.org:8443/subscription/fhirResourceGroup/ -org.openelisglobal.fhirstore.uri=http://localhost:8082/fhir/ +#org.openelisglobal.fhirstore.uri=http://localhost:8081/fhir/ # Remote FHIR server/Consolidated Server -#org.openelisglobal.remote.source.uri=http://localhost:8081/fhir/ -#org.openelisglobal.remote.source.identifier=Practitioner/f9badd80-ab76-11e2-9e96-0800200c9a66 +#org.openelisglobal.remote.source.uri=http://185.218.126.190:5001/fhir/ +#org.openelisglobal.remote.source.identifier=Practitioner/738185ba-eac9-11e5-8f4d-e06995eac916 #org.openelisglobal.remote.source.updateStatus=false #org.openelisglobal.task.useBasedOn=true #org.openelisglobal.fhirstore.username=openelis diff --git a/src/main/resources/hibernate/hbm/Patient.hbm.xml b/src/main/resources/hibernate/hbm/Patient.hbm.xml index 538e095952..0753e716d4 100644 --- a/src/main/resources/hibernate/hbm/Patient.hbm.xml +++ b/src/main/resources/hibernate/hbm/Patient.hbm.xml @@ -76,6 +76,8 @@ + diff --git a/src/main/resources/languages/message_en.properties b/src/main/resources/languages/message_en.properties index be14352796..ebdf4e1afd 100644 --- a/src/main/resources/languages/message_en.properties +++ b/src/main/resources/languages/message_en.properties @@ -1,5 +1,7 @@ #Generated by Eclipse Messages Editor (Eclipse Babel) +$R{report.followup.period.l1} = Period + AIDSStage.adultA = 1 = Stade A (Adult) AIDSStage.adultB = 2 = Stade B (Adult) AIDSStage.adultC = 3 = Stade C (Adult) @@ -62,6 +64,9 @@ action.edit.title = Edit Action action.id = Action Number action.type = Action Type +add.recency.sample.title = Add a Recency Testing +add.tb.sample.title = Add a TB Sample + age.anyAge = Any Age alert.error = Error @@ -174,7 +179,6 @@ banner.menu.editPatient.ReadWrite = Edit Patient banner.menu.editSample.ReadOnly = View Sample banner.menu.editSample.ReadWrite = Edit Sample banner.menu.eorders = Electronic Orders -banner.menu.study.eorders = Electronic Orders banner.menu.help = Help banner.menu.help.documents = Process Documentation banner.menu.help.formDBS = DBS Form @@ -196,6 +200,9 @@ banner.menu.ie.warning = The menus will only work \ running in compatibility \ view. banner.menu.inventory = Inventory +banner.menu.microbiology = Microbiology +banner.menu.microbiology_classic = Classic Bacteriology +banner.menu.microbiology_tb = Tuberculosis banner.menu.nonconformity = Non-Conforming Events banner.menu.nonconformity.correctiveActions = Corrective actions banner.menu.nonconformity.report = Report Non-Conforming Event @@ -293,6 +300,8 @@ banner.menu.sampleBatchEntry = Batch Order Entry banner.menu.sampleConsult = View banner.menu.sampleCreate = Study banner.menu.sampleEdit = Modify Order +banner.menu.study.eorders = Electronic Orders +banner.menu.study.recency = Recency Testing banner.menu.workplan = Workplan banner.menu.workplan.Biochemistry = Biochemistry banner.menu.workplan.Hematology = Hematology @@ -308,11 +317,11 @@ banner.menu.workplan.malaria = Malaria banner.menu.workplan.mycology = Mycology banner.menu.workplan.panel = By Panel Type banner.menu.workplan.parasitology = Parasitology +banner.menu.workplan.priority = By Priority banner.menu.workplan.serology = Serology banner.menu.workplan.serology-immunology = Serology-Immunology banner.menu.workplan.test = By Test Type banner.menu.workplan.virology = Virology -banner.menu.workplan.priority = By Priority barcode.common.button.print = Print labels barcode.common.section.barcode.header = Barcode(s) @@ -329,9 +338,9 @@ barcode.label.error.override.invalid = override is not a boolean value barcode.label.error.patientid.invalid = Barcode patient id is invalid barcode.label.error.quantity.invalid = Barcode quantity is invalid barcode.label.error.type.invalid = Barcode type is invalid +barcode.label.info.collectedBy = Collected By barcode.label.info.collectiondate = Collected barcode.label.info.collectiondatetime = Collection Date and Time -barcode.label.info.collectedBy = Collected By barcode.label.info.collectiontime = Time barcode.label.info.collectorid = By barcode.label.info.labnumber = Accession number @@ -512,6 +521,24 @@ common.sample.confirmExitPopup.title = Confirm Exit configuration.batch.test.reassignment = Batch test reassignment \ and cancelation configuration.menu.management = Menu Management +configuration.method = Manage Methods +configuration.method.confirmation.explain = This method unit will not \ + be active until at least \ + one test has been assigned \ + to it. +configuration.method.create = Create New Method +configuration.method.create.duplicate = An existing method with \ + the same name has been \ + found. Please cancel or \ + use a different name. +configuration.method.explain = Use to create a new \ + method, activate or \ + deactivate a method +configuration.method.manage = Manage Methods +configuration.method.rename = Rename existing method \ + names +configuration.method.rename.explain = Use to correct the name of \ + existing methods configuration.panel.assign = Test Assignment configuration.panel.assign.deactivate = configuration.panel.assign.\ deactivate (fix me) @@ -642,8 +669,6 @@ configuration.selectList.verifyMessage = Verify that the new entry \ otherwise use the back \ button to correct the entry configuration.test.activate = Activate/Deactivate tests -configuration.method = Manage Methods -configuration.method.explain = Use to create a new method, activate or deactivate a method configuration.test.activate.explain = Use to activate or \ deactivate an existing \ test. @@ -906,9 +931,10 @@ configuration.test.add.guide.verify = Verify that all values \ change the incorrect \ values. configuration.test.catalog = View Test Catalog -configuration.test.catalog.age.range.months = Age range (months) +configuration.test.catalog.age.range = Age Range configuration.test.catalog.age.range.days = Age range (days) -configuration.test.catalog.age.range = Age Range +configuration.test.catalog.age.range.months = Age range (months) +configuration.test.catalog.critical.range = Critical range configuration.test.catalog.explain = View the current test \ catalog configuration.test.catalog.guide = \ Name
Newest -eorder.lastupdateddesc = Newest -> Oldest -eorder.message = Original Message -eorder.noresults = No Results to Show -eorder.of = of -eorder.patient = Patient -eorder.patient.birthdate = Birthdate -eorder.patient.gender = Gender -eorder.patient.id = External ID -eorder.patient.name = Name -eorder.results = Showing Results -eorder.sort = Sort Entries By -eorder.status = Status -eorder.timestamp = Timestamp +entry.invalid.loinc.number.used = This LOINC is already in use, LOINC codes \ + must be unique + +eorder.browse.title = View Electronic Orders +eorder.enterorder = Enter Order +eorder.externalid = External ID +eorder.instruction = Scan Locator Form Barcode or enter patient \ + name or passport number and click Search +eorder.lastupdated = Last Updated +eorder.lastupdatedasc = Oldest -> Newest +eorder.lastupdateddesc = Newest -> Oldest +eorder.message = Original Message +eorder.noresults = No Results to Show +eorder.of = of +eorder.patient = Patient +eorder.patient.birthdate = Birthdate +eorder.patient.gender = Gender +eorder.patient.id = External ID +eorder.patient.name = Name +eorder.results = Showing Results +eorder.search.result.title = Test Requests Matching Search - Select Enter \ + to add a lab number and accept the order as \ + is, or select Edit to view more details or \ + make changes +eorder.sort = Sort Entries By +eorder.status = Status +eorder.table.highlighted.label = highlighted rows specifies a resource that is \ + likely out of sync with the server +eorder.timestamp = Timestamp error.2ndEntry.previous.not.matched = does not match the \ previous value @@ -2144,6 +2232,18 @@ error.analyzer.test.name.duplicate = The combination of \ error.birthdate.format = The patient birthdate \ is not in the correct \ format. +error.critical.range.value = Value is a critical \ + result. Please follow \ + normal critical result \ + procedures. +error.critical.range.value.high = High critical range \ + must be greater than \ + high normal and less \ + than high valid. +error.critical.range.value.low = Low critical range must \ + be greater than low \ + valid and less than low \ + normal. error.date = Date is invalid error.date.birthInPast = Date of birth must be \ in the past @@ -2163,8 +2263,9 @@ error.duplicate.STNumber = ST number belongs by \ another patient error.duplicate.nationalId = National ID belongs to \ another patient -error.duplicate.subjectNumber = Unique Health ID number belongs \ - to another patient +error.duplicate.subjectNumber = Unique Health ID number \ + belongs to another \ + patient error.duplicate.subjectNumber.warning = ID already in use error.field.charset.invalid = Illegal character in \ field "{0}". Must match \ @@ -2212,29 +2313,20 @@ error.low.normal.low.valid.order = Low normal range must \ be greater than or \ equal to the low valid \ range -error.out.side.range = Value is outside of reporting range. \ - Action Required. See procedure for further information. \ - Do you want to file this result? error.low.normal.value = Low normal value must \ be a number or \ '-Infinity' error.low.valid.value = Low valid range must be \ either a number or \ '-Infinity' -error.critical.range.value.low = Low critical range must be \ - greater than low valid and \ - less than low normal. -error.critical.range.value.high = High critical range must be \ - greater than high normal and \ - less than high valid. -error.critical.range.value = Value is a critical result. \ - Please follow normal critical result procedures. error.messageorganization.begindate.lessthan.enddate = Active End Date cannot \ be less than Active \ Begin Date. error.method.begindate.lessthan.enddate = Active End Date cannot \ be less than Active \ Begin Date. +error.method.invalid = Must match an existing \ + method error.missing.test.mapping = Unknown test sent by \ the analyzer.
\ Please note test name \ @@ -2245,6 +2337,16 @@ error.notentered = Sample could not be \ error.organizationType.required = At least one \ organization type must \ be selected +error.out.side.critical.range = Value is outside of \ + critical range. must be \ + between 0-10 or above 95 +error.out.side.range = Value is outside of \ + reporting range. Action \ + Required. See procedure \ + for further \ + information. Do you \ + want to file this \ + result? error.phone = Check Phone error.picklist = No Selections in the \ Picklist\\nPlease \ @@ -2375,7 +2477,6 @@ errors.final.result.required = Final HIV result is \ errors.float = {0} must be an float. errors.followingAccession = Errors for accession \ number {0} : -errors.resultValidated = Result has been validated by another user : {0} errors.footer = errors.general = The process did not \ complete. Details should \ @@ -2431,6 +2532,8 @@ errors.required.atLeastOneItem.forOneSelectBox = Select at least one {0}. errors.required.atLeastOneItem.forTwoSelectBoxes = Select at least one {0} \ and one {1}. errors.result.required = Result entry is required. +errors.resultValidated = Result has been validated \ + by another user : {0} errors.role.name.required = Name is required. errors.role.role.required = One or more roles are \ required. @@ -2514,6 +2617,10 @@ externalconnections.smtpserver = SMTP Server externalconnections.url.instruction = Specify connection end point \ e.g URL +field.contacttracing.indexname.label = Contact Tracing Index Name +field.contacttracing.indexrecordnumber.label = Contact Tracing Index Record \ + Number + footer.button.finish = Finish gender.add.subtitle = Add Gender @@ -2544,6 +2651,8 @@ homePage.menu.administration.toolTip = Administration tasks homePage.menu.labInteractions =
Lab
Interactions
homePage.menu.labInteractions.toolTip = Lab Interactions homePage.menu.logOut =
Log out
+homePage.menu.logOut.local = Local logout +homePage.menu.logOut.saml = SSO logout homePage.menu.logOut.toolTip = Log out homePage.menu.masterLists =
Master
Lists
homePage.menu.masterLists.toolTip = Master Lists @@ -2655,15 +2764,17 @@ humansampletwo.subtitle.requestor = Requesting Facility \ (1) humansampletwo.subtitle.sample = Sample Information (3) +input.label.startat.toggle = Use custom starting point + instruction.nonConformity.sample.id = If true then the sample number from \ the sending lab will be required \ when entering a non-conformity instruction.patient.id.required = If true then a patient ID will be \ required when new patient \ information is entered -instruction.patient.subNumber.required = If true then a Unique Health ID number will \ - be required when adding a new \ - patient +instruction.patient.subNumber.required = If true then a Unique Health ID \ + number will be required when adding \ + a new patient instruction.tabs.patientIdentity = If true then the patient management \ menu item will be in the menu @@ -2684,6 +2795,10 @@ instructions.clock = Set to true to use 24 hour clock or \ false to use 12 hour clock. \ Example: 24 hour clock 13:40 is \ 1:40 PM for 12 hour clock. +instructions.method.limit = If true the user must choose an \ + existing method and will not be \ + able to create a new method through \ + result entry.. instructions.nonconformity.collection = Set to true if Sample Collection \ should be listed with test sections \ for where non-conformity is being \ @@ -2803,8 +2918,9 @@ instructions.workplan.result = Set to true if there should be a \ Due to space limitation this will \ not allow for the next visit to \ also be printed. -instructions.workplan.subject = Set to true if the Unique Health ID number \ - should be printed on the workplan +instructions.workplan.subject = Set to true if the Unique Health ID \ + number should be printed on the \ + workplan inventory.manage.title = Manage test kits inventory.testKit = Test Kit @@ -2851,7 +2967,6 @@ label.biologist.CI_REG = Name label.browse.title = Label label.button.accept = Accept label.button.add = Add -label.button.new.user = New user label.button.add.note = Add Note #-- LIMS common request form entry-- label.button.addTest = Assign Test @@ -2865,7 +2980,6 @@ label.button.checkAll = Select All label.button.continue = Continue label.button.deactivate = Deactivate label.button.display = Display -label.button.modify = Modify label.button.edit = Edit label.button.edit.note = Edit Note label.button.editMultiples = Edit Multiples @@ -2875,7 +2989,9 @@ label.button.editTests = Add Tests label.button.exit = Exit label.button.finished = Finished label.button.hide = Hide +label.button.modify = Modify label.button.new.search = New Search +label.button.new.user = New user label.button.next = Next label.button.no = No label.button.picklist.add.arrow = -> @@ -2895,6 +3011,7 @@ label.button.runsearch = Run Search label.button.save = Save label.button.search = Search label.button.sort = Sort +label.button.ssoLogin = SSO Login label.button.submit = Submit label.button.tryAgain = Try Again label.button.uncheckAll = Deselect All @@ -2914,6 +3031,7 @@ label.color.red = Red label.comments = Comments label.computed = Computed label.confirmation = Confirmation +label.critical.range = Critical range label.current = Current label.current.date = Current Date label.currentTest = Current test @@ -2972,6 +3090,7 @@ label.new = New label.none = None label.not.available = not available label.notValidated = Not validated +label.note = Note label.openreports.activebegin = Active Begin: label.openreports.activeend = Active End: label.openreports.component = Component @@ -2994,28 +3113,34 @@ label.pagination.show = Show label.panel = Panel label.patient = Patient label.patient.search = Search +label.patient.search.external = External Search label.patient.search.select = Find lab order for \ this patient -label.patient.search.select.test = Find lab order with test for \ - this patient +label.patient.search.select.test = Find lab order with \ + test for this patient label.patient_name = Last Name, First \ Name(s) label.printerType = Label Printer Type label.prior.note = Prior Notes +label.priority.asap = ASAP +label.priority.futureStat = Future STAT +label.priority.routine = Routine +label.priority.stat = STAT +label.priority.timed = Timed label.program = Program label.provider = Provider label.qualifiers = Qualifiers label.range = Range -label.valid = Valid range label.reference.value = Reference value label.refusal.reason = Refusal Reason label.rejectedByBiologist = Rejected by biologist label.rejectedByTechnician = Rejected by technician +label.rememberSiteRequester = Remember site and \ + requester label.remove = Remove label.remove.image = Remove image label.replaceWith = Replace with label.reporting.range = Reporting range -label.critical.range = Critical range label.requester = Requester label.required.field = Indicates a required \ field @@ -3131,13 +3256,22 @@ label.true = true label.tubeType = Tube Type label.unitofmeasure = Unit of Measure label.uom = uom +label.valid = Valid range label.week = week label.year = year -label.priority.routine = Routine -label.priority.asap = ASAP -label.priority.stat = STAT -label.priority.timed = Timed -label.priority.futureStat = Future STAT + +labno.alt.prefix.error.length = Please enter a unique 4-character prefix for \ + preprinted barcodes +labno.alt.prefix.error.unique = Please choose a UNIQUE prefix that doesn't \ + match the generated lab accession numbers +labno.alt.prefix.instruction = Prefix for pre-printed barcode labels (4 \ + characters) +labno.alt.prefix.note = NOTE: If this prefix has already been used, \ + the numbering will continue from the last \ + number generated +labno.alt.prefix.use = Use the same accession number format and pool \ + of available numbers as Order Entry Generation +labno.alt.startAt = Start at list.of = of list.showing = Showing @@ -3177,10 +3311,14 @@ login.error.attempt.message = There have been {0} failed attempts to \ login. After {1} attempts the account \ will be locked for {2} minutes. login.error.message = Invalid login. Please try again -login.error.module.not.allow = You do not have access to this module. If you feel that you have received this message in error, please contact your system administrator. +login.error.module.not.allow = You do not have access to this module. \ + If you feel that you have received this \ + message in error, please contact your \ + system administrator. login.error.no.module = Sorry you have no module(s) assigned to \ you. Please contact system \ administrator. +login.error.noOeUser = No OE user exists for this user login.error.password.day = Passwords must be at least {0} days old \ before changing login.error.password.expired = Your password has expired. Please \ @@ -3192,12 +3330,12 @@ login.error.password.requirement = Password failed to meet the complexity \ instructions on the screen. login.error.session.message = Your session has expired. Please login \ again. +login.error.sessionsetup = Error setting up User Session login.error.system.user.id = User {0} is not in the system or is not \ active. Please contact system \ administrator. login.error.update.message = Update password failed. Please try \ again -login.error.sessionsetup = Error setting up User Session login.id = Login User Number login.is.admin = Is Admin login.login.name = Login Name @@ -3243,6 +3381,15 @@ marital.n_a = 7 = N/A for children marital.single = 1 = Single marital.widow = 5 = Widow(er) +menu.accession.validation = Search By Order +menu.accession.validation.range = Search By Range of Order Numbers +menu.label.filter = Filters +menu.label.filter.active = Only Active +menu.label.filter.admin = Only Administrator +menu.label.filter.role = By Lab Unit Roles +menu.results.range = By Range of Order Numbers +menu.validation.date = Search By Test Date + message.error.unauthorized = You do not have an authenticated \ session with the server.\nPlease log in \ and repeat your last action. @@ -3267,14 +3414,17 @@ method.activeBeginDate = Active Begin Date method.activeEndDate = Active End Date method.add.subtitle = Add Method method.add.title = Add Method -#--LIMS Method page -- -method.browse.title = Method +method.browse.title = Method Section method.description = Method Description method.edit.subtitle = Edit Method method.edit.title = Edit Method +method.entry.project.MaxMsg = ...matches more than 50 methods +method.existing = Existing Methods +method.existing.inactive = Inactive Methods. Assign tests to activate. method.id = Method Number method.isActive = Is Active -method.methodName = Method Name +method.methodName = Method Name +method.new = New Method method.reportingDescription = Method Reporting Description month.april.abbrev = Apr @@ -3290,6 +3440,8 @@ month.november.abbrev = Nov month.october.abbrev = Oct month.september.abbrev = Sept +months.label = Months + #--customized validation messages msg.phone.format = Invalid Phone Format. Accepted Format: {0} @@ -3562,8 +3714,6 @@ openreports.anthrax.title = Anthrax \ openreports.gonorrhea.title = Gonorrhea openreports.hiv.aggregate = HIV Test \ Summary -openreports.stat.aggregate = Statistics Report -openreports.mgt.rejection = Rejection Report openreports.hiv_eia_blood.title = HIV EIA \ Blood openreports.hiv_eia_oral.title = HIV EIA \ @@ -3577,8 +3727,10 @@ openreports.hiv_western_blot_oral.title = HIV \ Western \ Blot Oral openreports.hsv_typing.title = HSV Typing -openreports.management.title = Management \ +openreports.management.title = Management\ Reports +openreports.mgt.rejection = Rejection \ + Report openreports.micro_identification.title = Micro \ Identifica\ tion @@ -3772,6 +3924,8 @@ openreports.sib.title = SIB \ (Select \ Invasive \ Bacteria) +openreports.stat.aggregate = Statistics\ + Report openreports.syphilis_fta.title = Syphilis \ FTA openreports.syphilis_usr.title = Syphilis \ @@ -4134,9 +4288,12 @@ patient.schoolAttend = School Attended patient.search.all_IDs = Patient IDs patient.search.not.found = No patients found \ matching search terms -patient.site.subject.number = Site Unique Health ID number +patient.site.subject.number = Site Unique Health ID \ + number patient.subject.number = Unique Health ID number +patient.subject.tbnumber = TB code (XX-XXXXX) patient.type = Patient type +patient.upid.code = Unique Patient ID patient.ward = Ward patientEntryConfiguration.browse.title = Patient Entry Configuration @@ -4241,6 +4398,7 @@ project.ARVStudy.name = Initial ARV project.EIDStudy.name = EID project.IndeterminateStudy.name = Indeterminate project.RTNStudy.name = RTN +project.Recency.name = Recency Testing project.SequencingStudy.name = Sequencing project.SpecialRequestStudy.name = Special Request project.VLStudy.name = VL @@ -4376,6 +4534,8 @@ quick.entry.accession.number.2 = Thru Accession Number quick.entry.accession.number.CI = Lab No quick.entry.accession.number.batch.message = used for batches quick.entry.accession.number.thru = thru +quick.entry.accession.range = Load Next 99 Records Starting at \ + Lab No. quick.entry.add.title = Quick Entry quick.entry.assigned.tests = Assigned Tests quick.entry.edit.title = Quick Entry @@ -4437,6 +4597,8 @@ referral.header.group.request = Referral Request referral.header.group.results = Referral Results referral.institute = Institute referral.noReferralItems = No Referral Items +referral.noreferralDisplayItem = No Referrals matching criteria +referral.original.result = Orginal Result referral.out.manage = Referrals referral.reason = Reason for Referral referral.reason.EQA.testing = EQA by Repeat Testing @@ -4484,18 +4646,18 @@ report.account = Account report.accountHivTypeTest = HIV Tests by Test Type # Activity Report report.activity = Activity Report -report.turnaround = Turnaround -report.days = Days -report.hours = Hours report.activity.report.base = Activity report report.age = Age report.alert = Alert +report.all = All report.analysisReport = Results of Analysis report.appointmentDate = Tests Awaiting \ Validation +report.april = April report.assHeadOfBioclinicque = Assistants - Head \ Bioclinicque report.associateProfessor = Associate Professor +report.august = August report.belowNormal = Below Normal report.biologist = Biologist report.by.panel = By panel @@ -4546,6 +4708,8 @@ report.dateReviewedReceived = Reviewed / Released \ ____________________ \ by____________________\ ________________ +report.days = Days +report.december = December report.districtFacility = District report.email = Email report.enter.Service = Service @@ -4553,7 +4717,24 @@ report.enter.labNumber = Enter Lab Number report.enter.labNumber.detail = For a single lab, \ leave the right box \ empty. -report.enter.subjectNumber = By National ID / Unique Health ID number +report.enter.labNumber.headline = Generate a report or \ + range of reports by \ + Order Number / Lab \ + Number +report.enter.patient.headline = Generate All Reports \ + for a Client +report.enter.patient.headline.description = Search for the \ + patient via previous \ + lab number, Patient \ + ID (which can be \ + either Unique Health \ + ID number or national \ + ID) or other fields. +report.enter.site.headline = Generate Reports By \ + Site +report.enter.subjectNumber = By National ID / \ + Unique Health ID \ + number report.error.message.accession.not.valid = Lab Number not found report.error.message.activity.missing = Missing selection report.error.message.date.format = Date is not valid @@ -4573,6 +4754,7 @@ report.error.message.samePrefix = Laboratory number \ report.extLabReference = Reference to an \ external lab report.fax = Fax +report.february = February report.followup.general.comment = General Comment report.followup.no.authorizer = No authorizer \ specified @@ -4580,6 +4762,7 @@ report.followup.no.note = No note written report.followup.no.sampleType = No sample type \ specified report.followup.no.section = No section specified +report.followup.period = TB Followup Period report.footNote = * In Progress \ includes results that \ are : rejected by the \ @@ -4591,6 +4774,7 @@ report.from = From #Summary of all Tests report.globalLabReport = Global Laboratory \ Report +report.hours = Hours report.humanSampleList.organicunit.title = Human Sample List - \ Organic Unit #--REPORTTAB @@ -4609,6 +4793,9 @@ report.instruction.inventory.test.count = Selecting the site is \ is selected then all \ sites will be in the \ report +report.january = January +report.july = July +report.june = June report.labInfomation = General Comments report.labManager = Laboratory Manager report.labName.one.LNSP_Haiti = MINIST\u00C8RE DE LA \ @@ -4619,15 +4806,23 @@ report.labName.two.LNSP_Haiti = LABORATOIRE NATIONAL \ report.labTotal = Total Laboratories report.label.collectionDateTime = Collection date and \ time +report.label.datetype.orderdate = Order Date +report.label.datetype.printdate = Print Date +report.label.datetype.resultdate = Result Date report.label.days = Days report.label.labno = Lab No.: report.label.orderDateTime = Order date & time report.label.orderNo = Order No. : report.label.page = Page +report.label.site.dateType = Date Type +report.label.site.onlyResults = Only Reports with \ + results report.label.siteID = Page report.label.workplan = Workplan report.laboratory.unit = Laboratory Unit report.legend = Legend +report.march = March +report.may = May report.men = Men report.negative = Negative report.no.results = No results available @@ -4640,8 +4835,13 @@ report.noReportMessage = It is not possible to \ create the report at \ this time. report.normal = Normal +report.normalWorkingHours = Normal Work hours \ + (reception time \ + 9h-15h30) report.notStarted = Not Started report.note = Note +report.november = November +report.october = October report.of = Of report.orderDate = Date of order #Referred Test reports @@ -4650,9 +4850,22 @@ report.orderNo = Laboratory Number \ report.ordinanceNo = Order Number report.other = Other report.outcome = Result +report.outofnormalWorkingHours = Out of Normal Work \ + Hours (15h31-8h59) report.page = Page report.pageNumberOf = of report.patient.not.registered = Not registered +report.patient.site.description = Generate reports by \ + result date or by \ + order date. Result \ + date will show only \ + reports with results. \ + If you select onlt \ + resports with \ + results, all reports \ + where all tests are \ + in progress will not \ + be generated. report.patientCode = Patient code report.patientNameCode = Names / Codes of \ patient @@ -4693,6 +4906,7 @@ report.sample.xml.by.test.subtitle = Create XML - Samples \ report.sample.xml.by.test.title = Create XML - Samples \ By Test report.sampleType = Sample Type +report.samples = Samples report.section = Section report.section.not.specified = Not specified report.select.date.period = Select report period @@ -4701,12 +4915,39 @@ report.select.date.period.months.3 = past 3 months report.select.date.period.months.6 = past 6 months report.select.date.period.year = current year (jan-dec) report.select.labNumber = Select Lab Number +report.select.labUnit = Select the lab \ + unit(s) you would \ + like to create the \ + test for, you may \ + select as many as you \ + would like +report.select.priority = Select the priority \ + of the tests you \ + would like to show report.select.project = Select Study Type report.select.service.location = Referral Center or \ Laboratory report.select.site = Select site -report.select.subjectNumber = Select Unique Health ID number +report.select.subjectNumber = Select Unique Health \ + ID number +report.select.timeFrame = Select time frames \ + you would like to \ + generate the reports \ + for. +report.select.timeFrame.note = NOTE: all dates and \ + times are based on \ + reception time. EG: a \ + test received on Jan \ + 31 at 11:59 pm and \ + resulted Feb 1 at \ + 9:30am would show as \ + out of normal hours \ + in January +report.select.year = Select year you would \ + like to generate the \ + report for. report.selecte.date.period.custom = custom +report.september = September report.service = Service report.serviceHead = Head of Service report.sex = Sex @@ -4730,6 +4971,16 @@ report.supervisorSign = Supervisor's \ ______________________\ ____________Date______\ __________________ +report.tb.analysisMethod = TB Analysis method +report.tb.completedDate = Completed Date +report.tb.diagnostic.reason = Diagnostic Reason +report.tb.followup.period = TB followup Period +report.tb.followup.reason = TB Followup reason +report.tb.orderReason = TB order reason +report.tb.referingsite = Refering Site +report.tb.sample.aspect = Sample aspect +report.tb.sampleType = TB Sample Type +report.tb.testName = Test Name report.techId = Tech ID report.telephoneAbv = Tel report.test = Test @@ -4741,30 +4992,10 @@ report.test.status.referredOut = External Referrals \ report.testName = Name of test report.testSection = Test Section report.tests = Tests -report.samples = Samples report.to = To -report.january = January -report.february = February -report.march = March -report.april = April -report.may = May -report.june = June -report.july = July -report.august = August -report.september = September -report.october = October -report.november = November -report.december = December -report.normalWorkingHours = Normal Work hours (reception time 9h-15h30) -report.outofnormalWorkingHours = Out of Normal Work Hours (15h31-8h59) -report.all = All -report.select.labUnit = Select the lab unit(s) you would like to create the test for, you may select as many as you would like -report.select.priority = Select the priority of the tests you would like to show -report.select.timeFrame = Select time frames you would like to generate the reports for. -report.select.timeFrame.note = NOTE: all dates and times are based on reception time. EG: a test received on Jan 31 at 11:59 pm and resulted Feb 1 at 9:30am would show as out of normal hours in January -report.select.year = Select year you would like to generate the report for. # HIV summary report.total = Total +report.turnaround = Turnaround report.typeOfSample = Type of sample\u0009 report.undetermined = Indeterminate report.unit = Unit @@ -4810,6 +5041,8 @@ reports.label.patient.EID = Diagnostic for \ reports.label.patient.VL = Viral Load reports.label.patient.indeterminate = Indeterminate reports.label.project.export = Export a CSV File by +reports.label.project.export.dateType = Export a CSV File by \ + Date Type reports.label.referral.title = Referrals Out reports.label.referred.out = Referred Tests Reports reports.menu.covid = Covid Report @@ -4962,7 +5195,7 @@ result.forceAccept.warning = Checking\ of the \ change. \ \\n\\nIn\ - either \ + either \ case, \ leave a \ note \ @@ -5018,7 +5251,7 @@ result.notes = Notes\ \u0009\ \u0009\ \u0009 -result.original.result = Original \ +result.original.result = Original\ Result result.outOfValidRange.msg = The \ value \ @@ -5655,6 +5888,7 @@ resultsentry.tests.title = Test #--LIMS Results Entry: Tooltip resultsentry.tooltip.header = Tooltip +role.analyser = Analyser Import role.audittrail = Audit Trail role.browse.title = Roles role.description = Description @@ -5673,7 +5907,6 @@ role.results.all = Results View and Entry role.test.configuration = Test Management role.users = User Account Administrator role.validator = Validation -role.analyser = Analyser Import rror.field.time.invalid = Field "{0}" is an invalid time format @@ -5841,7 +6074,6 @@ sample.entry.invalid.accession.number.used = Accession number \ is already in use sample.entry.labID = Lab ID sample.entry.nextVisit.date = Date of next visit -entry.invalid.loinc.number.used = This LOINC is already in use, LOINC codes must be unique sample.entry.noTests = No appropriate \ tests for this \ sample type. \ @@ -5856,11 +6088,13 @@ sample.entry.patient = Patient sample.entry.patient.selection = Patient Selection sample.entry.patientPayment = Patient payment \ status +sample.entry.priority = Priority sample.entry.project = Activity sample.entry.project.ARV.cd4cd8Test = CD4/CD8 Test sample.entry.project.ARV.centerCode = Center Code sample.entry.project.ARV.centerName = Center Name sample.entry.project.ARV.creatinineTest = Creatinine Test +sample.entry.project.ARV.dbsvlTaken = DBS sample.entry.project.ARV.deptTitle = Biochemistry - \ Hematology - \ Immunology @@ -5869,6 +6103,7 @@ sample.entry.project.ARV.edtaTubeTaken = EDTA tube sample.entry.project.ARV.genotypingTest = Genotyping sample.entry.project.ARV.glycemiaTest = Glycemia Test sample.entry.project.ARV.nfsTest = NFS Test +sample.entry.project.ARV.pscvlTaken = PSC sample.entry.project.ARV.title = ARV sample.entry.project.ARV.transaminaseTest = Transaminase Test sample.entry.project.ARV.viralLoadTest = Viral Load Test @@ -5883,13 +6118,15 @@ sample.entry.project.EID.siteInfantNumber = DBS Site Infant \ sample.entry.project.EID.siteName = Site Name sample.entry.project.EID.title = EID sample.entry.project.EID.whichPCR = Which PCR ( 1 or 2) -sample.entry.project.LART = HARC -sample.entry.project.LDBS = HDBS +sample.entry.project.LART = LARS +sample.entry.project.LDBS = LDBS sample.entry.project.LIND = LIND sample.entry.project.LRTN = LRTN sample.entry.project.LSEQ = LSEQ sample.entry.project.LSPE = LSPE -sample.entry.project.LVL = HARC +sample.entry.project.LVL = LARS +sample.entry.project.RT = RTRI +sample.entry.project.RT.title = Recency Testing sample.entry.project.RTN.title = RTN sample.entry.project.VL.simple.title = Viral Load sample.entry.project.VL.title = ARV - Viral Load @@ -5955,6 +6192,11 @@ sample.entry.project.phoneNumber = Phone Number sample.entry.project.plqTest = PLQ sample.entry.project.receivedDate = Received Date sample.entry.project.receivedTime = Received Time +sample.entry.project.recency.asanteKit = Asante HIV-1 Rapid \ + Recency +sample.entry.project.recency.plasma = Plasma +sample.entry.project.recency.serum = Serum +sample.entry.project.recencyNumber = Recency ID No sample.entry.project.result = Result sample.entry.project.secondTest = Second Test sample.entry.project.secondTestName = Second Test Name @@ -5963,12 +6205,14 @@ sample.entry.project.sequencing.title = Sequencing sample.entry.project.serologyHIV = Serology HIV sample.entry.project.serologyHIVTest = Serology HIV Test sample.entry.project.siteCode = Site Code +sample.entry.project.siteDepartmentName = ward/dept/unit sample.entry.project.siteMaxMsg = ...matches more \ than 50 sites sample.entry.project.siteName = Site Name sample.entry.project.specialRequest.reason = Reason for Request sample.entry.project.specialRequest.title = Special Request -sample.entry.project.subjectNumber = Unique Health ID number +sample.entry.project.subjectNumber = Unique Health ID \ + number sample.entry.project.subjectSiteNumber = Subject Site sample.entry.project.tcmhTest = TCMH sample.entry.project.testName = Test Name @@ -5978,11 +6222,18 @@ sample.entry.project.title.dryTube = Dry Tube Tests sample.entry.project.title.edtaTube = EDTA Tube Tests sample.entry.project.title.infantInformation = Infant Information sample.entry.project.title.mothersInformation = Mothers Information +sample.entry.project.title.org = Facility sample.entry.project.title.otherTests = Other Tests +sample.entry.project.title.patientInfo = Patient \ + Informations +sample.entry.project.title.psc = PSC (?) +sample.entry.project.title.sample = Sample information +sample.entry.project.title.sampleType = Sample Type sample.entry.project.title.specimen = Specimens Collected sample.entry.project.title.tests = Tests sample.entry.project.transaminaseALTLTest = Transaminase ALTL sample.entry.project.transaminaseASTLTest = Transaminase ASTL +sample.entry.project.upidCode = Unique Patient ID sample.entry.project.vgmTest = VGM sample.entry.project.vironostikaTest = Vironostika sample.entry.project.vl.arv = Viral Load under \ @@ -5999,13 +6250,24 @@ sample.entry.project.vl.specify = Specify sample.entry.project.vl.virologicalfail = Virological Failure sample.entry.project.wb1Test = Western Blot 1 sample.entry.project.wb2Test = Western Blot 2 +sample.entry.provider = Requester sample.entry.provider.firstName = Requester's First \ Name sample.entry.provider.name = Requester's Last \ Name +sample.entry.referral.toggle = Refer test to a \ + reference lab sample.entry.referringSite.code = Referring Site Code +sample.entry.reject.warning = You are rejecting \ + a sample. This \ + sample will be \ + rejected and not \ + appear in \ + workplans once \ + saved,no results \ + can be entered for \ + this order. sample.entry.remove.sample = Remove Sample -sample.entry.sample.new = Add New Sample sample.entry.removeAllSamples = Remove All sample.entry.requestDate = Request Date sample.entry.requested.tests = Requested Tests @@ -6015,6 +6277,7 @@ sample.entry.runSearch = Run Search sample.entry.sample.condition = Condition sample.entry.sample.item = item sample.entry.sample.nature = Sample Nature +sample.entry.sample.new = Add New Sample sample.entry.sample.period = Sampling performed \ for analysis sample.entry.sample.tests = Tests @@ -6053,10 +6316,6 @@ sample.entry.updating.NonExistingPatient = Attempt to update \ a patient with a \ non-existing \ patientID -sample.entry.priority = Priority -sample.entry.reject.warning = You are rejecting a sample. \ - This sample will be rejected and not appear in workplans once saved,\ - no results can be entered for this order. sample.id = Sample Number sample.label.print.count = Number of Patients sample.label.print.count.per.patient = Number of labels \ @@ -6092,15 +6351,28 @@ sample.referring.patientNumber = Referrers Patient \ sample.releasedDate = Released Date sample.revision = Revision sample.sampleIdRelatesTo = Parent Sample +sample.search.date.instructions = Enter Test date sample.search.scanner.instructions = Scan or Enter \ Manually -sample.search.date.instructions = Enter Test date +sample.search.scanner.instructions.highaccession = For a single \ + report, leave the \ + box at the right \ + empty sample.status = Sample Status sample.stickerReceivedFlag = Sticker Received sample.sysUserId = User that received \ the Sample +sample.tb.aspects = Sample aspect +sample.tb.diagnostic.methods = TB Analysis method +sample.tb.diagnostic.reasons = TB diagnostic \ + reason +sample.tb.followup.reasons = TB followup reason +sample.tb.order.reasons = TB order reason +sample.tb.reference.unit = Reference unit +sample.tb.specimen.nature = Sample type sample.transmissionDate = Transmission Date sample.type.Coloration.de.Gram = Gram Stain +sample.type.PSC = PSC sample.type.ambionic.fluid = Ambionic fluid sample.type.ascite.fluid = Ascite fluid sample.type.blood = Blood @@ -6211,11 +6483,8 @@ site.info.nonConformity.sample.id = Is a sample id from the referring \ lab required site.info.patient.id.required = Is a patient ID required for a new \ patient -site.info.patient.subjectNumber.required = Is a Unique Health ID number required for a \ - new patient -siteInfo.instruction.nationalID.dup.d = Allow duplicate national ids -siteInfo.instruction.nationalID.req.d = National ID required -siteInfo.instruction.freeprovider.req.d = Restrict Free Text Provider Entry +site.info.patient.subjectNumber.required = Is a Unique Health ID number \ + required for a new patient site.info.result.age.adult = Adult site.info.result.age.child = Child site.info.result.age.infant = Infant @@ -6280,6 +6549,9 @@ siteInfo.dataSubmission = Show Option to submit data to VL \ DASH siteInfo.default.date.locale = The default date local siteInfo.default.language.locale = The default language local +siteInfo.description.default.barcode = Indicate the default number of bar \ + code labels which should be printed \ + with every order and specimen siteInfo.description.dimensions = Indicate the dimensions that bar \ code labels should conform to when \ printing @@ -6292,11 +6564,26 @@ siteInfo.description.max = Indicate the maximum number of bar \ maximum has been reached, a user \ will be unable to print additional \ labels. +siteInfo.description.max.barcode = Indicate the maximum number of bar \ + code labels that can be printed for \ + each order or specimen. Once the \ + maximum has been reached, a user \ + will be unable to print additional \ + labels. siteInfo.elements.mandatory = Mandatory Elements siteInfo.elements.optional = Optional Elements siteInfo.external.orders = Allow external sites to send \ electronic orders -siteInfo.instruction.directorname.d = The name of the lab director for the signature line +siteInfo.geographical.district = The Geographical sub-units for a \ + particular district +siteInfo.geographical.region = The Geographical units for a \ + particular region +siteInfo.instruction.contactTracing.d = Should the contact tracing fields \ + be activated +siteInfo.instruction.contactTracing.i = Should the contact tracing fields \ + be activated +siteInfo.instruction.directorname.d = The name of the lab director for \ + the signature line siteInfo.instruction.directorname.i = Enter the name of the lab director siteInfo.instruction.directorsignature.d = The signature of the lab director \ that should be placed on generated \ @@ -6305,6 +6592,11 @@ siteInfo.instruction.directorsignature.i = Select a jpg file that contains the \ lab directors signature. siteInfo.instruction.directortitle.d = The title of the lab director siteInfo.instruction.directortitle.i = Enter the title of the lab director +siteInfo.instruction.freeprovider.req.d = Restrict Free Text Provider Entry +siteInfo.instruction.georaphical.one = The Geographical sub-units for a \ + particular region +siteInfo.instruction.georaphical.two = The Geographical sub-units for a \ + particular district siteInfo.instruction.labLogo.left = Use file upload to set the lab logo \ for the left side of report header. \ The file must be either a jpg, png \ @@ -6313,15 +6605,30 @@ siteInfo.instruction.labLogo.right = Use file upload to set the lab logo \ for the right side of report \ header. The file must be either a \ jpg, png or gif. +siteInfo.instruction.label.one = The address lines 1 can be used to \ + specify anything +siteInfo.instruction.label.three = The address lines 3 can be used to \ + specify anything +siteInfo.instruction.label.two = The address lines 2 can be used to \ + specify anything +siteInfo.instruction.nationalID.dup.d = Allow duplicate national ids +siteInfo.instruction.nationalID.req.d = National ID required siteInfo.instruction.patient.nationality = Set to true to allow nationality be \ part of patient information. This \ may require nationalities to be \ entered into the database. -siteInfo.lab.director = The laboratory manager name for the report header +siteInfo.lab.director = The laboratory manager name for the \ + report header siteInfo.lab.logo.left = Provides for uploading report left \ lab logo siteInfo.lab.logo.right = Provides for uploading report right \ lab logo +siteInfo.label.one = The address lines 1 can be used to \ + specify anything +siteInfo.label.three = The address lines 3 can be used to \ + specify anything +siteInfo.label.two = The address lines 2 can be used to \ + specify anything siteInfo.malariaCaseReport = True to send reports, false \ otherwise siteInfo.malariaCaseURL = The URL for malaria case reports @@ -6356,6 +6663,10 @@ siteInfo.reflex_rules = What set of reflex rules are used. \ From a predefined list siteInfo.reportConfig.reportDirectory = Report Directory siteInfo.reportPageNumbers = use page numbers on reports +siteInfo.restrictFreeTextMethodEntry = If true the user must choose an \ + existing method and will not be \ + able to create a new method through \ + result entry. siteInfo.restrictFreeTextRefSiteEntry = If true the user must choose an \ existing referring site and will \ not be able to create a new site \ @@ -6368,6 +6679,7 @@ siteInfo.results.on.workplan = Should there be a space for results \ on workplan siteInfo.roleForPatientOnResults = Is patient information restricted \ to those in correct role +siteInfo.section.altAccession = Preprinted Bar Code Accession number siteInfo.section.elements = Bar Code Label Elements siteInfo.section.number = Number Bar Code Label siteInfo.section.size = Dimensions Bar Code Label @@ -6387,8 +6699,8 @@ siteInfo.statusRules = statusRules determine specific \ ex: LNSP_haiti siteInfo.stringContext = The context for the property, ex: \ Cote d' Iviore -siteInfo.subject.on.workplan = Use the Unique Health ID number on the \ - workplan +siteInfo.subject.on.workplan = Use the Unique Health ID number on \ + the workplan siteInfo.testUsageAggregationPassword = The password for accesser to the \ service for aggregating test usage siteInfo.testUsageAggregationUrl = The url of the site to which test \ @@ -6400,6 +6712,8 @@ siteInfo.testUsageReporting = Should reporting testUsage \ siteInfo.testUsageSendStatus = The status of what happened the \ last time an attempt was made to \ send the report +siteInfo.title.default.barcode = Default Bar Code Labels +siteInfo.title.max.barcode = Maximum Bar Code Labels siteInfo.trackPayment = If true track patient payment for \ services siteInfo.useExternalPatientSource = Use an external source patient \ @@ -6413,17 +6727,6 @@ siteInfo.validateTechnicalRejection = If true and a technician rejects \ be validated siteInfo.validationOnlyNotesAreExternal = If true note are internal except \ validation -siteInfo.label.one = The address lines 1 can be used to specify anything -siteInfo.label.two = The address lines 2 can be used to specify anything -siteInfo.label.three = The address lines 3 can be used to specify anything -siteInfo.instruction.label.one = The address lines 1 can be used to specify anything -siteInfo.instruction.label.two = The address lines 2 can be used to specify anything -siteInfo.instruction.label.three = The address lines 3 can be used to specify anything -siteInfo.geographical.region = The Geographical units for a particular region -siteInfo.geographical.district = The Geographical sub-units for a particular district -siteInfo.instruction.georaphical.one = The Geographical sub-units for a particular region -siteInfo.instruction.georaphical.two = The Geographical sub-units for a particular district - siteInformation.add.title = Add site information siteInformation.browse.title = Site Information @@ -6431,8 +6734,8 @@ siteInformation.edit.title = Edit site information siteInformation.instruction.headerInfo = This text will appear in the header \ of reports which support a \ additional information. To split \ - into two lines use HTML br Tag between \ - lines + into two lines use HTML br Tag \ + between lines siteInformation.instruction.sortQaEvents = Turning on will sort qa events \ alphabetically in lists. Will not \ take effect until server reboot. @@ -6499,9 +6802,36 @@ statusofsample.name = Name statusofsample.statusofsample = Status of Sample statusofsample.statustype = Status Type -system.role.module.add.title = Add Role Module -system.role.module.browse.title = System Role Module -system.role.module.edit.title = Edit Role Module +study.eorder.action.edit = Editer +study.eorder.action.enter = Entrer +study.eorder.action.reject = Rejeter +study.eorder.action.title = Actions +study.eorder.all_status = All Statuses +study.eorder.browse.title = View study electronic orders +study.eorder.choose_site.label = Please choose a facility +study.eorder.lab_number = Lab Number +study.eorder.patient.birth_date = Date of Birth +study.eorder.patient.code = Patient Code +study.eorder.patient.gender = Gender +study.eorder.patient.upid = Patient UPID +study.eorder.request.date = Request Date +study.eorder.request.id = Request Identifier +study.eorder.request.priority = Priority +study.eorder.request.status = Order Status +study.eorder.request.test_name = Test name +study.eorder.requester.facility = Facility +study.eorder.search.date.end = End Date +study.eorder.search.date.start = Start Date +study.eorder.search.date_range.title = Enter the date range for test requests. \ + This will search by the date of the \ + referral, or the order date of the \ + electronic request +study.eorder.search.title = Search electronic orders by patient \ + code or facility + +system.role.module.add.title = Add Role Module +system.role.module.browse.title = System Role Module +system.role.module.edit.title = Edit Role Module systemmodule.add.title = Add System Module #--LIMS SystemModule page -- @@ -6521,30 +6851,30 @@ systemmodule.instructions = The module name is what the system uses to \ that is wanted.
Sometimes the same page is \ used but with a separate parameter to direct the \ application. For \ - instance:
../../openElis/Results?type=hem\ - atology says to get the results for \ + instance:
../../openElis/Results?type=hemato\ + logy says to get the results for \ hematology.
The name for this action should be \ "Results:hematology"
Note the use of ':' as \ the separator between the page and the parameter \ values. systemmodule.name = Module Name -systemuser.add.subtitle = Add System User -systemuser.add.title = Add System User +systemuser.add.subtitle = Add System User +systemuser.add.title = Add System User #--LIMS SystemUser page -- -systemuser.browse.title = System User -systemuser.edit.subtitle = Edit System User -systemuser.edit.title = Edit System User -systemuser.externalId = System User External Id -systemuser.firstName = System User First Name -systemuser.id = System User Number -systemuser.initials = System User Initials -systemuser.isActive = Is Active -systemuser.isEmployee = Is Employee -systemuser.lastName = System User Last Name -systemuser.loginName = System User Login Name -systemuser.name = Name -systemuser.systemuser = System User +systemuser.browse.title = System User +systemuser.edit.subtitle = Edit System User +systemuser.edit.title = Edit System User +systemuser.externalId = System User External Id +systemuser.firstName = System User First Name +systemuser.id = System User Number +systemuser.initials = System User Initials +systemuser.isActive = Is Active +systemuser.isEmployee = Is Employee +systemuser.lastName = System User Last Name +systemuser.loginName = System User Login Name +systemuser.name = Name +systemuser.systemuser = System User systemusermodule.add.title = Add System User Module #--LIMS SystemUserModule page -- @@ -6558,12 +6888,57 @@ systemusermodule.id = System User Module Number systemusermodule.system.module.id = System module Id systemusermodule.system.user.id = System user Id -systemuserrole.browse.title = User Role -systemuserrole.role = Role -systemuserrole.roles = Roles -systemuserrole.roles.global = Global Roles -systemuserrole.roles.labunit = Lab Unit Roles -systemuserrole.user = User +systemuserrole.allLabUnits = All Lab Units +systemuserrole.allpermissions = All Permissions +systemuserrole.apply = Apply +systemuserrole.browse.title = User Role +systemuserrole.copypermisions = Copy Permisions From User +systemuserrole.instruction =

Roles

There are two \ + types of Roles. Global Roles which \ + are set for the entire application \ + and Lab Unit Roles which can be \ + set for all Lab Units or specific \ + Lab Units.

The available \ + Global Roles are: GLobal \ + Administrator (Acces to all Admin \ + Functions) ,Audit Trail (Access to \ + all Audit Trail) ,
User Account \ + Administrator (has acces to all \ + the user account administration \ + features ,but not any other admin \ + functions)

The Lab Unit \ + Roles are: Reception (Access to \ + the Order, Patient, and \ + Non-Conformity Tabs) ,Results \ + (Access to the Work Plan, \ + Non-Conformity, and Results Tabs) \ + ,Validation (Access to the \ + Validation and Non-Conformity \ + Tabs) ,
Reports (Acces to \ + Reports Tab except CSV export only \ + Availbale for Global \ + Administrators).
To assign Lab \ + Unit Roles ,select all lab units \ + or the specific lab unit from the \ + drop down and select any roles you \ + would like to set.

You can \ + also use the Copy Permisions \ + Feature to copy the permisions of \ + an existing user.Ensure that you \ + have filled all the information \ + above and enter the user name \ + whose permissions you want to copy \ + into the box and click apply. +systemuserrole.newpermissions = Add New Permissons +systemuserrole.role = Role +systemuserrole.roles = Roles +systemuserrole.roles.global = Global Roles +systemuserrole.roles.labunit = Lab Unit Roles +systemuserrole.select.allLabUnits.warning = Selecting All Lab Units will \ + Overide other Lab Unit Permisions +systemuserrole.user = User +systemuserrole.warning.replace = Warning! All current permissions \ + will be replaced! #--LIMS SystemUserSection page -- systemusersection.browse.title = System User Section @@ -6605,6 +6980,9 @@ test.has.result = Resul\ test.id = Test \ Numbe\ r +test.inLabOnly = In \ + Lab \ + Only test.isActive = Is \ Activ\ e @@ -6618,7 +6996,7 @@ test.methodName = Test \ d test.modify.save.warning = You \ are \ - about \ + about\ to \ delet\ e a \ @@ -6627,14 +7005,14 @@ test.modify.save.warning = You \ its \ resul\ t.\\n\ - \\nDo \ + \\nDo\ you \ wish \ to \ conti\ nue? test.modify.static.warning = Cance\ - lling \ + lling\ a \ test \ or \ @@ -6645,7 +7023,6 @@ test.modify.static.warning = Cance\ men \ for \ which\ - \ resul\ ts \ have \ @@ -6685,7 +7062,6 @@ test.notifyResults = Notif\ of \ Resul\ ts -test.inLabOnly = In Lab Only test.scriptletName = Test \ Scrip\ tlet @@ -6794,14 +7170,14 @@ testSection.VL = Virology Viral Load testSection.Virology = Virology testSection.testSectionName = Test Section Name - +testUnit.existing = Existing Test Units testUnit.existing.inactive = Inactive Test Units. Assign tests to activate. -method.existing.inactive = Inactive Methods. Assign tests to activate. testUnit.new = New Unit Test method.new = New Method method.browse.title = Method Section +test_section.TB = Tuberculosis testanalyte.add.subtitle = Add \ Test \ @@ -7508,6 +7884,9 @@ tooltip.banner.menu.results.facscanto = DB FacsCANTO analyzer \ tooltip.banner.menu.results.logbook.hemato-immunology = Hemato-Immunology tooltip.banner.menu.results.logbook.mycology = Mycology tooltip.banner.menu.workplan.panel = By Panel Type +tooltip.bannner.menu.microbiology = Microbiology +tooltip.bannner.menu.microbiology_classic = Microbiology +tooltip.bannner.menu.microbiology_tb = Tuberculosis tooltip.menu.report.aggregate.site.test.count = Test counts across \ sites tooltip.project.SpecialRequestStudy.name = Special Request @@ -7575,18 +7954,22 @@ uom.uomName = Unit Of Measure Name upload.profile.instructions = Upload a comma delimited csv of names that will \ be active -validationentry.accession.range = Get Tests For Lab No. -validationentry.date.search = Get Tests For Test Date -quick.entry.accession.range = Load Next 99 Records Starting at Lab No. +user.select.instruction = Select a User to Modify or to Deactivate . You can \ + set a Filter ,Search for users, or Add a User along \ + with the controls at the top +user.userSearch = User Names + validation.accept = Save validation.accept.all = Save all results validation.accept.explanation = Choosing "Save" will record the result \ shown into OpenELIS validation.accept.normal = Save all normal results +validation.date.title = Validation By Test Date validation.delete = Ignore validation.delete.explanation = Choosing "Ignore" will not record the \ result or the test run into OpenELIS validation.note.retest = Redo test +validation.range.title = Validation Range validation.reject = Retest validation.reject.all = Retest all results validation.reject.explanation = Choosing "Retest" will record the \ @@ -7598,6 +7981,9 @@ validation.title = Validation {0} validationconfiguration.browse.title = Field Validation Configuration +validationentry.accession.range = Get Tests For Lab No. +validationentry.date.search = Get Tests For Test Date + vn.hse1.emergency = Emergency vn.hse1.ext = Either remove Work Phone \ Extension or enter a value for \ @@ -7656,6 +8042,7 @@ workplan.hematology.title = Hematology Workplan workplan.immunology.title = Immunology Workplan workplan.liquidBio.title = Liquid Biology Workplan workplan.malaria.title = Malaria Workplan +workplan.method = Method workplan.molecularBio.title = Molecular Biology Workplan workplan.mycology.title = Mycology Workplan workplan.mycrobacteriology.title = Mycrobacteriology Workplan @@ -7664,6 +8051,8 @@ workplan.panel.title = Workplan By Panel workplan.panel.types = Panel Type workplan.parasitology.title = Parasitology Workplan workplan.print = Print Workplan +workplan.priority.list = Priority +workplan.priority.title = Workplan By Priority workplan.run = Get Workplan workplan.serology.immunology.title = Serology-Immmunology Workplan workplan.serology.title = Serology Workplan @@ -7673,11 +8062,11 @@ workplan.title = Workplan workplan.unit.types = Unit Type workplan.vct.title = HIV Workplan workplan.virology.title = Virology Workplan -workplan.priority.list = Priority -workplan.priority.title = Workplan By Priority workplanConfiguration.browse.title = Workplan Configuration +years.label = Years + zipcode.add.subtitle = Add ZipCode zipcode.add.title = Add ZipCode zipcode.browse.title = ZipCode diff --git a/src/main/resources/languages/message_fr.properties b/src/main/resources/languages/message_fr.properties index 754e861f78..17dd9aa1e9 100644 --- a/src/main/resources/languages/message_fr.properties +++ b/src/main/resources/languages/message_fr.properties @@ -1,5 +1,7 @@ #Generated by Eclipse Messages Editor (Eclipse Babel) +$R{report.followup.period.l1} = Mois + AIDSStage.adultA = 1 = Stade A (Adulte) AIDSStage.adultB = 2 = Stade B (Adulte) AIDSStage.adultC = 3 = Stade C (Adulte) @@ -44,6 +46,35 @@ HIVStatus.HIVDual = VIH-1+2 HIVStatus.HIV_1 = VIH-1 HIVStatus.HIV_2 = VIH-2 +Les\ ru00C3u00B4les\ globaux\ disponibles\ sont = administrateur global (acc\u00C3\ + \u00A8s \u00C3\u00A0 toutes les \ + fonctions d'administration), \ + piste d'audit (acc\u00C3\u00A8s \ + \u00C3\u00A0 toutes les pistes \ + d'audit),
Administrateur de \ + compte d'utilisateur (a \ + acc\u00C3\u00A8s \u00C3\u00A0 \ + toutes les \ + fonctionnalit\u00C3\u00A9s \ + d'administration de compte \ + d'utilisateur, mais pas \ + \u00C3\u00A0 d'autres fonctions \ + d'administration)

Les \ + r\u00C3\u00B4les de l'unit\u00C3\ + \u00A9 de laboratoire sont : \ + R\u00C3\u00A9ception \ + (Acc\u00C3\u00A8s aux onglets \ + Commande, Patient et \ + Non-conformit\u00C3\u00A9) , \ + R\u00C3\u00A9sultats \ + (Acc\u00C3\u00A8s aux onglets \ + Plan de travail, \ + Non-conformit\u00C3\u00A9 et \ + R\u00C3\u00A9sultats) , \ + Validation (Acc\u00C3\u00A8s aux \ + onglets Validation et \ + Non-conformit\u00C3\u00A9) ,
+ MenuStatementConfig.browse.title = Configuration des menus OE2 = @@ -63,6 +94,10 @@ action.type = Type d'Action active.text.field = Activ\u00E9 +add.recency.sample.title = Ajouter un test de d\u00E9tection d'infection \ + r\u00E9cente +add.tb.sample.title = Ajouter un examen TB + age.anyAge = Tout \u00E2ge alert.error = Erreur @@ -159,7 +194,6 @@ banner.menu.editPatient.ReadWrite = Modifier Patient banner.menu.editSample.ReadOnly = Consulter Ordonnance banner.menu.editSample.ReadWrite = Modifier Ordonnance banner.menu.eorders = Demandes Electroniques -banner.menu.study.eorders = Demandes Electroniques banner.menu.help = Aide banner.menu.help.documents = Documents de \ proc\u00E9dures @@ -187,6 +221,10 @@ banner.menu.ie.warning = Les menus ne fonctionnera \ d'ex\u00E9cution en mode \ compatibilit\u00E9. banner.menu.inventory = Inventaire +banner.menu.microbiology = Microbiologie +banner.menu.microbiology_classic = Bact\u00E9riologie \ + Classique +banner.menu.microbiology_tb = Tuberculose banner.menu.nonconformity = Non Conformit\u00E9 banner.menu.nonconformity.correctiveActions = Mesures correctives # TODO: translate to french @@ -298,6 +336,8 @@ banner.menu.sampleBatchEntry = Ajouter Ordonnances En Lot banner.menu.sampleConsult = Consulter banner.menu.sampleCreate = Etude banner.menu.sampleEdit = Modifier Ordonnance +banner.menu.study.eorders = Demandes Electroniques +banner.menu.study.recency = Recency Testing banner.menu.workplan = Plan de Travail banner.menu.workplan.Biochemistry = Biochimie banner.menu.workplan.Hematology = H\u00E9matologie @@ -310,9 +350,9 @@ banner.menu.workplan.malaria = Paludisme banner.menu.workplan.mycology = Mycologie banner.menu.workplan.panel = Par panel banner.menu.workplan.parasitology = Parasitologie +banner.menu.workplan.priority = Par priorit\u00C3\u00A9 banner.menu.workplan.serology-immunology = S\u00E9rologie-Immunologie banner.menu.workplan.test = Par test -banner.menu.workplan.priority = Par priorité barcode.button.print = Imprimer Etiquettes barcode.common.button.print = Imprimer Etiquettes @@ -430,6 +470,21 @@ codeelementxref.edit.title = \u00C9diter R\u00E9f\u00E9rence \u00E0 \ configuration.batch.test.reassignment = R\u00E9attribuer ou \ annuler des tests en nombre +configuration.method = G\u00C3\u00A9rer les \ + m\u00C3\u00A9thodes +configuration.method.explain = Utiliser pour \ + cr\u00C3\u00A9er une \ + nouvelle \ + m\u00C3\u00A9thode, \ + activer ou \ + d\u00C3\u00A9sactiver une \ + m\u00C3\u00A9thode +configuration.method.rename = Renommer les \ + m\u00C3\u00A9thodes +configuration.method.rename.explain = Utilisez pour corriger le \ + nom des \ + m\u00C3\u00A9thodes \ + existantes. configuration.panel.assign = Affecter l'analyse au panel configuration.panel.assign.deactivate = desactiver le lien de \ l'analyse au panel @@ -846,12 +901,11 @@ configuration.test.add.guide.verify = V\u00E9rifiez que \ valeurs incorrectes. configuration.test.catalog = Afficher le catalogue des \ tests -configuration.test.catalog.age.range.months = Plage d'Age (en mois) -configuration.method = Gérer les méthodes -configuration.method.explain = Utiliser pour créer une nouvelle méthode, activer ou désactiver une méthode +configuration.test.catalog.age.range = Plage d'Age configuration.test.catalog.age.range.days = Plage d'Age (en jours) configuration.test.catalog.age.range = Plage d'Age configuration.test.catalog.critical.range = Plage critique +configuration.test.catalog.age.range.months = Plage d'Age (en mois) configuration.test.catalog.explain = Afficher le catalogue des \ tests courants configuration.test.catalog.guide = \ Nom du \ @@ -1100,6 +1154,7 @@ configuration.test.catalog.reference.value = Valeur de \ r\u00E9f\u00E9rence configuration.test.catalog.report.name = Nom du test affich\u00E9 \ sur les rapports +configuration.test.catalog.reporting.range = Plage de rapport configuration.test.catalog.result.limits = Limites du r\u00E9sultat configuration.test.catalog.sections = S\u00E9lectionner \ l'unit\u00E9 de \ @@ -1108,7 +1163,6 @@ configuration.test.catalog.sections = S\u00E9lectionner \ pour cette unit\u00E9 configuration.test.catalog.select.values = Valeurs de liste configuration.test.catalog.valid.range = Plage valide -configuration.test.catalog.reporting.range = Plage de rapport configuration.test.management = Gestion des tests configuration.test.management.organization = Organisation des Tests configuration.test.management.spelling = Modifications et \ @@ -1347,8 +1401,6 @@ configuration.test.orderable.explain = Un test disponible peut \ que test r\u00E9flexe. configuration.test.rename = Modifier les noms des \ tests actuels -configuration.method.rename = Renommer les méthodes -configuration.method.rename.explain = Utilisez pour corriger le nom des méthodes existantes. configuration.test.rename.explain = Utiliser cette option pour \ renommer les tests \ actuels. Cela change \ @@ -1563,6 +1615,7 @@ date.format.display.year = aaaa date.format.formatKey = dd/MM/yyyy date.two.digit.year = AA +days.label = jours db.organization.type.name.refering = Laboratoire de r\u00E9f\u00E9rence db.organization.type.name.testkit = Laboratoire d'approvisionnement \ @@ -1666,6 +1719,10 @@ dictionary.program.initial = Programme PVVIH \ - Bilan initial dictionary.program.routine = Analyses de \ routine +dictionary.recency.result.Inconclusive = Non-Concluant +dictionary.recency.result.Invalid = Invalide +dictionary.recency.result.long_term = Long Terme +dictionary.recency.result.recent = R\u00E9cent dictionary.reject.result.already.available = Besoin de \ re-tester. \ Echantillon \ @@ -2480,6 +2537,73 @@ dictionary.result.rouge = rouge dictionary.result.salivaire = salivaire dictionary.result.semi_liquide = semi liquide dictionary.result.trace = trace +dictionary.tb.aspect.bloody = Sanglant +dictionary.tb.aspect.mucopurulent = Muco-purulent +dictionary.tb.aspect.salivary = Salivaire +dictionary.tb.culture = Culture TB +dictionary.tb.diagnostic.molecular = Diagnostic \ + mol\u00E9culaire \ + TB +dictionary.tb.followup.line1 = Examen de suivi \ + 1 i\u00E8re \ + ligne (TB \ + Sensible) +dictionary.tb.followup.line2 = Examen de suivi \ + 2i\u00E8me ligne \ + (TB/RR ; TBXDR) +dictionary.tb.immunologic_diagnostic = Diagnostic \ + Immunologique TB +dictionary.tb.lpa_tests = Tests de \ + sensibilit\u00E9 \ + genotypique LPA +dictionary.tb.microscopy = Microscopie TB +dictionary.tb.order.diagnostic = Diagnostic +dictionary.tb.order.failure = Echec +dictionary.tb.order.followup = Suivi +dictionary.tb.order.never_dealt = Cas \ + pr\u00E9sum\ + \u00E9 jamais \ + trait\u00E9 +dictionary.tb.order.relapse = Rechute +dictionary.tb.order.resumption = Reprise +dictionary.tb.order.smear_positivem2 = Frottis positif \ + \u00E0 M2 +dictionary.tb.phenotypic_tests = Tests de \ + sensibilit\u00E9 \ + ph\u00E9notypique +dictionary.tb.result.culture_cont = Culture contamin\ + \u00E9e +dictionary.tb.result.culture_neg = Culture \ + n\u00E9gative +dictionary.tb.result.culture_pos = Culture positive +dictionary.tb.result.culture_res = Resistant +dictionary.tb.result.culture_sens = Sensible +dictionary.tb.result.error = Erreur +dictionary.tb.result.invalide = Invalide +dictionary.tb.result.mtb_detected = MTB \ + d\u00E9tect\u00E9 +dictionary.tb.result.mtb_detected_resistant = MTB \ + d\u00E9tect\ + \u00E9 RIF \ + R\u00E9sistant +dictionary.tb.result.mtb_detected_sensible = MTB \ + d\u00E9tect\ + \u00E9 RIF \ + sensible +dictionary.tb.result.mtb_ind = MTB \ + d\u00E9tect\ + \u00E9 RIF \ + ind\u00E9termin\ + \u00E9 +dictionary.tb.result.mtb_not_detected = MTB non \ + d\u00E9tect\u00E9 +dictionary.tb.result.mtb_pos1P = Positif 1+ +dictionary.tb.result.mtb_pos2P = Positif 2+ +dictionary.tb.result.mtb_pos3P = Positif 3+ +dictionary.tb.result.mtb_posRB = Positif Rare BAAR +dictionary.tb.result.negative = N\u00E9gatif +dictionary.tb.result.no_result = Pas de \ + r\u00E9sultat dictionarycategory.add.subtitle = Ajouter Cat\u00E9gorie du Dictionnaire dictionarycategory.add.title = Ajouter Cat\u00E9gorie du Dictionnaire @@ -2547,24 +2671,23 @@ education.postSecondary = 4 = Sup\u00E9rieur education.primary = 2 = Primaire education.secondary = 3 = Secondaire -electronic.order.warning.missingPatientInfo = L'information des patients \ - n'est pas compl\u00E8te. S'il \ - vous pla\u00EEt ajoutez \ - num\u00E9ro date de naissance, \ - le sexe ou l'identifiant. - -electronic.order.message.canceled = Ordonnance a \u00E9t\u00E9 \ - annul\u00E9e par le \ - r\u00E9f\u00E9rent. -electronic.order.message.orderNotFound = Afin de ne pas trouv\u00E9e pour \ - num\u00E9ro d'\u00E9chantillon du \ - site r\u00E9f\u00E9rant. -electronic.order.message.realized = Ordonnance a d\u00E9j\u00E0 \ - \u00E9t\u00E9 entr\u00E9 dans le syst\ - \u00E8me. -electronic.order.message.suggestion = Essayez de re-v\u00E9rifier le \ - num\u00E9ro de commande ou entrer \ - dans l'ordre manuellement. +electronic.order.message.canceled = Ordonnance a \u00E9t\u00E9 annul\ + \u00E9e par le \ + r\u00E9f\u00E9rent. +electronic.order.message.orderNotFound = Afin de ne pas trouv\u00E9e pour \ + num\u00E9ro d'\u00E9chantillon \ + du site r\u00E9f\u00E9rant. +electronic.order.message.realized = Ordonnance a d\u00E9j\u00E0 \ + \u00E9t\u00E9 entr\u00E9 dans le \ + syst\u00E8me. +electronic.order.message.suggestion = Essayez de re-v\u00E9rifier le \ + num\u00E9ro de commande ou \ + entrer dans l'ordre manuellement. +electronic.order.warning.missingPatientInfo = L'information des patients n'est \ + pas compl\u00E8te. S'il vous pla\ + \u00EEt ajoutez num\u00E9ro date \ + de naissance, le sexe ou \ + l'identifiant. ellis.configuration = Configuration ellis.login.user.name = Utilisateur Actuel @@ -2572,26 +2695,40 @@ ellis.version = Version emergency.contact = Emergency Contact (todo) -eorder.browse.title = Voir les Demandes Electroniques -eorder.enterorder = Ajouter Ordonnance -eorder.externalid = Identifiant Externe -eorder.instruction = Scan Locator Form Barcode or enter patient name or \ - passport number and click Search (translate) -eorder.lastupdated = Derni\u00E8re mise \u00E0 jour -eorder.lastupdatedasc = Oldest -> Newest -eorder.lastupdateddesc = Newest -> Oldest -eorder.message = Message Original -eorder.noresults = Pas de Resultats \u00E0 afficher -eorder.of = de -eorder.patient = Patient -eorder.patient.birthdate = Date de Naissance -eorder.patient.gender = Sexe -eorder.patient.id = Identifiant Externe -eorder.patient.name = Nom -eorder.results = Voir les Resultats -eorder.sort = Trier par -eorder.status = Statut -eorder.timestamp = Horodatage +entry.invalid.loinc.number.used = Ce LOINC est d\u00C3\u00A9j\u00C3\u00A0 \ + utilis\u00C3\u00A9. Les codes LOINC doivent \ + \u00C3\u00AAtre uniques + +eorder.browse.title = Voir les Demandes Electroniques +eorder.enterorder = Ajouter Ordonnance +eorder.externalid = Identifiant Externe +eorder.instruction = Scan Locator Form Barcode or enter patient \ + name or passport number and click Search \ + (translate) +eorder.lastupdated = Derni\u00E8re mise \u00E0 jour +eorder.lastupdatedasc = Oldest -> Newest +eorder.lastupdateddesc = Newest -> Oldest +eorder.message = Message Original +eorder.noresults = Pas de Resultats \u00E0 afficher +eorder.of = de +eorder.patient = Patient +eorder.patient.birthdate = Date de Naissance +eorder.patient.gender = Sexe +eorder.patient.id = Identifiant Externe +eorder.patient.name = Nom +eorder.results = Voir les Resultats +eorder.search.result.title = Demandes correspondant a la recherche - \ + Choisir Entrer pour ajouter un num\u00E9ro \ + labo et accepter la demande,choisir Editer \ + pour voir plus de d\u00E9tails de la demande \ + ou faire des modifications, choisir Rejeter \ + pour rejeter la demande +eorder.sort = Trier par +eorder.status = Statut +eorder.table.highlighted.label = Les lignes en surbrillance pr\u00E9cisent une \ + ressource qui est probablement en cours de \ + synchronisation avec le serveur. +eorder.timestamp = Horodatage error.2ndEntry.previous.not.matched = Cela ne correspond pas \ \u00E0 la valeur \ @@ -2624,6 +2761,13 @@ error.analyzer.test.name.duplicate = La combinaison de \ error.birthdate.format = La date de naissance du \ patient ne sont pas dans le \ format correct. +error.critical.range.value = La valeur est un \ + r\u00C3\u00A9sultat \ + critique. Veuillez suivre \ + les proc\u00C3\u00A9dures \ + normales de \ + r\u00C3\u00A9sultats \ + critiques. error.date = La date est invalide error.date.birthInPast = La date de naissance doit \ \u00EAtre post\u00E9rieure @@ -2705,9 +2849,6 @@ error.low.normal.low.valid.order = Il faut que la valeur \ \u00E9gale \u00E0 la valeur \ minimale de la plage de \ validit\u00E9 -error.out.side.range = La valeur est en dehors de la plage de rapport. \ - Action requise. Voir la procédure pour plus d'informations. \ - Voulez-vous archiver ce résultat ? error.low.normal.value = Il faut que la valeur \ minimale de la plage \ normale soit un nombre ou \ @@ -2716,9 +2857,10 @@ error.low.valid.value = Il faut que la valeur \ minimale de la plage de \ validit\u00E9 soit un \ nombre ou 'l'infini' -error.critical.range.value = La valeur est un résultat critique. \ - Veuillez suivre les procédures normales de résultats critiques. - +error.method.invalid = Doit correspondre \ + \u00C3\u00A0 une \ + m\u00C3\u00A9thode \ + existante error.missing.test.mapping = Test inconnue envoy\u00E9 \ par l'analyseur.
S'il \ vous pla\u00EEt notez le \ @@ -2731,6 +2873,13 @@ error.organizationType.required = Au moins un type \ d'organisation doit \ \u00EAtre \ s\u00E9lectionn\u00E9 +error.out.side.range = La valeur est en dehors de \ + la plage de rapport. Action \ + requise. Voir la proc\u00C3\ + \u00A9dure pour plus \ + d'informations. Voulez-vous \ + archiver ce \ + r\u00C3\u00A9sultat ? error.referral.missingInstitution = {0} : Renvoy\u00E9 \u00E0 \ l'institut n'est pas \ sp\u00E9cifi\u00E9 @@ -2814,7 +2963,6 @@ errors.final.result.required = R\u00E9sultat VIH final \ Test Kits ont des \ r\u00E9sultats. errors.followingAccession = Erreurs du no d'ordre {0} : -errors.resultValidated = Result has been validated by another user : {0} errors.loginName.duplicated = Nom de connexion, {0}, est \ d\u00E9j\u00E0 en usage. \ S'il vous pla\u00EEt \ @@ -2848,6 +2996,8 @@ errors.required.atLeastOneItem.forTwoSelectBoxes = S\u00E9lectionnez au moins \ errors.result.required = Entr\u00E9e du \ r\u00E9sultat \ n\u00E9cessaire. +errors.resultValidated = Result has been validated \ + by another user : {0} errors.sample.test.missmatch = Tests \ s\u00E9lectionn\u00E9s ne \ sont pas appropri\u00E9es \ @@ -2915,6 +3065,12 @@ externalconnections.sms = SMS externalconnections.url.instruction = Sp\\u00E9cifiez le point de \ terminaison de connexion +field.contacttracing.indexname.label = Suivi de \ + contacts\u00EF\u00BF\u00BD: Nom \ + du cas index +field.contacttracing.indexrecordnumber.label = Suivi de contacts: Num\u00E9ro \ + de dossier du cas index + footer.button.finish = Terminer gender.add.subtitle = Ajouter Sexe @@ -3351,7 +3507,6 @@ label.biologist.haiti = Superviseur label.browse.title = Label label.button.accept = Accepter label.button.add = Ajouter -label.button.new.user = Nouvel utilisateur label.button.add.note = Ajouter Note label.button.addTestAnalyteTestResult = Ajouter \ \u00C9l\u00E9ments/R\ @@ -3365,7 +3520,6 @@ label.button.changePassword = Changer Mot de Passe label.button.checkAll = S\u00E9lectionez tout label.button.continue = Continuer label.button.deactivate = D\u00E9sactiver -label.button.modify = Modifier label.button.edit = \u00C9diter label.button.editMultiples = \u00C9diter plusieurs \ Tests @@ -3375,6 +3529,8 @@ label.button.editTests = Ajouter Tests label.button.exit = Quitter label.button.finished = Termin\u00E9 label.button.hide = Cacher +label.button.modify = Modifier +label.button.new.user = Nouvel utilisateur label.button.next = Suivant label.button.no = Non label.button.picklist.add = Ajouter la \ @@ -3459,12 +3615,15 @@ label.new = Nouveau label.none = Aucun label.not.available = pas sp\u00E9cifi\u00E9 label.notValidated = Non-valid\u00E9 +label.note = Note label.orderable = Disponible \u00E0 la \ commande label.over25 = 25+ label.panel = Panel label.patient = Patient label.patient.search = Lancer la recherche +label.patient.search.external = Lancer la recherche \ + externe label.patient.search.select = Trouver l'ordre pour \ ce patient label.patient.search.select.test = Trouver l'ordre pour \ @@ -3472,6 +3631,12 @@ label.patient.search.select.test = Trouver l'ordre pour \ label.patient_name = Nom, Prenom(s) label.prior.note = Note \ Pr\u00E9c\u00E9dente +label.priority.asap = ASAP +label.priority.futureStat = Avenir STAT +label.priority.routine = Routine +label.priority.stat = STAT +label.priority.timed = Chronom\u00C3\u00A9tr\ + \u00C3\u00A9 label.program = Programme label.provider = label.qualifiers = Qualificatifs @@ -3618,11 +3783,28 @@ label.unitofmeasure = Unit\u00E9 de Mesure label.uom = uom label.week = Semaine label.year = Ans -label.priority.routine = Routine -label.priority.asap = ASAP -label.priority.stat = STAT -label.priority.timed = Chronométré -label.priority.futureStat = Avenir STAT + +labno.alt.prefix.error.length = Veuillez saisir un pr\u00E9fixe unique \u00E0 \ + 4 caract\u00E8res pour les codes-barres \ + pr\u00E9-imprim\u00E9s +labno.alt.prefix.error.unique = Veuillez choisir un pr\u00E9fixe UNIQUE qui ne \ + correspond pas au pr\u00E9fixe des \ + num\u00E9ros d'ordonnance \ + g\u00E9n\u00E9r\u00E9s par le syst\u00E8me +labno.alt.prefix.instruction = Pr\u00E9fixe pour les \u00E9tiquettes de \ + codes-barres pr\u00E9-imprim\u00E9es (4 caract\ + \u00E8res) +labno.alt.prefix.note = REMARQUE: si ce pr\u00E9fixe a d\u00E9j\u00E0 \ + \u00E9t\u00E9 utilis\u00E9, la \ + num\u00E9rotation continuera \u00E0 partir du \ + dernier num\u00E9ro g\u00E9n\u00E9r\u00E9 avec \ + lui +labno.alt.prefix.use = Utilisez le m\u00EAme format de num\u00E9ro \ + d'ordonnance et le m\u00EAme pool de \ + num\u00E9ros disponibles qu'on utilise pour la \ + g\u00E9n\u00E9ration des num\u00E9ros lors de \ + la saisie des ordonnances g\u00E9n\u00E9rales +labno.alt.startAt = Commencer \u00E0 list.of = de list.showing = Montrer @@ -3756,6 +3938,15 @@ marital.n_a = 7 = N/A pour les enfants marital.single = 1 = C\u00E9libataire marital.widow = 5 = Veuf(ve) +menu.accession.validation = Recherche par Ordonnance +menu.accession.validation.range = Recherche gamme par Ordonnance +menu.label.filter = Filtres +menu.label.filter.active = Uniquement actif +menu.label.filter.admin = Seul Administrateur +menu.label.filter.role = Par r\u00C3\u00B4les d'unit\u00C3\u00A9 de \ + laboratoire +menu.validation.date = Rechercher par date de test + message.error.unauthorized = Vous n'avez pas de session \ authentifi\u00E9e avec le \ serveur.\nVeuillez vous connecter et \ @@ -3777,6 +3968,8 @@ method.browse.title = M\u00E9thode method.description = Description de la M\u00E9thode method.edit.subtitle = \u00C9diter M\u00E9thode method.edit.title = \u00C9diter M\u00E9thode +method.entry.project.MaxMsg = ...correspond \u00C3\u00A0 plus de 50 \ + m\u00C3\u00A9thodes method.id = Type de M\u00E9thode method.isActive = M\u00E9thode Activ\u00C9e method.methodName = Nom de la M\u00E9thode @@ -3795,6 +3988,8 @@ month.november.abbrev = Nov month.october.abbrev = Oct month.september.abbrev = Sept +months.label = mois + nationality.BF = 3 = Burkina Faso nationality.BJ = 2 = B\u00E9mom nationality.CI = 1 = C\u00F4te d'Ivoire @@ -4068,12 +4263,11 @@ openreports.activity.title = Rapport d'activit\u00E9 openreports.aggregate.title = Rapports globaux openreports.all.tests.aggregate = R\u00E9sum\u00E9 de tous les tests openreports.hiv.aggregate = R\u00E9sum\u00E9 des tests VIH -openreports.stat.aggregate = Rapport de statistiques -openreports.mgt.rejection = Rapport de rejet openreports.hiv.aggregate.CI_IPCI = Rapport du programme PVVIH openreports.hiv.aggregate.CI_LNSP = Rapport du programme PVVIH openreports.hiv.aggregate.CI_REG = Rapport du programme PVVIH openreports.management.title = Rapports de gestion +openreports.mgt.rejection = Rapport de rejet openreports.nonConformityReport = Rapport des non-conformit\u00E9s par \ date openreports.patient.ARVFollowup = ARV - Bilan de Suivi @@ -4088,6 +4282,7 @@ openreports.patientreports.title = R\u00E9sultats du patient openreports.referredOutHaitiReport = Rapport d'Analyse Envoy\u00E9 au \ Laboratoire de R\u00E9f\u00E9rence openreports.rejection.title = Rapports de rejet +openreports.stat.aggregate = Rapport de statistiques option.notListed = Non r\u00E9pertori\u00E9 @@ -4489,6 +4684,8 @@ patient.search.not.found = Aucun patient n'a \ patient.site.subject.number = Site Sujet No. patient.subject.number = Sujet No. patient.subject.number.CI_IPCI = Numero de Dossier +patient.subject.tbnumber = Code TB (XX-XXXXX) +patient.upid.code = Code UPID patientEntryConfiguration.browse.title = Configuration d'entr\u00E9e des \ Patients @@ -4573,6 +4770,7 @@ project.ARVStudy.name = ARV - Bilan Initial project.EIDStudy.name = EID project.IndeterminateStudy.name = Ind\u00E9termin\u00E9 project.RTNStudy.name = RTN +project.Recency.name = Recency Testing project.SequencingStudy.name = S\u00E9quen\u00E7age project.SpecialRequestStudy.name = Demande Sp\u00E9ciale project.VLStudy.name = ARV - Charge Virale @@ -4693,6 +4891,7 @@ quick.entry.accession.number.CI = N\u02DA Lab quick.entry.accession.number.CI_IPCI = N\u02DA Lab quick.entry.accession.number.CI_LNSP = N\u02DA Lab quick.entry.accession.number.CI_REG = N\u02DA Lab +quick.entry.accession.range = Load Next 99 Records Starting at Lab No. quick.entry.received.date = Date de R\u00E9ception quick.entry.received.date.CI_LSNP = Date de r\u00E9ception quick.entry.sample.type = Type d'\u00E9chantillon @@ -4729,6 +4928,7 @@ referral.header.group.request = Demande pour une r\u00E9f\u00E9rence d'un \ referral.header.group.results = R\u00E9sultat de la r\u00E9f\u00E9rence referral.institute = Centre de R\u00E9f\u00E9rence referral.noReferralItems = Aucun \u00E9l\u00E9ment d'orientation +referral.original.result = R\u00E9sultat Original referral.out.manage = Referr\u00E9 \u00E0 referral.reason = Raison de la r\u00E9f\u00E9rence referral.reason.EQA.testing = EQA repetition @@ -4781,13 +4981,16 @@ report.activity.report.base = Rapport \ d'activit\u00E9 report.age = Age report.alert = Alerte +report.all = Tout report.analysisReport = R\u00E9sultats \ d'Analyses report.appointment = Rendez vous report.appointmentDate = Date de rendez vous +report.april = Avril report.assHeadOfBioclinicque = Assistants - Chef \ bioclinicque report.associateProfessor = Pr Agr\u00E9g\u00E9 +report.august = Ao\u00C3\u00BBt report.belowNormal = Inf\u00E9rieure \ \u00E0 la Normale report.biologist = Biologiste @@ -4844,6 +5047,7 @@ report.dateReviewedReceived = Revu/Valid\ __________ \ par___________________\ _________________ +report.december = D\u00C3\u00A9cembre report.districtFacility = District sanitaire report.email = Email report.enter.labNumber = Nombre Lab Entrez @@ -4872,6 +5076,22 @@ report.enter.labNumber.headline.Haiti = Par Num\u00E9ro \ report.enter.labNumber.headline.LNSP_Haiti = Par Num\u00E9ro \ d'Ordre/ Num\u00E9ro \ de Laboratoire +report.enter.patient.headline = G\u00E9n\u00E9rer \ + tous les rapports \ + pour un Patient +report.enter.patient.headline.description = Rechercher un Patient \ + avec son num\u00E9ro \ + laboratoire pr\u00E9c\ + \u00E9dent, \ + Identifiant \ + Patient(qui peut \ + \u00EAtre son code \ + unique ou num\u00E9ro \ + identification \ + nationale) ou autre \ + champs. +report.enter.site.headline = G\u00E9n\u00E9rer \ + rapport par site report.enter.subjectNumber = Par Num\u00E9ro de \ Sujet report.enter.subjectNumber.Haiti = Par Num\u00E9ro du \ @@ -4912,6 +5132,7 @@ report.extLabReference = R\u00E9f\u00E9r\u00E9 \ \u00E0 un laboratoire \ externe report.fax = Fax +report.february = F\u00C3\u00A9vrier report.followup.general.comment = Observation \ g\u00E9n\u00E9rale report.followup.no.authorizer = Aucun utilisateur \ @@ -4923,6 +5144,7 @@ report.followup.no.sampleType = Aucun type \ \u00E9cifi\u00E9es report.followup.no.section = Aucune section \ sp\u00E9cifi\u00E9e +report.followup.period = Mois report.footNote = *En cours comprend \ des r\u00E9sultats \ qui sont: \ @@ -4955,6 +5177,9 @@ report.instruction.inventory.test.count = S\u00E9lection du \ \u00E9, tous les \ sites seront dans le \ rapport +report.january = Janvier +report.july = Juillet +report.june = Juin report.labInfomation = Remarques \ g\u00E9n\u00E9rales \ du laboratoire @@ -4968,17 +5193,26 @@ report.labName.two.LNSP_Haiti = LABORATOIRE NATIONAL \ report.labTotal = Totaux Laboratoires report.label.collectionDateTime = Date & heure de \ pr\u00E9l\u00E8vement: +report.label.datetype.orderdate = Date de saisie +report.label.datetype.printdate = Date d'impression +report.label.datetype.resultdate = Date de validation report.label.days = Jours report.label.labno = Num. Labo: report.label.orderDateTime = Date & heure de \ demande report.label.orderNo = No d'ordre: report.label.page = Page +report.label.site.dateType = Type de date: +report.label.site.onlyResults = Seulement rapports \ + avec des \ + r\u00E9sultats report.label.siteID = Page report.label.workplan = Plan de Travail report.laboratory.unit = Unit\u00E9 de \ Laboratoire report.legend = L\u00E9gende +report.march = Mars +report.may = Peut report.men = Hemmes report.negative = N\u00E9gatif report.no.panel.tests = @@ -4995,8 +5229,14 @@ report.noReportMessage = Il n\u2019est pas \ cr\u00E9er ce rapport \ \u00E0 ce temps report.normal = normal +report.normalWorkingHours = Heures normales de \ + travail (temps de \ + r\u00C3\u00A9ception \ + 9h-15h30) report.notStarted = Non Commenc\u00E9 report.note = Note +report.november = Novembre +report.october = Octobre report.orderDate = Date de \ l\u2019ordonnance #Referred Test reports @@ -5004,9 +5244,29 @@ report.orderNo = No d'Ordre report.ordinanceNo = No d\u2019Ordonnance report.other = Envoy\u00E9 report.outcome = R\u00E9sultat +report.outofnormalWorkingHours = Heures de travail \ + hors normales \ + (15h31-8h59) report.page = Page report.pageNumberOf = sur report.patient.not.registered = Pas enregistr\u00E9 +report.patient.site.description = G\u00E9n\u00E9rer des \ + rapports par date de \ + validation ou date de \ + saisie. Date de \ + validation affichera \ + uniquement des \ + rapports avec des \ + r\u00E9sultats. Si \ + vous \ + s\u00E9lectionnez \ + uniquement des \ + rapports avec des \ + r\u00E9sultats, les \ + rapports o\u00F9 tous \ + les tests sont en \ + cours ne seront pas \ + pris en compte. #Patient ReportCDI report.patientCode = Code du Patient report.patientNameCode = Noms/Codes du patient @@ -5049,6 +5309,8 @@ report.results.received.date = Date de \ r\u00E9sultat report.sampleType = Type \ d'\u00E9chantillon +report.samples = \u00C3\ + \u0089chantillons report.section = Section report.section.not.specified = Non sp\u00E9cifi\u00E9 report.select.date.period = S\u00E9lectionnez \ @@ -5066,6 +5328,24 @@ report.select.labNumber.Haiti = No d'Ordre \ S\u00E9lectionnez report.select.labNumber.LNSP_Haiti = No d'Ordre \ S\u00E9lectionnez +report.select.labUnit = S\u00C3\ + \u00A9lectionnez la \ + ou les \ + unit\u00C3\u00A9s de \ + laboratoire pour \ + lesquelles vous \ + souhaitez \ + cr\u00C3\u00A9er le \ + test, vous pouvez en \ + s\u00C3\ + \u00A9lectionner \ + autant que vous le \ + souhaitez +report.select.priority = S\u00C3\ + \u00A9lectionnez la \ + priorit\u00C3\u00A9 \ + des tests que vous \ + souhaitez afficher report.select.project = S\u00E9lectionnez le \ type d'\u00E9tude report.select.service.location = Centre de \ @@ -5079,6 +5359,38 @@ report.select.subjectNumber.Haiti = S\u00E9lectionnez Num\ \u00E9ro du Patient report.select.subjectNumber.LNSP_Haiti = S\u00E9lectionnez Num\ \u00E9ro du Patient +report.select.timeFrame = S\u00C3\ + \u00A9lectionnez les \ + p\u00C3\u00A9riodes \ + pour lesquelles vous \ + souhaitez \ + g\u00C3\u00A9n\u00C3\ + \u00A9rer les rapports +report.select.timeFrame.note = REMARQUE: toutes les \ + dates et heures sont \ + bas\u00C3\u00A9es sur \ + l\u00E2\u0080\ + \u0099heure de \ + r\u00C3\u00A9ception. \ + EG: un test \ + re\u00C3\u00A7u le 31 \ + janvier \u00C3\u00A0 \ + 23h59 et obtenu le \ + 1er \ + f\u00C3\u00A9vrier \ + \u00C3\u00A0 9h30 \ + montrerait que les \ + heures normales en \ + janvier +report.select.year = S\u00C3\ + \u00A9lectionnez \ + l\u00E2\u0080\ + \u0099ann\u00C3\ + \u00A9e pour laquelle \ + vous souhaitez \ + g\u00C3\u00A9n\u00C3\ + \u00A9rer le rapport. +report.september = Septembre report.service = Service report.serviceHead = Chef de service report.sex = Sexe @@ -5104,6 +5416,20 @@ report.supervisorSign = Signature du \ ______________________\ ______________Date____\ ____________________ +report.tb.analysisMethod = M\u00E9thode d'analyse +report.tb.completedDate = Date de \ + r\u00E9alisation +report.tb.diagnostic.reason = Motif du diagnostic +report.tb.followup.period = Mois +report.tb.followup.reason = Motif du suivi +report.tb.orderReason = Motif de l'examen TB +report.tb.referingsite = Unit\u00E9 qui a \ + adress\u00E9 le malade +report.tb.sample.aspect = Aspect de \ + l'\u00E9chantillon +report.tb.sampleType = Nature de \ + l'\u00E9chantillon +report.tb.testName = Nom de l'examen report.techId = ID Techn. report.telephoneAbv = T\u00E9l report.test = Test @@ -5112,6 +5438,7 @@ report.test.status.inProgress = En cours report.test.status.referredOut = Renvoy\u00E9 \u00E0 report.testName = Nom du Test report.testSection = Section d'essai +report.tests = Essais report.to = \u00E0 report.to.CI_IPCI = \u00E0 N\u02DA Lab report.to.CI_LNSP = \u00E0 N\u02DA Lab @@ -5168,6 +5495,8 @@ reports.label.patient.VL = Charge Virale reports.label.patient.indeterminate = Ind\u00E9termin\u00E9s reports.label.project.export = Exporter en Fichier \ CSV par +reports.label.project.export.dateType = Exporter en Fichier \ + CSV par Type de Date reports.label.referral.title = Renvois reports.label.referred.out = Tests r\u00E9f\u00E9r\ \u00E9s @@ -5224,28 +5553,7 @@ reports.patient.Indeterminate.version1 = Ind\u00E9termin\ \u00E9s Version 1 reports.patient.Indeterminate.version2 = Ind\u00E9termin\ \u00E9s Version 2 -report.tests = Essais -report.samples = Échantillons -report.january = Janvier -report.february = Février -report.march = Mars -report.april = Avril -report.may = Peut -report.june = Juin -report.july = Juillet -report.august = Août -report.september = Septembre -report.october = Octobre -report.november = Novembre -report.december = Décembre -report.normalWorkingHours = Heures normales de travail (temps de réception 9h-15h30) -report.outofnormalWorkingHours = Heures de travail hors normales (15h31-8h59) -report.all = Tout -report.select.labUnit = Sélectionnez la ou les unités de laboratoire pour lesquelles vous souhaitez créer le test, vous pouvez en sélectionner autant que vous le souhaitez -report.select.priority = Sélectionnez la priorité des tests que vous souhaitez afficher -report.select.timeFrame = Sélectionnez les périodes pour lesquelles vous souhaitez générer les rapports -report.select.timeFrame.note = REMARQUE: toutes les dates et heures sont basées sur l’heure de réception. EG: un test reçu le 31 janvier à 23h59 et obtenu le 1er février à 9h30 montrerait que les heures normales en janvier -report.select.year = Sélectionnez l’année pour laquelle vous souhaitez générer le rapport. + result.add.subtitle = Ajouter R\u00E9sultat result.add.title = Ajouter R\u00E9sultat result.analysis = Analyse @@ -5591,6 +5899,7 @@ resultsentry.tests.resultisreportable.title = Reportable resultsentry.tests.testisreportable.title = Reportable resultsentry.tests.title = Test +role.analyser = Analyze Import role.audittrail = Examen d'audit role.edit.identifiers = Modifier les identifiants role.intake = Accueil @@ -5600,12 +5909,11 @@ role.name = Nom role.parent.role = Regroupement parent role.reports = Rapports role.result.modifier = Modificateur R\u00E9sultat -role.results = Résultats +role.results = R\u00C3\u00A9sultats role.results.all = R\u00E9sultats role.test.configuration = Gestion des Tests role.users = Administrateur de compte d'utilisateur role.validator = Validation -role.analyser = Analyze Import rror.field.time.invalid = le format de l'heure est invalide pour: {0} @@ -5808,7 +6116,6 @@ sample.entry.invalid.accession.number.used = No d'ordre est \ d\u00E9j\u00E0 en \ usage sample.entry.nextVisit.date = Date de rendez vous -entry.invalid.loinc.number.used = Ce LOINC est déjà utilisé. Les codes LOINC doivent être uniques sample.entry.noTests = Pas de tests \ appropri\u00E9s \ pour ce type \ @@ -5829,12 +6136,14 @@ sample.entry.patient = Patient sample.entry.patientPayment = L'\u00E9tat des \ paiements des \ patients +sample.entry.priority = Priorit\u00C3\u00A9 sample.entry.project = Activit\u00E9 sample.entry.project.ARV.cd4cd8Test = CD4/CD8 sample.entry.project.ARV.centerCode = Code du Centre sample.entry.project.ARV.centerName = Nom du Centre sample.entry.project.ARV.creatinineTest = Cr\u00E9atinin\ \u00E9mie +sample.entry.project.ARV.dbsvlTaken = DBS sample.entry.project.ARV.deptTitle = Biochimie - \ Hematologie - \ Immunologie @@ -5843,6 +6152,7 @@ sample.entry.project.ARV.edtaTubeTaken = Tube EDTA sample.entry.project.ARV.genotypingTest = G\u00E9notypage sample.entry.project.ARV.glycemiaTest = Glyc\u00E9mie sample.entry.project.ARV.nfsTest = NFS +sample.entry.project.ARV.pscvlTaken = PSC sample.entry.project.ARV.title = ARV sample.entry.project.ARV.transaminaseTest = Transaminases sample.entry.project.ARV.viralLoadTest = Charge virale \ @@ -5863,13 +6173,15 @@ sample.entry.project.EID.siteName = Nom du Site sample.entry.project.EID.title = EID sample.entry.project.EID.whichPCR = Quelle PCR (1 ou \ 2) ? -sample.entry.project.LART = HARC -sample.entry.project.LDBS = HDBS +sample.entry.project.LART = LARS +sample.entry.project.LDBS = LDBS sample.entry.project.LIND = LIND sample.entry.project.LRTN = LRTN sample.entry.project.LSEQ = LSEQ sample.entry.project.LSPE = LSPE -sample.entry.project.LVL = HARC +sample.entry.project.LVL = LARS +sample.entry.project.RT = RTRI +sample.entry.project.RT.title = Recency Testing sample.entry.project.RTN.serologyHIV = S\u00E9rologie VIH sample.entry.project.RTN.title = RTN sample.entry.project.VL.simple.title = Charge Virale @@ -5966,6 +6278,13 @@ sample.entry.project.receivedDate = Date de \ R\u00E9ception sample.entry.project.receivedTime = Heure de \ R\u00E9ception +sample.entry.project.recency.asanteKit = Test Rapide \ + Asant\u00E9 pour \ + Infection \ + R\u00E9cente HIV-1 +sample.entry.project.recency.plasma = Plasma +sample.entry.project.recency.serum = S\u00E9rum +sample.entry.project.recencyNumber = Recency ID No sample.entry.project.result = R\u00E9sultat sample.entry.project.secondTest = 2\u00E9me \ Pr\u00E9l\ @@ -5978,6 +6297,10 @@ sample.entry.project.sequencing.title = S\u00E9quen\ \u00E7age sample.entry.project.serologyHIVTest = S\u00E9rologie VIH sample.entry.project.siteCode = Code du Site +sample.entry.project.siteDepartmentName = quartier/d\ + \u00E9\ + partement/unit\ + \u00E9 sample.entry.project.siteMaxMsg = ...correspond \ \u00E0 plus de 50 \ sites @@ -6007,13 +6330,24 @@ sample.entry.project.title.infantInformation = Informations sur \ l'Enfant sample.entry.project.title.mothersInformation = Informations de la \ M\u00E8re +sample.entry.project.title.org = Donn\u00E9es site sample.entry.project.title.otherTests = Autres Tests +sample.entry.project.title.patientInfo = Informations sur \ + le Patient +sample.entry.project.title.psc = PSC +sample.entry.project.title.sample = Identification du \ + pr\u00E9l\ + \u00E8vement +sample.entry.project.title.sampleType = Type de \ + pr\u00E9l\ + \u00E8vement sample.entry.project.title.specimen = Les \ \u00C9chantillons \ Pr\u00E9lev\u00E9s sample.entry.project.title.tests = Tests sample.entry.project.transaminaseALTLTest = Transaminases ALTL sample.entry.project.transaminaseASTLTest = Transaminases ASTL +sample.entry.project.upidCode = Code UPID sample.entry.project.vgmTest = VGM sample.entry.project.vironostikaTest = Vironostika sample.entry.project.vl.arv = CV contr\u00F4le \ @@ -6043,11 +6377,36 @@ sample.entry.provider.name.CI_LNSP = Nom de Famille du \ prescripteur sample.entry.provider.name.CI_REG = Nom de Famille du \ prescripteur +sample.entry.referral.toggle = Refer test to a \ + reference lab sample.entry.referringSite.code = Code du site \ r\u00E9f\u00E9rant sample.entry.referringSite.code.CI_LNSP = Code du site -sample.entry.remove.sample = Supprimer l'échantillon -sample.entry.sample.new = Ajouter un nouvel échantillon +sample.entry.reject.warning = Vous rejetez un \ + \u00C3\ + \u00A9\ + chantillon.Cet \ + \u00C3\ + \u00A9chantillon \ + sera \ + rejet\u00C3\u00A9 \ + et \ + n\u00E2\u0080\ + \u0099appara\u00C3\ + \u00AEtra pas dans \ + les plans de \ + travail une fois \ + enregistr\u00C3\ + \u00A9,aucun \ + r\u00C3\ + \u00A9sultat ne \ + peut \ + \u00C3\u00AAtre \ + entr\u00C3\u00A9 \ + pour cette \ + commande. +sample.entry.remove.sample = Supprimer l'\u00C3\ + \u00A9chantillon sample.entry.removeAllSamples = Supprimer Tout sample.entry.requestDate = Date de la demande sample.entry.requested.tests = Analyses \ @@ -6057,6 +6416,9 @@ sample.entry.requester.new = Nouveau Demandeur sample.entry.runSearch = Lancer la Recherche sample.entry.sample.condition = \u00C9tat de \ l'\u00E9chantillon +sample.entry.sample.new = Ajouter un nouvel \ + \u00C3\ + \u00A9chantillon sample.entry.sample.period = Pr\u00E9l\ \u00E8vement \ effectu\u00E9 pour \ @@ -6098,10 +6460,6 @@ sample.entry.test.requester.id = Exemple demandeur \ Id sample.entry.title = Ajouter Ordonnance sample.entry.title.CI = Ajouter Ordonnance -sample.entry.priority = Priorité -sample.entry.reject.warning = Vous rejetez un échantillon.\ - Cet échantillon sera rejeté et n’apparaîtra pas dans les plans de travail une fois enregistré,\ - aucun résultat ne peut être entré pour cette commande. sample.export.collectionDate = par Date de \ Pr\u00E9l\ \u00E8vement @@ -6150,10 +6508,15 @@ sample.releasedDate = Date de Soumission sample.revision = R\u00E9vision sample.sampleIdRelatesTo = \u00C9chantillon \ Parent +sample.search.date.instructions = Entrez la date du \ + test sample.search.scanner.instructions = Scan ou \ Entr\u00E9e \ Manuelle -sample.search.date.instructions = Entrez la date du test +sample.search.scanner.instructions.highaccession = Pout un seul \ + rapport, laissez \ + le champ de droite \ + vide sample.status = Statut de \ l'\u00C9chantillon sample.stickerReceivedFlag = Auto-collant \ @@ -6161,10 +6524,23 @@ sample.stickerReceivedFlag = Auto-collant \ sample.sysUserId = Utilisateur \ receveur de \ l'\u00C9chantillon +sample.tb.aspects = Aspect de \ + l'\u00E9chantillon +sample.tb.diagnostic.methods = M\u00E9thode \ + d'analyse +sample.tb.diagnostic.reasons = Motif du diagnostic +sample.tb.followup.reasons = Motif du suivi +sample.tb.order.reasons = Motif de l'examen \ + TB +sample.tb.reference.unit = Unit\u00E9 qui \ + adresse le malade +sample.tb.specimen.nature = Nature de \ + l'\u00E9chantillon sample.transmissionDate = Date de \ Transmission sample.type.Coloration.de.Gram = Coloration de Gram sample.type.DBS = DBS +sample.type.PSC = PSC sample.type.Sputum = Crachats sample.type.ambionic.fluid = Liquide Amniotique sample.type.ascite.fluid = Liquide Ascite @@ -6355,6 +6731,35 @@ siteInfo.elements.optional = El\u00E9ments Facultatifs siteInfo.external.orders = Si "Vrai" (True), cela permet les \ sites externes d'envoyer des \ ordonnances \u00E9lectroniques +siteInfo.geographical.district = La G\u00C3\u00A9ographique \ + unit\u00C3\u00A9s pour a \ + particuli\u00C3\u00A8re les \ + quartiers +siteInfo.geographical.region = La G\u00C3\u00A9ographique \ + unit\u00C3\u00A9s pour a \ + particuli\u00C3\u00A8re \ + R\u00C3\u00A9gion +siteInfo.instruction.contactTracing.d = Should the contact tracing fields \ + be activate +siteInfo.instruction.contactTracing.i = Should the contact tracing fields \ + be activated +siteInfo.instruction.directorname.d = Nom du directeur de laboratoire \ + pour la ligne de signature +siteInfo.instruction.directorsignature.d = La signature du directeur de \ + laboratoire qui doit \ + \u00C3\u00AAtre appos\u00C3\u00A9e \ + sur les rapports \ + g\u00C3\u00A9n\u00C3\u00A9r\u00C3\ + \u00A9s +siteInfo.instruction.directortitle.d = Le titre du directeur du laboratoire +siteInfo.instruction.georaphical.one = La G\u00C3\u00A9ographique \ + unit\u00C3\u00A9s 1 pour a \ + particuli\u00C3\u00A8re \ + R\u00C3\u00A9gion +siteInfo.instruction.georaphical.two = La G\u00C3\u00A9ographique \ + unit\u00C3\u00A9s 1 pour a \ + particuli\u00C3\u00A8re les \ + quartiers siteInfo.instruction.labLogo.left = Utilisez file upload de mettre le \ logo de laboratoire pour le \ c\u00F4t\u00E9 gauche de \ @@ -6367,6 +6772,18 @@ siteInfo.instruction.labLogo.right = Utilisez file upload de mettre le \ l'en-t\u00EAte de rapport. Le \ fichier doit \u00EAtre un jpg, png \ ou gif. +siteInfo.instruction.label.one = La adresse lignes 1 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit +siteInfo.instruction.label.three = La adresse lignes 3 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit +siteInfo.instruction.label.two = La adresse lignes 2 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit siteInfo.instruction.patient.nationality = S\u00E9lectionner "vrai" pour \ permettre la nationalit\u00E9 du \ patient d'appara\u00EEtre dans la \ @@ -6376,13 +6793,27 @@ siteInfo.instruction.patient.nationality = S\u00E9lectionner "vrai" pour \ entr\u00E9 dans la base de \ donn\u00E9es. siteInfo.lab.director = Nom du responsable de laboratoire \ - pour l\u00EA’en-tête du rapport + pour \ + l\u00EA\u00E2\u0080\u0099en-t\u00C3\ + \u00AAte du rapport siteInfo.lab.logo.left = Cela permet l'ajout du logo qui \ appara\u00EEtra en haut du rapport \ \u00E0 gauche siteInfo.lab.logo.right = Cela permet l'ajout du logo qui \ appara\u00EEtra en haut du rapport \ \u00E0 droite +siteInfo.label.one = La adresse lignes 1 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit +siteInfo.label.three = La adresse lignes 3 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit +siteInfo.label.two = La adresse lignes 2 pouvez \ + \u00C3\u00AAtre utilis\u00C3\u00A9e \ + \u00C3\u00A0 sp\u00C3\u00A9cifier \ + quoi que ce soit siteInfo.malariaCaseReport = Vrai pour envoyer le rapport, faux \ pour autre siteInfo.malariaCaseURL = L'URL pour les rapports de cas de \ @@ -6433,6 +6864,11 @@ siteInfo.reflex_rules = Quel ensemble de r\u00E8gles \ siteInfo.reportConfig.reportDirectory = R\u00E9pertoire de rapport siteInfo.reportPageNumbers = Si "Vrai" (True), les pages du \ rapport seront num\u00E9rot\u00E9es +siteInfo.restrictFreeTextMethodEntry = Si vrai, l'utilisateur doit choisir \ + une m\u00C3\u00A9thode existante et \ + ne pourra pas cr\u00C3\u00A9er une \ + nouvelle m\u00C3\u00A9thode via la \ + saisie des r\u00C3\u00A9sultats. siteInfo.restrictFreeTextRefSiteEntry = Si "Vrai" (True), l'utilisateur \ doit choisir un site de \ r\u00E9f\u00E9rence existant et ne \ @@ -6453,6 +6889,9 @@ siteInfo.roleForPatientOnResults = Si "Vrai" (True), la \ visibilit\u00E9 des informations du \ patient sera restreint \u00E0 ceux \ qui ont le r\u00F4le autoris\u00E9 +siteInfo.section.altAccession = Num\u00E9ro d'ordonnance pour les \ + codes \u00E0 barres pr\u00E9-imprim\ + \u00E9s siteInfo.section.elements = El\u00E9ments d'\u00E9tiquettes de \ Code Barres siteInfo.section.number = Nombre d'Etiquettes de Code Barres @@ -6526,8 +6965,8 @@ siteInformation.instruction.headerInfo = Ce texte appara\u00EEtra dans \ l'en-t\u00EAte des rapports qui \ soutiennent une information \ suppl\u00E9mentaire. De se scinder \ - en deux lignes utilisent Balise HTML br \ - entre les lignes. + en deux lignes utilisent Balise \ + HTML br entre les lignes. siteInformation.instruction.sortQaEvents = Allumer va trier les qa \ \u00E9v\u00E9nements par ordre \ alphab\u00E9tique dans les listes. \ @@ -6587,6 +7026,33 @@ statusofsample.id = Num\u00E9ro du Statut de l'\u00C9chantillon statusofsample.name = Nom statusofsample.statustype = Type de Statut +study.eorder.action.edit = Editer +study.eorder.action.enter = Entrer +study.eorder.action.reject = Rejeter +study.eorder.action.title = Actions +study.eorder.all_status = Tous les status +study.eorder.browse.title = Liste des demandes \u00E9lectroniques +study.eorder.choose_site.label = S\u00E9lectionner un site +study.eorder.lab_number = Lab No. +study.eorder.patient.birth_date = Date de Naissance +study.eorder.patient.code = Code Patient +study.eorder.patient.gender = Sexe +study.eorder.patient.upid = Code UPID +study.eorder.request.date = Date de la demande +study.eorder.request.id = ID Demande +study.eorder.request.priority = Priorit\u00E9 +study.eorder.request.status = Statut +study.eorder.request.test_name = Test +study.eorder.requester.facility = Site +study.eorder.search.date.end = Date Fin +study.eorder.search.date.start = Date d\u00E9but +study.eorder.search.date_range.title = Rechercher des demandes \ + \u00E9lectroniques par intervalle de \ + date de demande +study.eorder.search.title = Rechercher des demandes \ + \u00E9lectroniques par Code Patient ou \ + Site de prise en charge + systemmodule.add.title = Ajouter Module au Syst\u00E8me systemmodule.browse.title = Module du Syst\u00E8me systemmodule.description = Description @@ -6599,24 +7065,27 @@ systemmodule.has.update = Mettre \u00E0 Jour systemmodule.id = Num\u00E9ro du Module du Syst\u00E8me systemmodule.name = Nom du Module -systemuser.add.subtitle = Ajouter Utilisateur du Syst\u00E8me -systemuser.add.title = Ajouter Utilisateur du Syst\u00E8me -systemuser.browse.title = Utilisateur du Syst\u00E8me -systemuser.edit.subtitle = \u00C9diter Utilisateur du Syst\u00E8me -systemuser.edit.title = \u00C9diter Utilisateur du Syst\u00E8me -systemuser.externalId = Identifiant Externe de l'Utilisateur du \ - Syst\u00E8me -systemuser.firstName = Pr\u00E9nom de l'Utilisateur du \ - Syst\u00E8me -systemuser.id = Num\u00E9ro de l'Utilisateur du \ - Syst\u00E8me -systemuser.initials = Initiales de l'Utilisateur du Syst\u00E8me -systemuser.isActive = Activ\u00E9 -systemuser.isEmployee = Employ\u00E9 -systemuser.lastName = Nom de Famille de l'Utilisateur du \ - Syst\u00E8me -systemuser.loginName = Nom d'Acc\u00E8s de l'utilisateur du \ - Syst\u00E8me +systemuser.add.subtitle = Ajouter Utilisateur du Syst\u00E8me +systemuser.add.title = Ajouter Utilisateur du Syst\u00E8me +systemuser.browse.title = Utilisateur du Syst\u00E8me +systemuser.edit.subtitle = \u00C9diter Utilisateur du \ + Syst\u00E8me +systemuser.edit.title = \u00C9diter Utilisateur du \ + Syst\u00E8me +systemuser.externalId = Identifiant Externe de \ + l'Utilisateur du Syst\u00E8me +systemuser.firstName = Pr\u00E9nom de l'Utilisateur du \ + Syst\u00E8me +systemuser.id = Num\u00E9ro de l'Utilisateur du \ + Syst\u00E8me +systemuser.initials = Initiales de l'Utilisateur du Syst\ + \u00E8me +systemuser.isActive = Activ\u00E9 +systemuser.isEmployee = Employ\u00E9 +systemuser.lastName = Nom de Famille de l'Utilisateur du \ + Syst\u00E8me +systemuser.loginName = Nom d'Acc\u00E8s de l'utilisateur \ + du Syst\u00E8me systemusermodule.add.title = Ajouter Module Utilisateur du Syst\u00E8me systemusermodule.browse.title = Module Utilisateur du Syst\u00E8me @@ -6632,11 +7101,41 @@ systemusermodule.system.module.id = Identifiant Module Utilisateur du \ Syst\u00E8me systemusermodule.system.user.id = Identifiant Utilisateur du Syst\u00E8me -systemuserrole.browse.title = Rôle d'utilisateur -systemuserrole.roles = R\u00F4les -systemuserrole.roles.global = Rôles globaux -systemuserrole.roles.labunit = Rôles de l'unité de laboratoire -systemuserrole.user = Utilisatrice +systemuserrole.allLabUnits = Toutes les unit\u00C3\u00A9s de \ + laboratoire +systemuserrole.allpermissions = Toutes les autorisations +systemuserrole.apply = Appliquer +systemuserrole.browse.title = R\u00C3\u00B4le d'utilisateur +systemuserrole.copypermisions = Copier les autorisations de \ + l'utilisateur +systemuserrole.instruction =

R\u00C3\u00B4les

Il \ + existe deux types de \ + r\u00C3\u00B4les. R\u00C3\u00B4les \ + globaux qui sont \ + d\u00C3\u00A9finis pour l'ensemble \ + de l'application et \ + r\u00C3\u00B4les \ + d'unit\u00C3\u00A9 de laboratoire \ + qui peuvent \u00C3\u00AAtre \ + d\u00C3\u00A9finis pour toutes les \ + unit\u00C3\u00A9s de laboratoire \ + ou des unit\u00C3\u00A9s
de \ + laboratoire \ + sp\u00C3\u00A9cifiques.

+systemuserrole.newpermissions = Ajouter de nouvelles autorisations +systemuserrole.roles = R\u00F4les +systemuserrole.roles.global = R\u00C3\u00B4les globaux +systemuserrole.roles.labunit = R\u00C3\u00B4les de \ + l'unit\u00C3\u00A9 de laboratoire +systemuserrole.select.allLabUnits.warning = La s\u00C3\u00A9lection de toutes \ + les unit\u00C3\u00A9s de \ + laboratoire remplacera les autres \ + autorisations d'unit\u00C3\u00A9 \ + de laboratoire +systemuserrole.user = Utilisatrice +systemuserrole.warning.replace = Avertissement! Toutes les \ + autorisations actuelles seront \ + remplac\u00C3\u00A9es ! systemusersection.browse.title = Section Utilisateur du Syst\u00E8me systemusersection.has.assign = Assigner @@ -6789,6 +7288,8 @@ testUnit.existing.inactive = Unit\u00E9s des tests inactives. Attribuer des \ activer. testUnit.new = Nouvelle unit\u00E9 de test +test_section.TB = Tuberculose + testanalyte.add.subtitle = Ajouter \ \u00C9l\ \u00E9ment du \ @@ -7017,9 +7518,10 @@ testusage.config.transmit.url.note = Par exemple \ testusageconfiguration.browse.title = Configuration de test d'agr\u00E9gation \ d'utilisation +time.format.formatKey = HH:mm + timestamp.format.formatKey = dd/MM/yyyy HH:mm timestamp.format.formatKey.12 = dd/MM/yyyy KK:mm a -time.format.formatKey = HH:mm tooltip.banner.menu.results.facscanto = DB FacsCANTO \ r\u00E9sultats de \ @@ -7027,6 +7529,9 @@ tooltip.banner.menu.results.facscanto = DB FacsCANTO \ tooltip.banner.menu.results.logbook.hemato-immunology = H\u00E9mato-Immunologie tooltip.banner.menu.results.logbook.mycology = Mycologie tooltip.banner.menu.workplan.panel = Par panel +tooltip.bannner.menu.microbiology = Microbiologie +tooltip.bannner.menu.microbiology_classic = Microbiologie Classique +tooltip.bannner.menu.microbiology_tb = Tuberculose tooltip.menu.report.aggregate.site.test.count = Compte de tests par \ site tooltip.project.SpecialRequestStudy.name = Demande Sp\u00E9ciale @@ -7092,18 +7597,24 @@ uom.uomName = Unit\u00E9s de mesure upload.profile.instructions = -validationentry.accession.range = Get Tests For Lab No. -quick.entry.accession.range = Load Next 99 Records Starting at Lab No. -validationentry.date.search = Obtenir des tests pour la date du test +user.select.instruction = S\u00C3\u00A9lectionnez un utilisateur \u00C3\u00A0 \ + modifier ou \u00C3\u00A0 d\u00C3\u00A9sactiver . \ + Vous pouvez d\u00C3\u00A9finir un filtre, rechercher \ + des utilisateurs ou ajouter un utilisateur avec les \ + contr\u00C3\u00B4les en haut +user.userSearch = Noms d'utilisateur + validation.accept = Enregistrer validation.accept.all = Enregistrer tous les r\u00E9sultats validation.accept.explanation = Les r\u00E9sultats seront \ sauvegard\u00E9s dans OpenELIS +validation.date.title = Validation par date de test validation.delete = Ignorer validation.delete.explanation = Les r\u00E9sultats et les tests ne \ seront pas sauvegard\u00E9s dans \ OpenELIS validation.note.retest = Test \u00E0 refaire +validation.range.title = Gamme de Validation validation.reject = Retester validation.reject.all = Retester tous les r\u00E9sultats validation.reject.explanation = Les r\u00E9sultats seront \ @@ -7115,6 +7626,9 @@ validation.title = Validation {0} validationconfiguration.browse.title = Configuration de Validation +validationentry.accession.range = Get Tests For Lab No. +validationentry.date.search = Obtenir des tests pour la date du test + vn.sampletracking.sortlist.receiveddate = Date de r\u00E9ception vn.sampletracking.sortlist.sampletype = Type d'\u00E9chantillon @@ -7157,6 +7671,7 @@ workplan.immunology.title.Haiti = Plan de Travail Immuno-Virologie workplan.liquidBio.title = Plan de Travail Liquides \ Biologique workplan.malaria.title = Plan de Travail Paludisme +workplan.method = M\u00C3\u00A9thode workplan.molecularBio.title = Plan de Travail Biologie \ Moleculaire workplan.mycology.title = Plan de Travail Mycologie @@ -7167,6 +7682,9 @@ workplan.panel.title = Plan de Travail par Panel workplan.panel.types = Panel workplan.parasitology.title = Plan de Travail Parasitologie workplan.print = Imprimer Plan de Travail +workplan.priority.list = Priorit\u00C3\u00A9 +workplan.priority.title = Plan de travail par priorit\u00C3\ + \u00A9 workplan.run = Rechercher workplan.serology.immunology.title = Plan de Travail \ S\u00E9rologie-Immunologie @@ -7181,11 +7699,11 @@ workplan.vct.title.Haiti = Plan de Travail CDV workplan.virology.title = Plan de Travail Virologie workplan.virology.title.LNSP_Haiti = Plan de Travail \ S\u00E9rologie-Virologie -workplan.priority.list = Priorité -workplan.priority.title = Plan de travail par priorité workplanConfiguration.browse.title = Configuration Plan de Travail +years.label = ans + zipcode.add.subtitle = Ajouter Code Postal zipcode.add.title = Ajouter Code Postal zipcode.edit.subtitle = \u00C9diter Code Postal diff --git a/src/main/resources/liquibase/2.7.x.x/activate_result_modifer_role.xml b/src/main/resources/liquibase/2.7.x.x/activate_result_modifer_role.xml new file mode 100644 index 0000000000..bc3ac9f84e --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/activate_result_modifer_role.xml @@ -0,0 +1,35 @@ + + + + + + + select count(*) from + clinlims.system_role + where name = 'Results modifier' limit 1; + + + select count(*) from + clinlims.system_role + where name = 'Lab Unit Roles' limit 1; + + + + + + + id=:value + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_TB_menu.xml b/src/main/resources/liquibase/2.7.x.x/add_TB_menu.xml new file mode 100644 index 0000000000..bfd78b074c --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_TB_menu.xml @@ -0,0 +1,261 @@ + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_microbiology' + + Add menu entry for microbiology + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_microbiology_tb' + + Add menu entry for microbiology + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_microbiology_classic' + + Add menu entry for microbiology + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.system_module WHERE name = 'MicrobiologyTBView' + + Add a module for microbiology TB + + + + + + + + + + + + + + + + SELECT COUNT(*) FROM clinlims.system_role WHERE name = 'Reception' + + + SELECT COUNT(*) FROM clinlims.system_module WHERE name = 'MicrobiologyTBView' + + + Add roles for Microbiology + + + + + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_report_microbiology' + + Add menu entry for microbiology report + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_report' + + Add menu entry for tb report + + + + + + + + + + + + + + + + + + SELECT COUNT(*) FROM clinlims.system_role WHERE name = 'Reception' + + + SELECT COUNT(*) FROM clinlims.system_module WHERE name = 'MicrobiologyTBView' + + + Add roles for Microbiology + + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_report_microbiology_classic' + + Add menu entry for microbiology + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_report' + + + + id=:value + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_report' + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_patient_report' + + Add menu entry for tb report + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_report' + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_result_export' + + Add menu entry for tb report + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_report' + SELECT count(*) FROM clinlims.menu WHERE element_id = 'menu_tb_order_report' + + Add menu entry for tb report + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_loinc_code.xml b/src/main/resources/liquibase/2.7.x.x/add_loinc_code.xml new file mode 100644 index 0000000000..ce82d35733 --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_loinc_code.xml @@ -0,0 +1,27 @@ + + + + + + + select count(*) from + clinlims.test + where name = 'Viral Load' limit 1; + + + + + id=:value + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_patient_upid.xml b/src/main/resources/liquibase/2.7.x.x/add_patient_upid.xml new file mode 100644 index 0000000000..563a48607a --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_patient_upid.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/liquibase/2.7.x.x/add_recency_testing.xml b/src/main/resources/liquibase/2.7.x.x/add_recency_testing.xml new file mode 100644 index 0000000000..c460f73785 --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_recency_testing.xml @@ -0,0 +1,286 @@ + + + + + + + SELECT count(*) FROM + clinlims.project + WHERE name = 'Recency Testing' + + + Add entry for recency testing + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Asante HIV-1 Rapid Recency' + + + + INSERT INTO clinlims.localization( + id, description, english, + french, lastupdated) + VALUES + (nextval('localization_seq'),'test name','Asante HIV-1 Rapid Recency','Asante HIV-1 Rapid Recency', + now()); + INSERT INTO clinlims.localization( + id, description, english, + french, lastupdated) + VALUES + (nextval('localization_seq'),'test report name','Rapid Test for Recent infection','Test Rapide pour Infection Récente', + now()); + + + + + + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Long-Term' + + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Long-Term',now(),'Long-Term',null, + 'dictionary.recency.result.long_term',55000,null), + (nextval('dictionary_seq'),'Y','Recent',now(),'Recent',null, + 'dictionary.recency.result.recent',55000,null), + (nextval('dictionary_seq'),'Y','Inconclusive',now(),'Inconclusive',null, + 'dictionary.recency.result.Inconclusive',55000,null), + (nextval('dictionary_seq'),'Y','Invalid',now(),'Invalid',null, + 'dictionary.recency.result.Invalid',55000,null); + + + + + + SELECT count(*) FROM clinlims.test + WHERE description = 'Asante HIV-1 Rapid Recency(Plasma)' + + + + INSERT INTO clinlims.test( + id, method_id, uom_id, description, + loinc, reporting_description, + sticker_req_flag, is_active, + active_begin, active_end, is_reportable, + time_holding, time_wait, + time_ta_average, time_ta_warning, + time_ta_max, label_qty, lastupdated, + label_id, test_trailer_id, + test_section_id, scriptlet_id, + test_format_id, local_code, + sort_order, name, orderable, + guid, + name_localization_id, reporting_name_localization_id, + default_test_result_id, notify_results) + VALUES + (nextval('test_seq'),null,null,'Asante HIV-1 Rapid Recency(Plasma)','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(), + null,null,136,null,null,'Asante HIV-1 Rapid Recency',1,'Asante HIV-1 Rapid Recency','t', + '6224b40c-388d-41f5-9c70-34c69d149569', + (select id + from localization + where description = 'test name' and + english = 'Asante HIV-1 Rapid Recency' limit + 1), + (select id from localization where + description = 'test report name' and english = 'Rapid Test for Recent infection' limit 1), + null,'f'); + INSERT INTO clinlims.test( + id, + method_id, uom_id, description, loinc, reporting_description, + sticker_req_flag, is_active, active_begin, active_end, is_reportable, + time_holding, time_wait, time_ta_average, time_ta_warning, + time_ta_max, label_qty, lastupdated, label_id, test_trailer_id, + test_section_id, scriptlet_id, test_format_id, local_code, + sort_order, name, orderable, + guid, name_localization_id, + reporting_name_localization_id, + default_test_result_id, + notify_results) + VALUES + (nextval('test_seq'),null,null,'Asante HIV-1 Rapid Recency(Serum)','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(), + null,null,136,null,null,'Asante HIV-1 Rapid Recency',1,'Asante HIV-1 Rapid Recency','t', + '21d9cdc8-e58a-4ba3-9a39-52c15a0c5848', + (select id + from localization + where description = 'test name' and + english = 'Asante HIV-1 Rapid Recency' limit + 1), + (select id from localization where + description = 'test report name' and english = 'Rapid Test for Recent infection' limit 1), + null,'f'); + + + + + SELECT count(*) FROM + clinlims.sampletype_test WHERE test_id = + (select id from + clinlims.test where description = 'Asante HIV-1 Rapid Recency(Plasma)') + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id, + is_panel) + VALUES (nextval('sample_type_test_seq'), + (select id from + type_of_sample where description = 'Plasma' limit + 1), + (select id from + test where description = 'Asante HIV-1 Rapid Recency(Plasma)'), + 'f'); + + + + + SELECT count(*) FROM + clinlims.sampletype_test WHERE test_id = + (select id from + clinlims.test where description = 'Asante HIV-1 Rapid Recency(Serum)') + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id, + is_panel) + VALUES (nextval('sample_type_test_seq'), + (select id from + type_of_sample where description = 'Serum' limit + 1), + (select id from + test where description = 'Asante HIV-1 Rapid Recency(Serum)'), + 'f'); + + + + + + SELECT count(*) FROM + clinlims.result_limits WHERE test_id = + (select id from clinlims.test + where description = 'Asante HIV-1 Rapid Recency(Plasma)') + + + + INSERT INTO clinlims.result_limits(id, test_id, + test_result_type_id, + min_age, max_age, gender, low_normal, + high_normal, low_valid, + high_valid, lastupdated, normal_dictionary_id, + always_validate) + VALUES (nextval('result_limits_seq'), + (select id from + test where + description = 'Asante HIV-1 Rapid Recency(Plasma)'), + 4,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'); + + + + + + SELECT count(*) FROM + clinlims.result_limits WHERE test_id = + (select id from clinlims.test + where description = 'Asante HIV-1 Rapid Recency(Serum)') + + + + INSERT INTO clinlims.result_limits(id, test_id, + test_result_type_id, + min_age, max_age, gender, low_normal, + high_normal, low_valid, + high_valid, lastupdated, normal_dictionary_id, + always_validate) + VALUES (nextval('result_limits_seq'), + (select id from + test where + description = 'Asante HIV-1 Rapid Recency(Serum)'), + 4,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'); + + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id = + (select id from clinlims.test + where description = 'Asante HIV-1 Rapid Recency(Serum)') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order,is_quantifiable,is_active,is_normal) + VALUES + (nextval('test_result_seq'), + (select id from test where description = 'Asante HIV-1 Rapid Recency(Serum)'), null,null,'D', + (select id from dictionary where dict_entry = 'Long-Term' limit 1), + null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), + (select id from test where description = 'Asante HIV-1 Rapid Recency(Serum)'), + null,null,'D', + (select id from dictionary where dict_entry = 'Recent' limit 1), + null,null,null,now(),null,2,'f','t','f'), + (nextval('test_result_seq'), + (select id from test where description ='Asante HIV-1 Rapid Recency(Serum)'), + null,null,'D',(select id from dictionary where dict_entry = 'Inconclusive' limit 1), + null,null,null,now(),null,3,'f','t','f'), + (nextval('test_result_seq'),(select id from test where description ='Asante HIV-1 Rapid Recency(Serum)'), + null,null,'D', + (select id from dictionary where dict_entry = 'Invalid' limit 1),null,null,null,now(),null,4,'f','t','f'); + + + + + SELECT count(*) FROM clinlims.test_result WHERE test_id = + (select id from clinlims.test where description = 'Asante HIV-1 Rapid Recency(Plasma)') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order,is_quantifiable,is_active,is_normal) + VALUES + (nextval('test_result_seq'), + (select id from test where description = 'Asante HIV-1 Rapid Recency(Plasma)'), null,null,'D', + (select id from dictionary where dict_entry = 'Long-Term' limit 1), + null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), + (select id from test where description = 'Asante HIV-1 Rapid Recency(Plasma)'), + null,null,'D', + (select id from dictionary where dict_entry = 'Recent' limit 1), + null,null,null,now(),null,2,'f','t','f'), + (nextval('test_result_seq'), + (select id from test where description ='Asante HIV-1 Rapid Recency(Plasma)'), + null,null,'D',(select id from dictionary where dict_entry = 'Inconclusive' limit 1), + null,null,null,now(),null,3,'f','t','f'), + (nextval('test_result_seq'),(select id from test where description ='Asante HIV-1 Rapid Recency(Plasma)'), + null,null,'D', + (select id from dictionary where dict_entry = 'Invalid' limit 1),null,null,null,now(),null,4,'f','t','f'); + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_tb_dictionary_infos.xml b/src/main/resources/liquibase/2.7.x.x/add_tb_dictionary_infos.xml new file mode 100644 index 0000000000..95c4e0c707 --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_tb_dictionary_infos.xml @@ -0,0 +1,194 @@ + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Order Reasons' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Diagnostic Reasons' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Followup Reasons' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Analysis Methods' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Sample Aspects' + + + + + + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Order Reasons' limit 1 + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Diagnostic' + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Diagnostic',now(),'Diagn',(select id from clinlims.dictionary_category where description = 'TB Order Reasons' limit 1), + 'dictionary.tb.order.diagnostic',55000,null), + (nextval('dictionary_seq'),'Y','Follow up',now(),'Followup',(select id from clinlims.dictionary_category where description = 'TB Order Reasons' limit 1), + 'dictionary.tb.order.followup',55000,null); + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Diagnostic Reasons' limit 1 + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Cas présumé jamais traité' + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Cas présumé jamais traité',now(),'never deal',(select id from clinlims.dictionary_category where description = 'TB Diagnostic Reasons' limit 1), + 'dictionary.tb.order.never_dealt',60001,null), + (nextval('dictionary_seq'),'Y','Echec',now(),'Echec',(select id from clinlims.dictionary_category where description = 'TB Diagnostic Reasons' limit 1), + 'dictionary.tb.order.failure',60002,null), + (nextval('dictionary_seq'),'Y','Rechute',now(),'Rechute',(select id from clinlims.dictionary_category where description = 'TB Diagnostic Reasons' limit 1), + 'dictionary.tb.order.relapse',60003,null), + (nextval('dictionary_seq'),'Y','Reprise',now(),'Reprise',(select id from clinlims.dictionary_category where description = 'TB Diagnostic Reasons' limit 1), + 'dictionary.tb.order.resumption',60004,null), + (nextval('dictionary_seq'),'Y','Frottis positif à M2',now(),'positifM2',(select id from clinlims.dictionary_category where description = 'TB Diagnostic Reasons' limit 1), + 'dictionary.tb.order.smear_positivem2',60005,null); + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Followup Reasons' limit 1 + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Examen de suivi 1ère ligne (TB Sensible)' + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Examen de suivi 1ère ligne (TB Sensible)',now(),'TB Line1',(select id from clinlims.dictionary_category where description = 'TB Followup Reasons' limit 1), + 'dictionary.tb.followup.line1',60001,null), + (nextval('dictionary_seq'),'Y','Examen de suivi 2ième ligne (TB/RR ; TBXDR)',now(),'TB Line2',(select id from clinlims.dictionary_category where description = 'TB Followup Reasons' limit 1), + 'dictionary.tb.followup.line2',60002,null); + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Analysis Methods' limit 1 + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Diagnostic moléculaire TB' + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Diagnostic moléculaire TB',now(),'TB DiagMol',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.diagnostic.molecular',60001,null), + (nextval('dictionary_seq'),'Y','Microscopie TB',now(),'Microsc',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.microscopy',60002,null), + (nextval('dictionary_seq'),'Y','Culture TB',now(),'CultureTB',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.culture',60003,null), + (nextval('dictionary_seq'),'Y','Diagnostic Immunologique TB',now(),'ImmunTB',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.immunologic_diagnostic',60004,null), + (nextval('dictionary_seq'),'Y','Tests de sensibilité genotypique LPA',now(),'LPATests',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.lpa_tests',60005,null), + (nextval('dictionary_seq'),'Y','Tests de sensibilité phénotypique',now(),'PhenoTests',(select id from clinlims.dictionary_category where description = 'TB Analysis Methods' limit 1), + 'dictionary.tb.phenotypic_tests',60006,null); + + + + + + SELECT count(*) FROM + clinlims.dictionary_category WHERE description = 'TB Sample Aspects' limit 1 + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'Muco-purulent' + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','Muco-purulent',now(),'MucoPuru',(select id from clinlims.dictionary_category where description = 'TB Sample Aspects' limit 1), + 'dictionary.tb.aspect.mucopurulent',60001,null), + (nextval('dictionary_seq'),'Y','Salivaire',now(),'Saliv',(select id from clinlims.dictionary_category where description = 'TB Sample Aspects' limit 1), + 'dictionary.tb.aspect.salivary',60002,null), + (nextval('dictionary_seq'),'Y','Sanglant',now(),'Sanglant',(select id from clinlims.dictionary_category where description = 'TB Sample Aspects' limit 1), + 'dictionary.tb.aspect.bloody',60003,null); + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_tb_observation_type.xml b/src/main/resources/liquibase/2.7.x.x/add_tb_observation_type.xml new file mode 100644 index 0000000000..706529cf3f --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_tb_observation_type.xml @@ -0,0 +1,27 @@ + + + + + + + SELECT count(*) FROM clinlims.observation_history_type WHERE type_name = 'TbOrderReason' + + + + INSERT INTO clinlims.observation_history_type(id, type_name, description,lastupdated) VALUES + (nextval('observation_history_type_seq'),'TbOrderReason','Reason for TB order',now()), + (nextval('observation_history_type_seq'),'TbDiagnosticReason','Reason for a TB Patient Diagnostic',now()), + (nextval('observation_history_type_seq'),'TbFollowupReason','Reason for a TB Patient Followup',now()), + (nextval('observation_history_type_seq'),'TbAnalysisMethod','Method for TB Analysis',now()), + (nextval('observation_history_type_seq'),'TbSampleAspects','Aspects for a TB sample',now()), + (nextval('observation_history_type_seq'),'TbFollowupReasonPeriodLine1','Period for a the TB Patient followup 1st Line',now()), + (nextval('observation_history_type_seq'),'TbFollowupReasonPeriodLine2','Period for a the TB Patient followup 2nd Line',now()); + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_tb_samples.xml b/src/main/resources/liquibase/2.7.x.x/add_tb_samples.xml new file mode 100644 index 0000000000..3c368164bb --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_tb_samples.xml @@ -0,0 +1,400 @@ + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Sputum' + + + + + french='Sputum' + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Crachat' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide pleural' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'LCR' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Pus ganglionnaires' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide d’ascite' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide articulaire' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide de ponction péricardique' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Selles' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Urines' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide d’aspiration gastrique' + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Liquide d’aspiration broncho-alvéolaire' + + + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Sputum' OR description = 'Crachat' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide pleural' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'LCR' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Pus ganglionnaires' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide d’ascite' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide articulaire' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide de ponction péricardique' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Selles' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description in ('Urines','Urine') + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description ='Liquide d’aspiration gastrique' + + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description ='Liquide d’aspiration broncho-alvéolaire' + + + + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.localization WHERE french = 'Tuberculose' + + + + + + + + + + + + + + SELECT count(*) FROM clinlims.test_section WHERE name ='TB' + + + + + + + + + + + + + + + SELECT count(*) FROM + clinlims.test_section WHERE name ='TB' limit 1 + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_tb_tests.xml b/src/main/resources/liquibase/2.7.x.x/add_tb_tests.xml new file mode 100644 index 0000000000..f2d39afccc --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/add_tb_tests.xml @@ -0,0 +1,2075 @@ + + + + + + + SELECT count(*) FROM clinlims.localization WHERE french = 'GeneXpert MTB/RIF' + + + + INSERT INTO clinlims.localization(id, description, english,french, lastupdated) VALUES + (nextval('localization_seq'),'test name','GeneXpert MTB/RIF','GeneXpert MTB/RIF',now()), + (nextval('localization_seq'),'test name','TB LAMP','TB LAMP',now()), + (nextval('localization_seq'),'test name','Auramine bacilloscopy','Bacilloscopie Auramine',now()), + (nextval('localization_seq'),'test name','Bacilloscopie Ziehl-Neelsen','Bacilloscopie Ziehl-Neelsen', now()), + (nextval('localization_seq'),'test name','Culture Milieu LJ','Culture Milieu LJ',now()), + (nextval('localization_seq'),'test name','Culture Milieu MGIT','Culture Milieu MGIT',now()), + (nextval('localization_seq'),'panel name','MTBDRplus','MTBDRplus',now()), + (nextval('localization_seq'),'panel name','MTBDRsl','MTBDRsl',now()), + (nextval('localization_seq'),'test name','Rifampicine','Rifampicine',now()), + (nextval('localization_seq'),'test name','Isoniazide','Isoniazide',now()), + (nextval('localization_seq'),'test name','Fluoroquinolone','Fluoroquinolone',now()), + (nextval('localization_seq'),'test name','Injectable','Injectable',now()), + (nextval('localization_seq'),'panel name','Antibiogram TB 1st Line','Antibiogramme TB 1ere Ligne',now()), + (nextval('localization_seq'),'panel name','Antibiogram TB 2nd Line','Antibiogramme TB 2e Ligne',now()), + (nextval('localization_seq'),'test name','Pyrazinamide','Pyrazinamide',now()), + (nextval('localization_seq'),'test name','Ethambutol','Ethambutol',now()), + (nextval('localization_seq'),'test name','Capreomicine','Capreomicine',now()), + (nextval('localization_seq'),'test name','Teridizone','Teridizone',now()), + (nextval('localization_seq'),'test name','Kanamycine','Kanamycine',now()), + (nextval('localization_seq'),'test name','Imipenem','Imipenem',now()), + (nextval('localization_seq'),'test name','Streptomicine','Streptomicine',now()), + (nextval('localization_seq'),'test name','Ethionamide','Ethionamide',now()), + (nextval('localization_seq'),'test name','Prothionamide','Prothionamide',now()), + (nextval('localization_seq'),'test name','Cyclosérine','Cyclosérine',now()), + (nextval('localization_seq'),'test name','Linezolid','Linezolid',now()), + (nextval('localization_seq'),'test name','Moxifloxacine','Moxifloxacine',now()), + (nextval('localization_seq'),'test name','Clofazimine','Clofazimine',now()), + (nextval('localization_seq'),'test name','Levofloxacine','Levofloxacine',now()), + (nextval('localization_seq'),'test name','PAS','PAS',now()), + (nextval('localization_seq'),'test name','Imipénème-Cilastatine','Imipénème-Cilastatine',now()), + (nextval('localization_seq'),'test name','Meropenem','Meropenem',now()), + (nextval('localization_seq'),'test name','Bedaquilline','Bedaquilline',now()), + (nextval('localization_seq'),'test name','Delamanide','Delamanide',now()), + (nextval('localization_seq'),'test name','TB LAM urinaire','TB LAM urinaire',now()), + (nextval('localization_seq'),'test report name','GeneXpert MTB/RIF','GeneXpert MTB/RIF',now()), + (nextval('localization_seq'),'test report name','TB LAMP','TB LAMP',now()), + (nextval('localization_seq'),'test report name','Auramine bacilloscopy','Bacilloscopie Auramine',now()), + (nextval('localization_seq'),'test report name','Bacilloscopie Ziehl-Neelsen','Bacilloscopie Ziehl-Neelsen', now()), + (nextval('localization_seq'),'test report name','Culture Milieu LJ','Culture Milieu LJ',now()), + (nextval('localization_seq'),'test report name','Culture Milieu MGIT','Culture Milieu MGIT',now()), + (nextval('localization_seq'),'test report name','Rifampicine','Rifampicine',now()), + (nextval('localization_seq'),'test report name','Isoniazide','Isoniazide',now()), + (nextval('localization_seq'),'test report name','Fluoroquinolone','Fluoroquinolone',now()), + (nextval('localization_seq'),'test report name','Injectable','Injectable',now()), + (nextval('localization_seq'),'test report name','Pyrazinamide','Pyrazinamide',now()), + (nextval('localization_seq'),'test report name','Ethambutol','Ethambutol',now()), + (nextval('localization_seq'),'test report name','Capreomicine','Capreomicine',now()), + (nextval('localization_seq'),'test report name','Teridizone','Teridizone',now()), + (nextval('localization_seq'),'test report name','Kanamycine','Kanamycine',now()), + (nextval('localization_seq'),'test report name','Imipenem','Imipenem',now()), + (nextval('localization_seq'),'test report name','Streptomicine','Streptomicine',now()), + (nextval('localization_seq'),'test report name','Ethionamide','Ethionamide',now()), + (nextval('localization_seq'),'test report name','Prothionamide','Prothionamide',now()), + (nextval('localization_seq'),'test report name','Cyclosérine','Cyclosérine',now()), + (nextval('localization_seq'),'test report name','Linezolid','Linezolid',now()), + (nextval('localization_seq'),'test report name','Moxifloxacine','Moxifloxacine',now()), + (nextval('localization_seq'),'test report name','Clofazimine','Clofazimine',now()), + (nextval('localization_seq'),'test report name','Levofloxacine','Levofloxacine',now()), + (nextval('localization_seq'),'test report name','PAS','PAS',now()), + (nextval('localization_seq'),'test report name','Imipénème-Cilastatine','Imipénème-Cilastatine',now()), + (nextval('localization_seq'),'test report name','Meropenem','Meropenem',now()), + (nextval('localization_seq'),'test report name','Bedaquilline','Bedaquilline',now()), + (nextval('localization_seq'),'test report name','Delamanide','Delamanide',now()), + (nextval('localization_seq'),'test report name','TB LAM urinaire','TB LAM urinaire',now()); + + + + + + SELECT count(*) FROM + clinlims.dictionary WHERE dict_entry = 'MTB non détecté' + + + + INSERT INTO + clinlims.dictionary(id,is_active,dict_entry,lastupdated,local_abbrev,dictionary_category_id,display_key,sort_order,name_localization_id) + VALUES + (nextval('dictionary_seq'),'Y','MTB non détecté',now(),'MTB NotD',null, + 'dictionary.tb.result.mtb_not_detected',80001,null), + (nextval('dictionary_seq'),'Y','MTB détecté RIF sensible',now(),'MTB RifS',null, + 'dictionary.tb.result.mtb_detected_sensible',80002,null), + (nextval('dictionary_seq'),'Y','MTB détecté RIF Résistant',now(),'MTB RifR',null, + 'dictionary.tb.result.mtb_detected_resistant',80003,null), + (nextval('dictionary_seq'),'Y','MTB détecté RIF indéterminé',now(),'MTB RifI',null, + 'dictionary.tb.result.mtb_ind',80004,null), + (nextval('dictionary_seq'),'Y','Erreur',now(),'Erreur',null, + 'dictionary.tb.result.error',80005,null), + (nextval('dictionary_seq'),'Y','Invalide',now(),'Invalide',null, + 'dictionary.tb.result.invalide',80006,null), + (nextval('dictionary_seq'),'Y','Pas de résultat',now(),'NoResult',null, + 'dictionary.tb.result.no_result',80007,null), + (nextval('dictionary_seq'),'Y','MTB détecté',now(),'MTB DET',null, + 'dictionary.tb.result.mtb_detected',80008,null), + (nextval('dictionary_seq'),'Y','Positif +',now(),'Pos +',null, + 'dictionary.tb.result.mtb_pos1P',80009,null), + (nextval('dictionary_seq'),'Y','Positif ++',now(),'Pos ++',null, + 'dictionary.tb.result.mtb_pos2P',80010,null), + (nextval('dictionary_seq'),'Y','Positif +++',now(),'Pos +++',null, + 'dictionary.tb.result.mtb_pos3P',80011,null), + (nextval('dictionary_seq'),'Y','Positif Rare BAAR',now(),'Pos RB',null, + 'dictionary.tb.result.mtb_posRB',80012,null), + (nextval('dictionary_seq'),'Y','Négatif',now(),'Negative',null, + 'dictionary.tb.result.negative',80013,null), + (nextval('dictionary_seq'),'Y','Culture contaminée',now(),'Culture C',null, + 'dictionary.tb.result.culture_cont',80014,null), + (nextval('dictionary_seq'),'Y','Culture négative',now(),'Culture N',null, + 'dictionary.tb.result.culture_neg',80015,null), + (nextval('dictionary_seq'),'Y','Culture positive',now(),'Culture P',null, + 'dictionary.tb.result.culture_pos',80016,null), + (nextval('dictionary_seq'),'Y','Resistant',now(),'Resistant',null, + 'dictionary.tb.result.culture_res',80017,null), + (nextval('dictionary_seq'),'Y','Sensible',now(),'Sensible',null, + 'dictionary.tb.result.culture_sens',80018,null); + + + + + + SELECT count(*) FROM clinlims.test WHERE description = 'GeneXpert MTB/RIF' + + + + INSERT INTO clinlims.test(id, method_id, uom_id, description,loinc, reporting_description,sticker_req_flag, is_active,active_begin, active_end, is_reportable, + time_holding, time_wait,time_ta_average, time_ta_warning,time_ta_max, label_qty, lastupdated,label_id, test_trailer_id,test_section_id, scriptlet_id, + test_format_id, local_code, sort_order, name, orderable,guid,name_localization_id, reporting_name_localization_id,default_test_result_id, notify_results) + VALUES + (nextval('test_seq'),null,null,'GeneXpert MTB/RIF','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'GeneXpert MTB/RIF',1,'GeneXpert MTB/RIF','t','c9413e2e-8979-440f-9673-6bf1ddc73f6f', + (select id from localization where description = 'test name' and french = 'GeneXpert MTB/RIF' limit 1), + (select id from localization where description = 'test report name' and french = 'GeneXpert MTB/RIF' limit 1), null,'f'), + (nextval('test_seq'),null,null,'TB LAMP','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'TB LAMP',1,'TB LAMP','t','837e42e0-e9a1-45dd-b89d-2e764553448b', + (select id from localization where description = 'test name' and french = 'TB LAMP' limit 1), + (select id from localization where description = 'test report name' and french = 'TB LAMP' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Bacilloscopie Auramine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Bacilloscopie Auramine',1,'Bacilloscopie Auramine','t','e4543638-81c2-4a14-95a2-fe706d321b21', + (select id from localization where description = 'test name' and french = 'Bacilloscopie Auramine' limit 1), + (select id from localization where description = 'test report name' and french = 'Bacilloscopie Auramine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Bacilloscopie Ziehl-Neelsen','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Bacilloscopie Ziehl-Neelsen',1,'Bacilloscopie Ziehl-Neelsen','t','1ee24887-4c74-460f-8eb3-4aed3a323a2d', + (select id from localization where description = 'test name' and french = 'Bacilloscopie Ziehl-Neelsen' limit 1), + (select id from localization where description = 'test report name' and french = 'Bacilloscopie Ziehl-Neelsen' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Culture Milieu LJ','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Culture Milieu LJ',1,'Culture Milieu LJ','t','b0373870-04d7-4a55-92f5-eed1e2fc3935', + (select id from localization where description = 'test name' and french = 'Culture Milieu LJ' limit 1), + (select id from localization where description = 'test report name' and french = 'Culture Milieu LJ' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Culture Milieu MGIT','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Culture Milieu MGIT',1,'Culture Milieu MGIT','t','1043ff93-ca92-4123-87d9-bc63dc4cb8fb', + (select id from localization where description = 'test name' and french = 'Culture Milieu MGIT' limit 1), + (select id from localization where description = 'test report name' and french = 'Culture Milieu MGIT' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Rifampicine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Rifampicine',1,'Rifampicine','t','b026e596-9455-45d1-bb1e-701826855338', + (select id from localization where description = 'test name' and french = 'Rifampicine' limit 1), + (select id from localization where description = 'test report name' and french = 'Rifampicine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Isoniazide','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Isoniazide',1,'Isoniazide','t','34a8ded2-3418-4410-88a1-6b61639aab54', + (select id from localization where description = 'test name' and french = 'Isoniazide' limit 1), + (select id from localization where description = 'test report name' and french = 'Isoniazide' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Fluoroquinolone','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Fluoroquinolone',1,'Fluoroquinolone','t','b7a92712-0d6c-4c62-b516-4e2c5aa9db15', + (select id from localization where description = 'test name' and french = 'Fluoroquinolone' limit 1), + (select id from localization where description = 'test report name' and french = 'Fluoroquinolone' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Injectable','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Injectable',1,'Injectable','t','02c088d2-20a0-4c5d-8a38-eda89876a6c0', + (select id from localization where description = 'test name' and french = 'Injectable' limit 1), + (select id from localization where description = 'test report name' and french = 'Injectable' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Pyrazinamide','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Pyrazinamide',1,'Pyrazinamide','t','a82f3b98-6a7e-4884-bb91-c4a174ce3f72', + (select id from localization where description = 'test name' and french = 'Pyrazinamide' limit 1), + (select id from localization where description = 'test report name' and french = 'Pyrazinamide' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Ethambutol','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Ethambutol',1,'Ethambutol','t','b115cb58-511d-41d1-8212-d6d88053b9e2', + (select id from localization where description = 'test name' and french = 'Ethambutol' limit 1), + (select id from localization where description = 'test report name' and french = 'Ethambutol' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Capreomicine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Capreomicine',1,'Capreomicine','t','89d4e974-ae49-4b93-8906-98b579a86f69', + (select id from localization where description = 'test name' and french = 'Capreomicine' limit 1), + (select id from localization where description = 'test report name' and french = 'Capreomicine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Teridizone','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Teridizone',1,'Teridizone','t','5d56f762-ca73-485e-92fc-6fd035cacd8e', + (select id from localization where description = 'test name' and french = 'Teridizone' limit 1), + (select id from localization where description = 'test report name' and french = 'Teridizone' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Kanamycine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Kanamycine',1,'Kanamycine','t','5354866f-64b0-43a9-a414-e168418db871', + (select id from localization where description = 'test name' and french = 'Kanamycine' limit 1), + (select id from localization where description = 'test report name' and french = 'Kanamycine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Imipenem','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Imipenem',1,'Imipenem','t','077ea0ca-d075-49f9-a33d-5a0e891efb71', + (select id from localization where description = 'test name' and french = 'Imipenem' limit 1), + (select id from localization where description = 'test report name' and french = 'Imipenem' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Streptomicine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Streptomicine',1,'Streptomicine','t','f248174d-84b2-4ec1-8ebe-528ec62c210d', + (select id from localization where description = 'test name' and french = 'Streptomicine' limit 1), + (select id from localization where description = 'test report name' and french = 'Streptomicine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Ethionamide','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Ethionamide',1,'Ethionamide','t','95a8a513-c3de-4caf-b9e3-f2abc20281c7', + (select id from localization where description = 'test name' and french = 'Ethionamide' limit 1), + (select id from localization where description = 'test report name' and french = 'Ethionamide' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Prothionamide','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Prothionamide',1,'Prothionamide','t','47b7255c-3d7e-4d22-a37e-723667a5daef', + (select id from localization where description = 'test name' and french = 'Prothionamide' limit 1), + (select id from localization where description = 'test report name' and french = 'Prothionamide' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Cyclosérine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Cyclosérine',1,'Cyclosérine','t','020d39d0-5eec-4ca9-bcc9-4a1031d1e339', + (select id from localization where description = 'test name' and french = 'Cyclosérine' limit 1), + (select id from localization where description = 'test report name' and french = 'Cyclosérine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Linezolid','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Linezolid',1,'Linezolid','t','7681ae7b-f62c-4480-a83b-18a008d336e2', + (select id from localization where description = 'test name' and french = 'Linezolid' limit 1), + (select id from localization where description = 'test report name' and french = 'Linezolid' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Moxifloxacine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Moxifloxacine',1,'Moxifloxacine','t','b10587c8-d3b5-486c-bac2-8d07c62144d7', + (select id from localization where description = 'test name' and french = 'Moxifloxacine' limit 1), + (select id from localization where description = 'test report name' and french = 'Moxifloxacine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Clofazimine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Clofazimine',1,'Clofazimine','t','6834169e-c1d2-49ba-9272-34d4fda0519e', + (select id from localization where description = 'test name' and french = 'Clofazimine' limit 1), + (select id from localization where description = 'test report name' and french = 'Clofazimine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Levofloxacine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Levofloxacine',1,'Levofloxacine','t','5bf4b52c-52b8-4164-b634-c57e22a0f4eb', + (select id from localization where description = 'test name' and french = 'Levofloxacine' limit 1), + (select id from localization where description = 'test report name' and french = 'Levofloxacine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'PAS','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'PAS',1,'PAS','t','4a2941a2-0997-4538-89e0-5a7e4fcb14de', + (select id from localization where description = 'test name' and french = 'PAS' limit 1), + (select id from localization where description = 'test report name' and french = 'PAS' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Imipénème-Cilastatine','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Imipénème-Cilastatine',1,'Imipénème-Cilastatine','t','b33a435c-d884-4c80-a324-dffd4a289697', + (select id from localization where description = 'test name' and french = 'Imipénème-Cilastatine' limit 1), + (select id from localization where description = 'test report name' and french = 'Imipénème-Cilastatine' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Meropenem','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Meropenem',1,'Meropenem','t','4fe3dcf0-ea96-4523-b530-1cf3f116871c', + (select id from localization where description = 'test name' and french = 'Meropenem' limit 1), + (select id from localization where description = 'test report name' and french = 'Meropenem' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Bedaquilline','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Bedaquilline',1,'Bedaquilline','t','1498e2db-4114-4489-b378-27e7710fbdf3', + (select id from localization where description = 'test name' and french = 'Bedaquilline' limit 1), + (select id from localization where description = 'test report name' and french = 'Bedaquilline' limit 1),null,'f'), + (nextval('test_seq'),null,null,'Delamanide','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'Delamanide',1,'Delamanide','t','a66669e6-27dc-4895-9b5e-981151b00f3a', + (select id from localization where description = 'test name' and french = 'Delamanide' limit 1), + (select id from localization where description = 'test report name' and french = 'Delamanide' limit 1),null,'f'), + (nextval('test_seq'),null,null,'TB LAM urinaire','',null,null,'Y',null,null,'N',null,null,null,null,null,null,now(),null,null, + (select id from test_section where name = 'TB' limit 1), + null,null,'TB LAM urinaire',1,'TB LAM urinaire','t','f41361dc-1c51-4684-a42d-5ec34435a387', + (select id from localization where description = 'test name' and french = 'TB LAM urinaire' limit 1), + (select id from localization where description = 'test report name' and french = 'TB LAM urinaire' limit 1),null,'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Sputum' OR description = 'Crachat limit 1' + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Sputum' OR description = 'Crachat' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide pleural' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide pleural' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'LCR' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'LCR' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Pus ganglionnaires' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Pus ganglionnaires' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide d’ascite' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’ascite' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide articulaire' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide articulaire' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide de ponction péricardique' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide de ponction péricardique' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Selles' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Selles' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Urines' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Urines' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide d’aspiration gastrique' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration gastrique' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.type_of_sample WHERE description = 'Liquide d’aspiration broncho-alvéolaire' limit 1 + + + + INSERT into clinlims.sampletype_test(id, sample_type_id, test_id,is_panel) + VALUES + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'GeneXpert MTB/RIF'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'TB LAMP'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Bacilloscopie Auramine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Culture Milieu LJ'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Culture Milieu MGIT'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Rifampicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Isoniazide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Fluoroquinolone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Injectable'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Pyrazinamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Ethambutol'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Capreomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Teridizone'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Kanamycine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Imipenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Streptomicine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Ethionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Prothionamide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Cyclosérine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Linezolid'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Moxifloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Clofazimine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Levofloxacine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'PAS'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Imipénème-Cilastatine'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Meropenem'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Bedaquilline'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'Delamanide'),'f'), + (nextval('sample_type_test_seq'),(select id from type_of_sample where description = 'Liquide d’aspiration broncho-alvéolaire' limit 1), + (select id from test where description = 'TB LAM urinaire'),'f'); + + + + + SELECT count(*) FROM clinlims.result_limits WHERE test_id = + (select id from clinlims.test where description = 'GeneXpert MTB/RIF') + + + + INSERT INTO clinlims.result_limits(id, test_id, test_result_type_id,min_age, max_age, gender, low_normal, + high_normal, low_valid, high_valid, lastupdated, normal_dictionary_id, always_validate) + VALUES + (nextval('result_limits_seq'),(select id from test where description = 'GeneXpert MTB/RIF'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'TB LAMP'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Bacilloscopie Auramine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Bacilloscopie Ziehl-Neelsen'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Culture Milieu LJ'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Culture Milieu MGIT'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Rifampicine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Isoniazide'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Fluoroquinolone'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Injectable'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Pyrazinamide'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Ethambutol'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Capreomicine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Teridizone'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Kanamycine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Imipenem'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Streptomicine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Ethionamide'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Prothionamide'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Cyclosérine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Cyclosérine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Linezolid'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Moxifloxacine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Clofazimine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Levofloxacine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'PAS'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Imipénème-Cilastatine'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Meropenem'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Meropenem'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Bedaquilline'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'Delamanide'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'), + (nextval('result_limits_seq'),(select id from test where description = 'TB LAM urinaire'), + 2,0,'Infinity',null,'-Infinity','Infinity','-Infinity','Infinity',now(),null,'f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'GeneXpert MTB/RIF') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'MTB non détecté' limit 1), null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'MTB détecté RIF sensible' limit 1), null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'MTB détecté RIF Résistant' limit 1), null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'MTB détecté RIF indéterminé' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'Erreur' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'Invalide' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'GeneXpert MTB/RIF'), null,null,'D', + (select id from dictionary where dict_entry = 'Pas de résultat' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'TB LAMP') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'TB LAMP'),null,null,'D', + (select id from dictionary where dict_entry = 'MTB non détecté' limit 1), null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'TB LAMP'), null,null,'D', + (select id from dictionary where dict_entry = 'MTB détecté' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Bacilloscopie Auramine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Auramine'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif +' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Auramine'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif ++' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Auramine'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif +++' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Auramine'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif Rare BAAR' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Auramine'),null,null,'D', + (select id from dictionary where dict_entry = 'Négatif' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Bacilloscopie Ziehl-Neelsen') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif +' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif ++' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif +++' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif Rare BAAR' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bacilloscopie Ziehl-Neelsen'),null,null,'D', + (select id from dictionary where dict_entry = 'Négatif' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Culture Milieu LJ') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu LJ'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture contaminée' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu LJ'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture négative' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu LJ'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture positive' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Culture Milieu MGIT') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu MGIT'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture contaminée' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu MGIT'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture négative' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Culture Milieu MGIT'),null,null,'D', + (select id from dictionary where dict_entry = 'Culture positive' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Rifampicine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Rifampicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Rifampicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Isoniazide') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Isoniazide'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Isoniazide'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Fluoroquinolone') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Fluoroquinolone'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Fluoroquinolone'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Injectable') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Injectable'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Injectable'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Pyrazinamide') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Pyrazinamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Pyrazinamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Ethambutol') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Ethambutol'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Ethambutol'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Capreomicine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Capreomicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Capreomicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Teridizone') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Teridizone'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Teridizone'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Kanamycine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Kanamycine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Kanamycine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Imipenem') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Imipenem'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Imipenem'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Streptomicine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Streptomicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Streptomicine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Ethionamide') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Ethionamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Ethionamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Prothionamide') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Prothionamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Prothionamide'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Cyclosérine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Cyclosérine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Cyclosérine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Linezolid') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Linezolid'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Linezolid'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Moxifloxacine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Moxifloxacine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Moxifloxacine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Clofazimine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Clofazimine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Clofazimine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Levofloxacine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Levofloxacine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Levofloxacine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'PAS') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'PAS'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'PAS'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Imipénème-Cilastatine') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Imipénème-Cilastatine'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Imipénème-Cilastatine'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Meropenem') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Meropenem'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Meropenem'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Bedaquilline') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Bedaquilline'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Bedaquilline'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'Delamanide') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'Delamanide'),null,null,'D', + (select id from dictionary where dict_entry = 'Resistant' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'Delamanide'),null,null,'D', + (select id from dictionary where dict_entry = 'Sensible' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + SELECT count(*) FROM + clinlims.test_result WHERE test_id =(select id from clinlims.test where description = 'TB LAM urinaire') + + + + INSERT INTO + clinlims.test_result(id,test_id,result_group,flags,tst_rslt_type,value,significant_digits,quant_limit,cont_level,lastupdated,scriptlet_id,sort_order, + is_quantifiable,is_active,is_normal) VALUES + (nextval('test_result_seq'), (select id from test where description = 'TB LAM urinaire'),null,null,'D', + (select id from dictionary where dict_entry = 'Positif' limit 1),null,null,null,now(),null,1,'f','t','f'), + (nextval('test_result_seq'), (select id from test where description = 'TB LAM urinaire'),null,null,'D', + (select id from dictionary where dict_entry = 'Négatif' limit 1),null,null,null,now(),null,1,'f','t','f'); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Diagnostic moléculaire TB' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Diagnostic moléculaire TB' limit 1), + (select id from test where name ='GeneXpert MTB/RIF' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Diagnostic moléculaire TB' limit 1), + (select id from test where name ='TB LAMP' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Microscopie TB' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Microscopie TB' limit 1), + (select id from test where name ='Bacilloscopie Auramine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Microscopie TB' limit 1), + (select id from test where name ='Bacilloscopie Ziehl-Neelsen' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Culture TB' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Culture TB' limit 1), + (select id from test where name ='Culture Milieu LJ' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Culture TB' limit 1), + (select id from test where name ='Culture Milieu MGIT' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Diagnostic Immunologique TB' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Diagnostic Immunologique TB' limit 1), + (select id from test where name ='TB LAM urinaire' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Tests de sensibilité genotypique LPA' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from test where name ='Rifampicine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from test where name ='Isoniazide' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from test where name ='Fluoroquinolone' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from test where name ='Injectable' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Tests de sensibilité phénotypique' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_test(id,method_id,test_id,is_active) VALUES + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Rifampicine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Isoniazide' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Pyrazinamide' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Ethambutol' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Capreomicine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Teridizone' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Kanamycine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Imipenem' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Streptomicine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Ethionamide' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Prothionamide' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Cyclosérine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Linezolid' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Moxifloxacine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Clofazimine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Levofloxacine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='PAS' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Imipénème-Cilastatine' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Meropenem' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Bedaquilline' limit 1),'Y'), + (nextval('tb_method_test_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from test where name ='Delamanide' limit 1),'Y'); + + + + + + + + SELECT count(*) FROM panel WHERE name ='MTBDRplus' + + + + INSERT INTO clinlims.panel(id,name,description,lastupdated,sort_order,is_active,name_localization_id) VALUES + (nextval('panel_seq'), 'MTBDRplus','MTBDRplus', now(), 51,'Y', (select id from clinlims.localization where + french ='MTBDRplus' limit 1)), + (nextval('panel_seq'), 'MTBDRsl','MTBDRsl', now(), 52,'Y', (select id from clinlims.localization where + french ='MTBDRsl' limit 1)), + (nextval('panel_seq'), 'Antibiogramme TB 1ere Ligne','Antibiogramme TB 1ere Ligne', now(), 53,'Y', (select id from clinlims.localization where + french ='Antibiogramme TB 1ere Ligne' limit 1)), + (nextval('panel_seq'), 'Antibiogramme TB 2e Ligne','Antibiogramme TB 2e Ligne', now(), 54,'Y', (select id from clinlims.localization where + french ='Antibiogramme TB 2e Ligne' limit 1)); + + + + + + + + SELECT count(*) FROM panel WHERE name ='MTBDRplus' LIMIT 1 + + + + INSERT INTO clinlims.panel_item(id,panel_id,lastupdated,test_id) VALUES + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='MTBDRplus' limit 1),now(),(select id from clinlims.test where + name ='Rifampicine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='MTBDRplus' limit 1),now(),(select id from clinlims.test where + name ='Isoniazide' limit 1)); + + + + + + + SELECT count(*) FROM panel WHERE name ='MTBDRsl' LIMIT 1 + + + + INSERT INTO clinlims.panel_item(id,panel_id,lastupdated,test_id) VALUES + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='MTBDRsl' limit 1),now(),(select id from clinlims.test where + name ='Fluoroquinolone' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='MTBDRsl' limit 1),now(),(select id from clinlims.test where + name ='Injectable' limit 1)); + + + + + + + SELECT count(*) FROM panel WHERE name ='Antibiogramme TB 1ere Ligne' LIMIT 1 + + + + INSERT INTO clinlims.panel_item(id,panel_id,lastupdated,test_id) VALUES + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 1ere Ligne' limit 1),now(),(select id from clinlims.test where + name ='Rifampicine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 1ere Ligne' limit 1),now(),(select id from clinlims.test where + name ='Isoniazide' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 1ere Ligne' limit 1),now(),(select id from clinlims.test where + name ='Pyrazinamide' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 1ere Ligne' limit 1),now(),(select id from clinlims.test where + name ='Ethambutol' limit 1)); + + + + + + + SELECT count(*) FROM panel WHERE name ='Antibiogramme TB 2e Ligne' LIMIT 1 + + + + INSERT INTO clinlims.panel_item(id,panel_id,lastupdated,test_id) VALUES + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Capreomicine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Teridizone' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Kanamycine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Pyrazinamide' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Imipenem' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Streptomicine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Ethionamide' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Prothionamide' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Cyclosérine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Linezolid' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Moxifloxacine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Clofazimine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Levofloxacine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='PAS' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Imipénème-Cilastatine' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Meropenem' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Bedaquilline' limit 1)), + (nextval('panel_item_seq'),(select id from clinlims.panel where name ='Antibiogramme TB 2e Ligne' limit 1),now(),(select id from clinlims.test where + name ='Delamanide' limit 1)); + + + + + + + + + + ALTER TABLE clinlims.tb_method_test ALTER COLUMN method_id TYPE numeric(10) USING method_id::numeric; + ALTER TABLE clinlims.tb_method_test ALTER COLUMN test_id TYPE numeric(10) USING test_id::numeric; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Tests de sensibilité genotypique LPA' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_panel(id,method_id,panel_id,is_active) VALUES + (nextval('tb_method_panel_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from panel where name ='MTBDRplus' limit 1),'Y'), + (nextval('tb_method_panel_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité genotypique LPA' limit 1), + (select id from panel where name ='MTBDRsl' limit 1),'Y'); + + + + + + + SELECT count(*) FROM dictionary WHERE dict_entry ='Tests de sensibilité phénotypique' LIMIT 1 + + + + INSERT INTO clinlims.tb_method_panel(id,method_id,panel_id,is_active) VALUES + (nextval('tb_method_panel_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from panel where name ='Antibiogramme TB 1ere Ligne' limit 1),'Y'), + (nextval('tb_method_panel_seq'), (select id from dictionary where + dict_entry ='Tests de sensibilité phénotypique' limit 1), + (select id from panel where name ='Antibiogramme TB 2e Ligne' limit 1),'Y'); + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/add_validation_by_date.xml b/src/main/resources/liquibase/2.7.x.x/add_validation_by_date.xml index f312144c77..36d80f6373 100644 --- a/src/main/resources/liquibase/2.7.x.x/add_validation_by_date.xml +++ b/src/main/resources/liquibase/2.7.x.x/add_validation_by_date.xml @@ -23,4 +23,18 @@ + + + SELECT count(*) FROM + clinlims.system_module_url WHERE url_path = '/ResultValidationByTestDate' + + + Add ResultValidationByTestDate module url to the ResultsValidationGeneral module + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/base.xml b/src/main/resources/liquibase/2.7.x.x/base.xml index acd4b31d25..bac914a821 100644 --- a/src/main/resources/liquibase/2.7.x.x/base.xml +++ b/src/main/resources/liquibase/2.7.x.x/base.xml @@ -15,4 +15,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/liquibase/2.7.x.x/extend_person_state_column.xml b/src/main/resources/liquibase/2.7.x.x/extend_person_state_column.xml new file mode 100644 index 0000000000..70a547ef51 --- /dev/null +++ b/src/main/resources/liquibase/2.7.x.x/extend_person_state_column.xml @@ -0,0 +1,18 @@ + + + + + + + + Extend patient state length + + + + \ No newline at end of file diff --git a/src/main/resources/reports/PatientReportCDI_vreduit.jrxml b/src/main/resources/reports/PatientReportCDI_vreduit.jrxml index 29571f347a..3beebc89f5 100644 --- a/src/main/resources/reports/PatientReportCDI_vreduit.jrxml +++ b/src/main/resources/reports/PatientReportCDI_vreduit.jrxml @@ -1,6 +1,6 @@ - + @@ -96,7 +96,7 @@ - + @@ -113,7 +113,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -140,13 +140,13 @@ - + - + @@ -158,7 +158,7 @@ - + @@ -177,7 +177,7 @@ - + @@ -193,7 +193,7 @@ - + 1]]> @@ -204,7 +204,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -233,7 +233,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -261,7 +261,7 @@ - + @@ -275,7 +275,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -302,7 +302,7 @@ - + @@ -316,7 +316,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -346,11 +346,11 @@ - + - + @@ -365,7 +365,7 @@ - + @@ -380,7 +380,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -412,7 +412,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -441,7 +441,7 @@ - + @@ -456,7 +456,7 @@ - + @@ -472,7 +472,7 @@ - + @@ -487,7 +487,7 @@ - + @@ -502,7 +502,7 @@ - + @@ -516,7 +516,7 @@ - + @@ -527,7 +527,7 @@ - + @@ -541,7 +541,7 @@ - + @@ -553,7 +553,7 @@ - + @@ -567,7 +567,7 @@ - + @@ -579,7 +579,7 @@ - + @@ -593,7 +593,7 @@ - + @@ -606,7 +606,7 @@ - + @@ -621,7 +621,7 @@ - + @@ -636,7 +636,7 @@ - + @@ -648,7 +648,7 @@ - + @@ -660,7 +660,7 @@ - + @@ -675,7 +675,7 @@ - + @@ -687,7 +687,7 @@ - + @@ -703,7 +703,7 @@ - + @@ -719,7 +719,7 @@ - + @@ -733,7 +733,7 @@ - + @@ -746,7 +746,7 @@ - + @@ -772,7 +772,7 @@ - + @@ -780,7 +780,7 @@ - + @@ -791,7 +791,7 @@ - + @@ -802,7 +802,7 @@ - + @@ -813,7 +813,7 @@ - + @@ -824,7 +824,7 @@ - + @@ -835,7 +835,7 @@ - + @@ -846,7 +846,7 @@ - + @@ -861,7 +861,7 @@ - + @@ -882,7 +882,7 @@ <band height="2" splitType="Stretch"> <line> - <reportElement key="line" x="0" y="-45" width="534" height="1" forecolor="#000000" uuid="c8ef8d50-e434-41ac-9333-a3c38e4f7e10"/> + <reportElement key="line" x="0" y="-45" width="534" height="1" forecolor="#000000"/> <graphicElement> <pen lineWidth="2.0" lineStyle="Solid"/> </graphicElement> @@ -893,7 +893,7 @@ <band height="124" splitType="Stretch"> <printWhenExpression><![CDATA[$V{PAGE_NUMBER} == 1]]></printWhenExpression> <subreport> - <reportElement x="0" y="0" width="552" height="94" printWhenGroupChanges="person" uuid="00b90f40-e147-45c1-9d66-55819ec18be1"/> + <reportElement x="0" y="0" width="552" height="94" printWhenGroupChanges="person"/> <subreportParameter name="labName2"> <subreportParameterExpression><![CDATA[$P{additionalSiteInfo}]]></subreportParameterExpression> </subreportParameter> @@ -955,7 +955,7 @@ <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + $P{headerName}]]></subreportExpression> </subreport> <textField> - <reportElement mode="Transparent" x="0" y="93" width="552" height="16" isRemoveLineWhenBlank="true" uuid="eff7285f-3850-4c1c-b992-31456e5d07e0"> + <reportElement mode="Transparent" x="0" y="93" width="552" height="16" isRemoveLineWhenBlank="true"> <printWhenExpression><![CDATA[$F{correctedResult}]]></printWhenExpression> </reportElement> <textElement textAlignment="Center" verticalAlignment="Bottom"> @@ -965,7 +965,7 @@ <textFieldExpression><![CDATA[$R{report.correctedReport}]]></textFieldExpression> </textField> <textField> - <reportElement mode="Opaque" x="1" y="110" width="550" height="13" uuid="e92e9718-5cbe-4e23-af55-8d2ddd09d5cd"/> + <reportElement mode="Opaque" x="1" y="110" width="550" height="13" /> <textElement textAlignment="Center" verticalAlignment="Middle"> <font size="8"/> <paragraph lineSpacing="Single"/> @@ -980,7 +980,7 @@ <detail> <band height="23" splitType="Prevent"> <rectangle> - <reportElement positionType="Float" mode="Opaque" x="0" y="12" width="10" height="11" isRemoveLineWhenBlank="true" isPrintWhenDetailOverflows="true" forecolor="#E6E6E6" backcolor="#CCCCCC" uuid="4253a44e-0a1c-4c2d-a2b0-3e89a2204c1e"> + <reportElement positionType="Float" mode="Opaque" x="0" y="12" width="10" height="11" isRemoveLineWhenBlank="true" isPrintWhenDetailOverflows="true" forecolor="#E6E6E6" backcolor="#CCCCCC" > <printWhenExpression><![CDATA[$F{note} != null]]></printWhenExpression> </reportElement> <graphicElement> @@ -988,7 +988,7 @@ </graphicElement> </rectangle> <frame> - <reportElement x="0" y="0" width="553" height="12" forecolor="#000000" uuid="e878469d-7d34-49d1-a2fb-cbcddac2f384"/> + <reportElement x="0" y="0" width="553" height="12" forecolor="#000000"/> <box> <pen lineWidth="0.25" lineColor="#CCCCCC"/> <topPen lineWidth="0.5" lineColor="#000000"/> @@ -997,7 +997,7 @@ <rightPen lineWidth="0.25" lineColor="#000000"/> </box> <rectangle> - <reportElement stretchType="RelativeToBandHeight" x="1" y="0" width="551" height="11" backcolor="#E0E0E0" uuid="5057da31-3221-45b5-bd39-3b72a109d5c1"> + <reportElement stretchType="RelativeToBandHeight" x="1" y="0" width="551" height="11" backcolor="#E0E0E0"> <printWhenExpression><![CDATA[$F{parentMarker}]]></printWhenExpression> </reportElement> <graphicElement> @@ -1005,7 +1005,7 @@ </graphicElement> </rectangle> <textField textAdjust="StretchHeight" isBlankWhenNull="true"> - <reportElement stretchType="RelativeToTallestObject" x="183" y="0" width="110" height="12" uuid="85834b4b-905d-4e59-92a3-474edfb0f5aa"> + <reportElement stretchType="RelativeToTallestObject" x="183" y="0" width="110" height="12"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box topPadding="2" bottomPadding="2" rightPadding="4"> @@ -1021,7 +1021,7 @@ <textFieldExpression><![CDATA[$F{result}]]></textFieldExpression> </textField> <textField textAdjust="StretchHeight"> - <reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="153" height="12" uuid="7369b84e-d459-45d6-9e8b-688d3dc83c5d"> + <reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="153" height="12"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box topPadding="2" leftPadding="4" bottomPadding="2"> @@ -1038,7 +1038,7 @@ <textFieldExpression><![CDATA[$F{testName}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> - <reportElement stretchType="RelativeToTallestObject" x="373" y="0" width="110" height="12" uuid="5a890443-25a6-460c-9ecf-e94266bcf1a3"> + <reportElement stretchType="RelativeToTallestObject" x="373" y="0" width="110" height="12"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box topPadding="2" bottomPadding="2"> @@ -1054,7 +1054,7 @@ <textFieldExpression><![CDATA[$F{testRefRange}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> - <reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="343" y="0" width="30" height="12" backcolor="#FFFFFF" uuid="63be3b3a-d647-464f-b0a7-0fa5bb2a0adf"> + <reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="343" y="0" width="30" height="12" backcolor="#FFFFFF"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box> @@ -1068,7 +1068,7 @@ <textFieldExpression><![CDATA[$F{alerts}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> - <reportElement stretchType="RelativeToTallestObject" x="483" y="0" width="70" height="12" uuid="3b35fc1a-0d5c-429b-aa47-ab673563b8fa"> + <reportElement stretchType="RelativeToTallestObject" x="483" y="0" width="70" height="12"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box topPadding="2" bottomPadding="2"> @@ -1084,7 +1084,7 @@ <textFieldExpression><![CDATA[$F{uom}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> - <reportElement x="293" y="0" width="50" height="12" uuid="39ca2a4f-6c95-47ae-929a-fd94e81462f1"> + <reportElement x="293" y="0" width="50" height="12"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <textElement textAlignment="Center" verticalAlignment="Middle"> @@ -1094,7 +1094,7 @@ <textFieldExpression><![CDATA[$F{analysisStatus}]]></textFieldExpression> </textField> <textField isBlankWhenNull="true"> - <reportElement stretchType="RelativeToTallestObject" x="153" y="0" width="30" height="12" isPrintWhenDetailOverflows="true" uuid="44c91a22-b27e-499f-bbf0-de8e83fc01ea"> + <reportElement stretchType="RelativeToTallestObject" x="153" y="0" width="30" height="12" isPrintWhenDetailOverflows="true"> <property name="com.jaspersoft.studio.unit.width" value="px"/> </reportElement> <box topPadding="2" leftPadding="4" bottomPadding="2"> @@ -1112,7 +1112,7 @@ </textField> </frame> <textField textAdjust="StretchHeight" isBlankWhenNull="true"> - <reportElement positionType="Float" stretchType="RelativeToTallestObject" mode="Opaque" x="10" y="12" width="543" height="11" isRemoveLineWhenBlank="true" backcolor="#F5F5F5" uuid="33e6ed2f-7490-4610-bb37-82e66d73ae33"> + <reportElement positionType="Float" stretchType="RelativeToTallestObject" mode="Opaque" x="10" y="12" width="543" height="11" isRemoveLineWhenBlank="true" backcolor="#F5F5F5"> <printWhenExpression><![CDATA[$F{note} != null]]></printWhenExpression> </reportElement> <box topPadding="2" leftPadding="4" rightPadding="4"> @@ -1133,7 +1133,7 @@ <columnFooter> <band height="16" splitType="Stretch"> <textField> - <reportElement x="28" y="2" width="524" height="14" uuid="48dbca36-4911-4bc3-a3df-abf71f70f14b"/> + <reportElement x="28" y="2" width="524" height="14"/> <textElement verticalAlignment="Middle"> <font size="7"/> <paragraph lineSpacing="Single"/> @@ -1141,7 +1141,7 @@ <textFieldExpression><![CDATA["B = " + $R{report.belowNormal} + " E = " + $R{report.aboveNormal} + " * = " + $R{report.abnormal} + " R = " + $R{report.extLabReference} + " C = " + $R{report.confirmTest}]]></textFieldExpression> </textField> <textField> - <reportElement x="0" y="2" width="28" height="14" uuid="e08f4316-e96a-4177-afb9-356c2c14820c"/> + <reportElement x="0" y="2" width="28" height="14"/> <textElement verticalAlignment="Middle"> <font size="6"/> <paragraph lineSpacing="Single"/> @@ -1153,7 +1153,7 @@ <pageFooter> <band height="14" splitType="Stretch"> <textField> - <reportElement x="371" y="4" width="126" height="10" uuid="8fdf8c08-a40a-4f30-9129-67558587e3fe"> + <reportElement x="371" y="4" width="126" height="10"> <printWhenExpression><![CDATA[$P{usePageNumbers}.equals("true")]]></printWhenExpression> </reportElement> <textElement textAlignment="Right" verticalAlignment="Middle"> @@ -1163,7 +1163,7 @@ <textFieldExpression><![CDATA[$R{report.label.page}+" "+$V{PAGE_NUMBER}+" "+$R{report.about}]]></textFieldExpression> </textField> <textField evaluationTime="Group" evaluationGroup="Accession Number"> - <reportElement x="497" y="4" width="37" height="10" uuid="fbc71ed2-8d6d-46ba-920f-256901710d1a"> + <reportElement x="497" y="4" width="37" height="10"> <printWhenExpression><![CDATA[$P{usePageNumbers}.equals("true")]]></printWhenExpression> </reportElement> <textElement verticalAlignment="Middle"> @@ -1173,7 +1173,7 @@ <textFieldExpression><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression> </textField> <textField pattern="dd/MM/yyyy HH.mm.ss"> - <reportElement x="102" y="4" width="148" height="10" uuid="4add1ea7-4995-4e0a-ab30-d3973a195b7a"/> + <reportElement x="102" y="4" width="148" height="10"/> <textElement verticalAlignment="Middle"> <font size="7" isBold="true"/> <paragraph lineSpacing="Single"/> @@ -1181,7 +1181,7 @@ <textFieldExpression><![CDATA[new java.util.Date()]]></textFieldExpression> </textField> <textField> - <reportElement x="2" y="4" width="100" height="10" uuid="dd5d01af-cc58-4b1d-b19b-872051847196"/> + <reportElement x="2" y="4" width="100" height="10"/> <box rightPadding="4"/> <textElement textAlignment="Right" verticalAlignment="Middle"> <font size="7" isBold="true"/> diff --git a/src/main/resources/reports/Patient_ARV_Followup_patient_info.jasper b/src/main/resources/reports/Patient_ARV_Followup_patient_info.jasper index cfbce7dff8..838bea7c9d 100644 Binary files a/src/main/resources/reports/Patient_ARV_Followup_patient_info.jasper and b/src/main/resources/reports/Patient_ARV_Followup_patient_info.jasper differ diff --git a/src/main/resources/reports/Patient_ARV_Followup_patient_info.jrxml b/src/main/resources/reports/Patient_ARV_Followup_patient_info.jrxml index 9437049523..4ec28c4188 100644 --- a/src/main/resources/reports/Patient_ARV_Followup_patient_info.jrxml +++ b/src/main/resources/reports/Patient_ARV_Followup_patient_info.jrxml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Patient_ARV_Followup_patient_info" pageWidth="552" pageHeight="802" columnWidth="552" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0"> +<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Patient_ARV_Followup_patient_info" pageWidth="552" pageHeight="802" columnWidth="552" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="dab72e0b-fab1-4108-ab9f-21f81a0fa6ac"> <property name="ireport.scriptlethandling" value="0"/> <property name="ireport.encoding" value="UTF-8"/> <property name="ireport.zoom" value="1.6528925619834736"/> @@ -26,6 +26,7 @@ <parameter name="studyName" class="java.lang.String"/> <parameter name="vlPregnancy" class="java.lang.String"/> <parameter name="vlSuckle" class="java.lang.String"/> + <parameter name="releasedate" class="java.lang.String"/> <queryString> <![CDATA[]]> </queryString> @@ -44,7 +45,7 @@ <detail> <band height="75" splitType="Stretch"> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="71" y="15" width="83" height="18" forecolor="#000000" backcolor="#FFFFFF"/> + <reportElement key="textField" x="71" y="18" width="83" height="13" forecolor="#000000" backcolor="#FFFFFF" uuid="ab1feb68-bee9-494c-9370-c3ee7910cd19"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -52,12 +53,12 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{birth_date}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{birth_date}]]></textFieldExpression> </textField> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="32" y="31" width="27" height="18" forecolor="#000000" backcolor="#FFFFFF"/> + <reportElement key="textField" x="195" y="19" width="27" height="18" forecolor="#000000" backcolor="#FFFFFF" uuid="c344d132-6699-4743-b4d0-03e630385607"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -65,12 +66,12 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{age}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{age}]]></textFieldExpression> </textField> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="119" y="31" width="16" height="18" forecolor="#000000" backcolor="#FFFFFF"/> + <reportElement key="textField" x="411" y="1" width="26" height="18" forecolor="#000000" backcolor="#FFFFFF" uuid="f242d755-eff9-4167-bbaa-5adf236727f4"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -78,12 +79,12 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{gender}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{gender}]]></textFieldExpression> </textField> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="255" y="36" width="71" height="18" forecolor="#000000" backcolor="#FFFFFF"> + <reportElement key="textField" x="246" y="38" width="83" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="89cb11d8-01ea-4727-be5d-a6103dc1978f"> <printWhenExpression><![CDATA[$P{receptiondate}!= ""]]></printWhenExpression> </reportElement> <box> @@ -93,12 +94,12 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{receptiondate}.substring(0,10)]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{receptiondate}]]></textFieldExpression> </textField> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" mode="Transparent" x="371" y="0" width="178" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF"/> + <reportElement key="textField" mode="Transparent" x="282" y="1" width="92" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="af0eb502-72e4-4760-8b54-7f702186bd1f"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -106,15 +107,15 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="11" isBold="true"/> + <font size="10" isBold="true"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{labNo}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{labNo}]]></textFieldExpression> </textField> <rectangle> - <reportElement key="rectangle-1" x="328" y="18" width="223" height="53" backcolor="#F8F8F8"/> + <reportElement key="rectangle-1" x="328" y="31" width="223" height="40" backcolor="#F8F8F8" uuid="c68d91ea-5d42-4f65-91d3-70e5a21ead88"/> </rectangle> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="353" y="37" width="196" height="17" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF"/> + <reportElement key="textField" x="353" y="45" width="196" height="13" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="68c09256-086e-453d-bc6d-1d4cde073879"/> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -124,10 +125,10 @@ <textElement> <font size="8" isBold="true"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{orgname}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{orgname}]]></textFieldExpression> </textField> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="401" y="19" width="151" height="17" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF"> + <reportElement key="textField" x="402" y="31" width="151" height="14" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="6d14d22e-1160-4cd3-b917-4b9e6e1ecad9"> <printWhenExpression><![CDATA[$P{showDoctor}]]></printWhenExpression> </reportElement> <box> @@ -139,64 +140,64 @@ <textElement> <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{doctor}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{doctor}]]></textFieldExpression> </textField> <textField isBlankWhenNull="false"> - <reportElement key="textField-3" x="62" y="0" width="263" height="18" isPrintWhenDetailOverflows="true"/> + <reportElement key="textField-3" x="58" y="0" width="162" height="18" isPrintWhenDetailOverflows="true" uuid="05246157-793a-4bd7-a7b4-c6840026b2f5"/> <textElement> <font size="10" isBold="true"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{subjectNumber}]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{subjectNumber}]]></textFieldExpression> </textField> <staticText> - <reportElement key="staticText-1" x="328" y="37" width="29" height="18" isPrintWhenDetailOverflows="true"/> + <reportElement key="staticText-1" x="329" y="45" width="29" height="14" isPrintWhenDetailOverflows="true" uuid="8310b604-f59c-45cf-9b4c-24927ea61d43"/> <textElement> <font size="9" isBold="true"/> </textElement> <text><![CDATA[Site:]]></text> </staticText> <staticText> - <reportElement key="staticText-2" x="1" y="0" width="61" height="18"/> + <reportElement key="staticText-2" x="0" y="0" width="58" height="18" uuid="a228506a-2568-4d9d-8f9d-0b152a38e562"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Sujetno: ]]></text> </staticText> <staticText> - <reportElement key="staticText-3" x="1" y="15" width="81" height="18" isPrintWhenDetailOverflows="true"/> + <reportElement key="staticText-3" x="1" y="17" width="81" height="13" isPrintWhenDetailOverflows="true" uuid="51818d39-ff64-48be-844d-3bdf5aec0333"/> <textElement> <font size="10" isBold="true"/> </textElement> <text><![CDATA[Date Naiss.:]]></text> </staticText> <staticText> - <reportElement key="staticText-4" x="3" y="31" width="29" height="18"/> - <textElement> + <reportElement key="staticText-4" x="166" y="18" width="29" height="13" uuid="d6b8f9b7-78b8-4d50-bb50-9af82f76265e"/> + <textElement textAlignment="Right"> <font isBold="true"/> </textElement> <text><![CDATA[Age:]]></text> </staticText> <staticText> - <reportElement key="staticText-5" x="85" y="31" width="34" height="18"/> + <reportElement key="staticText-5" x="377" y="1" width="34" height="18" uuid="b0c21a9a-dede-47d7-abc3-28da423ccf9d"/> <textElement> <font isBold="true"/> </textElement> <text><![CDATA[Sexe:]]></text> </staticText> <staticText> - <reportElement key="staticText-6" x="328" y="0" width="41" height="18"/> - <textElement> + <reportElement key="staticText-6" x="240" y="1" width="41" height="18" uuid="05940b56-0a2f-48ea-9c34-ad74002848eb"/> + <textElement textAlignment="Right"> <font size="10" isBold="true"/> </textElement> <text><![CDATA[Labno:]]></text> </staticText> <staticText> - <reportElement key="staticText-7" x="178" y="18" width="75" height="18"/> + <reportElement key="staticText-7" x="138" y="54" width="104" height="18" isPrintWhenDetailOverflows="true" uuid="2d08cb70-a9d3-49ec-9235-8a4d8368fc84"/> <textElement textAlignment="Right"/> - <text><![CDATA[Date de Prél.:]]></text> + <text><![CDATA[Date de validation:]]></text> </staticText> <staticText> - <reportElement key="staticText-8" x="328" y="19" width="73" height="17" isPrintWhenDetailOverflows="true"> + <reportElement key="staticText-8" x="329" y="31" width="73" height="14" isPrintWhenDetailOverflows="true" uuid="4dfa1d90-25bb-4ef9-ba6e-749faa827e83"> <printWhenExpression><![CDATA[$P{showDoctor}]]></printWhenExpression> </reportElement> <textElement> @@ -205,15 +206,15 @@ <text><![CDATA[Prescripteur:]]></text> </staticText> <staticText> - <reportElement key="staticText-7" x="150" y="36" width="105" height="18"> + <reportElement key="staticText-7" x="137" y="37" width="108" height="18" isPrintWhenDetailOverflows="true" uuid="cb0d1eb9-22b4-4997-8e00-e07c8d529d4b"> <printWhenExpression><![CDATA[$P{receptiondate} != ""]]></printWhenExpression> </reportElement> <textElement textAlignment="Right"/> <text><![CDATA[Date de Réception:]]></text> </staticText> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="254" y="18" width="71" height="18" forecolor="#000000" backcolor="#FFFFFF"> - <printWhenExpression><![CDATA[$P{collectiondate}!= ""]]></printWhenExpression> + <reportElement key="textField" x="244" y="55" width="85" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="54139f63-4581-484d-8d96-682145f026cb"> + <printWhenExpression><![CDATA[$P{releasedate}!= ""]]></printWhenExpression> </reportElement> <box> <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> @@ -222,19 +223,19 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{collectiondate}.substring(0,10)]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{releasedate}]]></textFieldExpression> </textField> <staticText> - <reportElement key="staticText-1" x="328" y="55" width="62" height="16" isPrintWhenDetailOverflows="true"/> + <reportElement key="staticText-1" x="329" y="58" width="62" height="13" isPrintWhenDetailOverflows="true" uuid="3a2eeb20-4fed-4f9c-bbd3-12f3bd54f11e"/> <textElement> <font size="9" isBold="true"/> </textElement> <text><![CDATA[Adresse:]]></text> </staticText> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField-5" x="255" y="54" width="70" height="18" forecolor="#000000" backcolor="#FFFFFF"> + <reportElement key="textField-5" x="106" y="55" width="94" height="14" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="5655432a-0b96-4b0b-b293-4f66dae6d8eb"> <printWhenExpression><![CDATA[$P{compleationdate}!= ""]]></printWhenExpression> </reportElement> <box> @@ -244,17 +245,16 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$P{compleationdate}.substring(0,10)]]></textFieldExpression> + <textFieldExpression><![CDATA[$P{compleationdate}]]></textFieldExpression> </textField> <staticText> - <reportElement x="135" y="54" width="120" height="18"/> - <textElement textAlignment="Right"/> + <reportElement x="0" y="55" width="106" height="15" isPrintWhenDetailOverflows="true" uuid="0349da03-d721-47ee-9206-f159f64c736a"/> <text><![CDATA[Date de Réalisation :]]></text> </staticText> <staticText> - <reportElement key="staticText-5" x="3" y="46" width="73" height="13" isPrintWhenDetailOverflows="true"> + <reportElement key="staticText-5" x="449" y="1" width="73" height="18" isPrintWhenDetailOverflows="true" uuid="cf592af6-a238-44d9-aca3-737d6c99111a"> <printWhenExpression><![CDATA[$P{gender}.equalsIgnoreCase("F")]]></printWhenExpression> </reportElement> <textElement> @@ -263,7 +263,7 @@ <text><![CDATA[Grossesse: ]]></text> </staticText> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="72" y="46" width="47" height="13" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF"> + <reportElement key="textField" x="522" y="1" width="25" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="8ca67d8e-ae8e-4ff3-9ce6-8301798a3efb"> <printWhenExpression><![CDATA[$P{gender}.equalsIgnoreCase("F")]]></printWhenExpression> </reportElement> <box> @@ -273,12 +273,12 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[($P{vlPregnancy}.isEmpty() || $P{vlPregnancy}.isEmpty())?" ":$P{vlPregnancy}.split("=")[1] ]]></textFieldExpression> + <textFieldExpression><![CDATA[($P{vlPregnancy}.isEmpty() || $P{vlPregnancy}.isEmpty())?" ":$P{vlPregnancy}.split("=")[1]]]></textFieldExpression> </textField> <staticText> - <reportElement key="staticText-5" x="3" y="58" width="73" height="13" isPrintWhenDetailOverflows="true"> + <reportElement key="staticText-5" x="242" y="19" width="73" height="13" isPrintWhenDetailOverflows="true" uuid="d89a5346-ebbd-4477-8046-f279e1dc5b3b"> <printWhenExpression><![CDATA[$P{gender}.equalsIgnoreCase("F")]]></printWhenExpression> </reportElement> <textElement> @@ -287,7 +287,7 @@ <text><![CDATA[Allaitement:]]></text> </staticText> <textField pattern="" isBlankWhenNull="true"> - <reportElement key="textField" x="72" y="58" width="47" height="13" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF"> + <reportElement key="textField" x="315" y="18" width="47" height="13" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="5251a03e-bc47-4615-95af-623a5bb43ec5"> <printWhenExpression><![CDATA[$P{gender}.equalsIgnoreCase("F")]]></printWhenExpression> </reportElement> <box> @@ -297,10 +297,29 @@ <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> </box> <textElement> - <font size="10"/> + <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[($P{vlSuckle}.isEmpty() || $P{vlSuckle}.isEmpty())?" ":$P{vlSuckle}.split("=")[1] ]]></textFieldExpression> + <textFieldExpression><![CDATA[($P{vlSuckle}.isEmpty() || $P{vlSuckle}.isEmpty())?" ":$P{vlSuckle}.split("=")[1]]]></textFieldExpression> </textField> + <textField pattern="" isBlankWhenNull="true"> + <reportElement key="textField" x="73" y="38" width="96" height="18" isPrintWhenDetailOverflows="true" forecolor="#000000" backcolor="#FFFFFF" uuid="9871ebf7-f1ba-4132-8712-04a11e8331f0"> + <printWhenExpression><![CDATA[$P{collectiondate}!= ""]]></printWhenExpression> + </reportElement> + <box> + <topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> + <leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> + <bottomPen lineWidth="0.0" lineColor="#000000"/> + <rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$P{collectiondate}]]></textFieldExpression> + </textField> + <staticText> + <reportElement key="staticText-7" x="0" y="37" width="70" height="18" isPrintWhenDetailOverflows="true" uuid="c198a8a4-3c24-4a7f-a40e-1cf83f92c4b4"/> + <text><![CDATA[Date de Prél.:]]></text> + </staticText> </band> </detail> <columnFooter> diff --git a/src/main/resources/reports/Patient_VL_Version_Nationale.jasper b/src/main/resources/reports/Patient_VL_Version_Nationale.jasper index d532b0b2de..d345564200 100644 Binary files a/src/main/resources/reports/Patient_VL_Version_Nationale.jasper and b/src/main/resources/reports/Patient_VL_Version_Nationale.jasper differ diff --git a/src/main/resources/reports/Patient_VL_Version_Nationale.jrxml b/src/main/resources/reports/Patient_VL_Version_Nationale.jrxml index 017b996103..ce354166e9 100644 --- a/src/main/resources/reports/Patient_VL_Version_Nationale.jrxml +++ b/src/main/resources/reports/Patient_VL_Version_Nationale.jrxml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> -<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Patient_VL_Version_Nationale" pageWidth="612" pageHeight="862" whenNoDataType="AllSectionsNoDetail" columnWidth="552" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20"> +<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Patient_VL_Version_Nationale" pageWidth="612" pageHeight="862" whenNoDataType="AllSectionsNoDetail" columnWidth="552" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" uuid="646bd21b-e007-4c57-b51d-b568f02b8eed"> <property name="ireport.scriptlethandling" value="0"/> <property name="ireport.encoding" value="UTF-8"/> <property name="ireport.zoom" value="1.5"/> <property name="ireport.x" value="0"/> - <property name="ireport.y" value="0"/> + <property name="ireport.y" value="1479"/> <import value="net.sf.jasperreports.engine.*"/> <import value="java.util.*"/> <import value="net.sf.jasperreports.engine.data.*"/> @@ -24,6 +24,7 @@ <parameter name="imagesPath" class="java.lang.String" isForPrompting="false"/> <parameter name="vlPregnancy" class="java.lang.String"/> <parameter name="vlSuckle" class="java.lang.String"/> + <parameter name="releasedate" class="java.lang.String"/> <queryString> <![CDATA[]]> </queryString> @@ -49,6 +50,7 @@ <field name="vlPregnancy" class="java.lang.String"/> <field name="sampleTypeName" class="java.lang.String"/> <field name="vlSuckle" class="java.lang.String"/> + <field name="releasedate" class="java.lang.String"/> <background> <band splitType="Stretch"/> </background> @@ -58,35 +60,35 @@ <pageHeader> <band height="207" splitType="Stretch"> <subreport> - <reportElement x="0" y="135" width="552" height="69"/> + <reportElement x="0" y="135" width="552" height="69" uuid="36ed7880-d1ab-466b-b5c1-61aad4f7b21a"/> <subreportParameter name="accession_number"/> - <subreportParameter name="birth_date"> - <subreportParameterExpression><![CDATA[$F{birth_date}]]></subreportParameterExpression> - </subreportParameter> - <subreportParameter name="doctor"> - <subreportParameterExpression><![CDATA[$F{doctor}]]></subreportParameterExpression> - </subreportParameter> <subreportParameter name="subjectNumber"> <subreportParameterExpression><![CDATA[$F{subjectno}==null ? $F{sitesubjectno}:$F{subjectno}]]></subreportParameterExpression> </subreportParameter> - <subreportParameter name="compleationdate"> - <subreportParameterExpression><![CDATA[$F{compleationdate}]]></subreportParameterExpression> + <subreportParameter name="birth_date"> + <subreportParameterExpression><![CDATA[$F{birth_date}]]></subreportParameterExpression> </subreportParameter> <subreportParameter name="orgname"> <subreportParameterExpression><![CDATA[$F{servicename}]]></subreportParameterExpression> </subreportParameter> + <subreportParameter name="compleationdate"> + <subreportParameterExpression><![CDATA[$F{compleationdate}]]></subreportParameterExpression> + </subreportParameter> <subreportParameter name="age"> <subreportParameterExpression><![CDATA[$F{age}]]></subreportParameterExpression> </subreportParameter> - <subreportParameter name="vlPregnancy"> - <subreportParameterExpression><![CDATA[$F{vlPregnancy}]]></subreportParameterExpression> - </subreportParameter> <subreportParameter name="labNo"> <subreportParameterExpression><![CDATA[$F{accession_number}]]></subreportParameterExpression> </subreportParameter> + <subreportParameter name="vlPregnancy"> + <subreportParameterExpression><![CDATA[$F{vlPregnancy}]]></subreportParameterExpression> + </subreportParameter> <subreportParameter name="gender"> <subreportParameterExpression><![CDATA[$F{gender}]]></subreportParameterExpression> </subreportParameter> + <subreportParameter name="releasedate"> + <subreportParameterExpression><![CDATA[$F{releasedate}]]></subreportParameterExpression> + </subreportParameter> <subreportParameter name="collectiondate"> <subreportParameterExpression><![CDATA[$F{collectiondate}]]></subreportParameterExpression> </subreportParameter> @@ -96,17 +98,20 @@ <subreportParameter name="vlSuckle"> <subreportParameterExpression><![CDATA[$F{vlSuckle}]]></subreportParameterExpression> </subreportParameter> + <subreportParameter name="doctor"> + <subreportParameterExpression><![CDATA[$F{doctor}]]></subreportParameterExpression> + </subreportParameter> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource()]]></dataSourceExpression> - <subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "Patient_ARV_Followup_patient_info.jasper"]]></subreportExpression> + <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "Patient_ARV_Followup_patient_info.jasper"]]></subreportExpression> </subreport> <line> - <reportElement x="0" y="134" width="552" height="1"/> + <reportElement x="0" y="134" width="552" height="1" uuid="a5866634-e37d-4b10-9b77-6a409663d27f"/> <graphicElement> <pen lineStyle="Dashed"/> </graphicElement> </line> <subreport> - <reportElement x="0" y="0" width="552" height="134"/> + <reportElement x="0" y="0" width="552" height="134" uuid="5a2b9b45-c827-4fff-856e-b0ad9c5f34e5"/> <subreportParameter name="leftHeaderImage"> <subreportParameterExpression><![CDATA[$P{leftHeaderImage}]]></subreportParameterExpression> </subreportParameter> @@ -133,10 +138,10 @@ <subreportParameterExpression><![CDATA[$P{imagesPath}]]></subreportParameterExpression> </subreportParameter> <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource()]]></dataSourceExpression> - <subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "RetroCIHeader.jasper"]]></subreportExpression> + <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "RetroCIHeader.jasper"]]></subreportExpression> </subreport> <line> - <reportElement x="0" y="205" width="552" height="1"/> + <reportElement x="0" y="205" width="552" height="1" uuid="e58a4cf9-0a7b-42ec-9384-5cf70654baf7"/> </line> </band> </pageHeader> @@ -146,235 +151,232 @@ <detail> <band height="423" splitType="Stretch"> <rectangle> - <reportElement x="156" y="223" width="196" height="20"/> + <reportElement x="156" y="223" width="196" height="20" uuid="44b6f367-5c9c-4335-9d00-c6748ecd90dc"/> </rectangle> <rectangle> - <reportElement x="352" y="223" width="155" height="20"/> + <reportElement x="352" y="223" width="155" height="20" uuid="33cd7cc7-d598-4ed9-a024-ff097ea42028"/> </rectangle> <textField isBlankWhenNull="false"> - <reportElement key="textField-20" x="129" y="113" width="351" height="15" isRemoveLineWhenBlank="true" isPrintInFirstWholeBand="true"/> + <reportElement key="textField-20" x="129" y="113" width="351" height="15" isRemoveLineWhenBlank="true" isPrintInFirstWholeBand="true" uuid="fe43c859-66e1-4d45-9153-fb2349a0c5e0"/> <textElement> <font size="9"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$F{virologyVlQaEvent} == null ? "Normal" : $F{virologyVlQaEvent}]]></textFieldExpression> + <textFieldExpression><![CDATA[$F{virologyVlQaEvent} == null ? "Normal" : $F{virologyVlQaEvent}]]></textFieldExpression> </textField> <image onErrorType="Blank"> - <reportElement x="297" y="316" width="210" height="84" isPrintInFirstWholeBand="true"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "VLSign.jpg"]]></imageExpression> + <reportElement x="297" y="316" width="210" height="84" isPrintInFirstWholeBand="true" uuid="a2de8557-9bee-48f0-9b96-02b20d7b5860"/> + <imageExpression><![CDATA[$P{imagesPath}+ "VLSign.jpg"]]></imageExpression> </image> <image onErrorType="Blank"> - <reportElement x="6" y="-1" width="229" height="62"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "ciphiaLogo.jpg"]]></imageExpression> + <reportElement x="6" y="-1" width="229" height="62" uuid="e5fd560c-715f-4de8-9c8e-495790269e9b"/> + <imageExpression><![CDATA[$P{imagesPath}+ "ciphiaLogo.jpg"]]></imageExpression> </image> <staticText> - <reportElement x="7" y="81" width="122" height="15"/> + <reportElement x="7" y="81" width="122" height="15" uuid="4594f09b-5c40-4d28-9562-f6b03e923c4f"/> <textElement> <font isUnderline="true"/> </textElement> <text><![CDATA[Type d’Examen : ]]></text> </staticText> <staticText> - <reportElement x="7" y="97" width="122" height="15"/> + <reportElement x="7" y="97" width="122" height="15" uuid="09ae0bf0-6402-4b76-89b3-45200487cac8"/> <textElement> <font isUnderline="true"/> </textElement> <text><![CDATA[Type de prélèvement :]]></text> </staticText> <staticText> - <reportElement x="15" y="315" width="282" height="106"/> - <textElement/> + <reportElement x="15" y="315" width="282" height="106" uuid="1a06e366-3dab-42ce-9502-c7875bbac539"/> <text><![CDATA[1-Si le titre HIV-1<=1000 copies/mL, suppression virale selon les directives nationales de suivi biologique des patients sous traitement antiretroviral 2-Si le titre HIV-1>1000 copies/mL, le virus est détectable au niveau du sang périphérique et le patient est dit en échec virologique. Refaire un autre prélèvement trois mois après le conseil à l’observance, pour un autre examen de charge virale pour confirmer et infirmer l’échec virologique ]]></text> </staticText> <staticText> - <reportElement x="7" y="113" width="122" height="15"/> + <reportElement x="7" y="113" width="122" height="15" uuid="25e471b1-c16e-40b5-b6fe-6e627175807d"/> <textElement> <font isUnderline="true"/> </textElement> <text><![CDATA[Etat de l’échantillon :]]></text> </staticText> <staticText> - <reportElement x="7" y="129" width="122" height="15"/> + <reportElement x="7" y="129" width="122" height="15" uuid="892e2115-40e2-4b53-b62a-b754dfd02f29"/> <textElement> <font isUnderline="true"/> </textElement> <text><![CDATA[Automate :]]></text> </staticText> <staticText> - <reportElement x="7" y="148" width="122" height="15"/> + <reportElement x="7" y="148" width="122" height="15" uuid="3efc2192-3d47-44c2-9aac-337c5556e5cd"/> <textElement> <font isUnderline="true"/> </textElement> <text><![CDATA[Trousse commerciale:]]></text> </staticText> <staticText> - <reportElement x="129" y="148" width="423" height="15" isPrintWhenDetailOverflows="true"/> + <reportElement x="129" y="148" width="423" height="15" isPrintWhenDetailOverflows="true" uuid="fa89e5e3-9cae-4db8-878d-26a28dbe6227"/> <textElement> <font size="9" isItalic="false" isStrikeThrough="false"/> </textElement> <text><![CDATA[COBAS Taqman/Ampliprep HIV-1 tests,V2.0 Quantitative (HI2CAP) / C4800 HIV-1 AMP/DET]]></text> </staticText> <staticText> - <reportElement x="129" y="129" width="421" height="15" isPrintWhenDetailOverflows="true"/> + <reportElement x="129" y="129" width="421" height="15" isPrintWhenDetailOverflows="true" uuid="61815090-2efd-486d-9466-162c3cc85012"/> <textElement> <font size="9"/> </textElement> <text><![CDATA[COBAS Ampliprep / Cobas Taqman Series / Cobas 6800 Roche Diagnostic / Cobas 4800]]></text> </staticText> <staticText> - <reportElement x="129" y="81" width="423" height="15"/> + <reportElement x="129" y="81" width="423" height="15" uuid="ad016800-a5f2-41c8-b2ba-fc245757db3f"/> <textElement> <font size="9"/> </textElement> <text><![CDATA[Recherche de l’ARN du virus HIV-1 par amplification génétique (PCR) et par quantification ]]></text> </staticText> <rectangle> - <reportElement x="5" y="223" width="157" height="20"/> + <reportElement x="5" y="223" width="157" height="20" uuid="fe618937-837c-4ff8-84d0-8e47f56b971a"/> </rectangle> <staticText> - <reportElement x="377" y="225" width="110" height="17"/> + <reportElement x="377" y="225" width="110" height="17" uuid="e5d08d15-7ebc-45af-be50-cfd31093b169"/> <textElement> <font size="12"/> </textElement> <text><![CDATA[Résultats Log /mL]]></text> </staticText> <staticText> - <reportElement x="167" y="225" width="179" height="17"/> + <reportElement x="167" y="225" width="179" height="17" uuid="9c7827b5-18cd-42c6-9068-200254d12bc9"/> <textElement> <font size="12"/> </textElement> <text><![CDATA[Résultats nombre de copies /mL]]></text> </staticText> <rectangle> - <reportElement x="352" y="243" width="155" height="20"/> + <reportElement x="352" y="243" width="155" height="20" uuid="c7209a13-128c-4e7e-9025-5dfaf5ffcb63"/> </rectangle> <rectangle> - <reportElement x="162" y="243" width="190" height="20"/> + <reportElement x="162" y="243" width="190" height="20" uuid="645320b8-555d-4805-9816-588002701073"/> </rectangle> <textField> - <reportElement x="377" y="244" width="110" height="18"/> + <reportElement x="377" y="244" width="110" height="18" uuid="3760faa7-5c1e-4204-9ac1-00949c7fddec"/> <textElement verticalAlignment="Top"> <font size="12"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$F{ampli2lo}==null ? "X" : $F{ampli2lo}]]></textFieldExpression> + <textFieldExpression><![CDATA[$F{ampli2lo}==null ? "X" : $F{ampli2lo}]]></textFieldExpression> </textField> <staticText> - <reportElement x="19" y="225" width="100" height="18"/> + <reportElement x="19" y="225" width="100" height="18" uuid="564dda6b-2bd5-4dc6-9675-a667059b80c1"/> <textElement> <font size="12"/> </textElement> <text><![CDATA[Virologie]]></text> </staticText> <rectangle> - <reportElement x="5" y="243" width="157" height="20"/> + <reportElement x="5" y="243" width="157" height="20" uuid="41789650-078a-425d-aedd-e9b6a7f1cd4f"/> </rectangle> <textField> - <reportElement x="167" y="244" width="179" height="18"/> + <reportElement x="167" y="244" width="179" height="18" uuid="7158ffb6-ee79-4ef9-94f8-0a8cbf293a46"/> <textElement textAlignment="Center" verticalAlignment="Top"> <font size="12"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$F{ampli2}==null ? "X" : $F{ampli2}]]></textFieldExpression> + <textFieldExpression><![CDATA[$F{ampli2}==null ? "X" : $F{ampli2}]]></textFieldExpression> </textField> <image onErrorType="Blank"> - <reportElement x="247" y="0" width="260" height="24"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "VL_LaboRef.jpg"]]></imageExpression> + <reportElement x="247" y="0" width="260" height="24" uuid="f86bf41d-3c3b-4588-856b-bdbffafb5bdd"/> + <imageExpression><![CDATA[$P{imagesPath}+ "VL_LaboRef.jpg"]]></imageExpression> </image> <image> - <reportElement x="5" y="56" width="271" height="20"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "EXAMEN_VL.jpg"]]></imageExpression> + <reportElement x="5" y="56" width="271" height="20" uuid="73b2a83d-3f87-4bb9-846e-47a3d98af781"/> + <imageExpression><![CDATA[$P{imagesPath}+ "EXAMEN_VL.jpg"]]></imageExpression> </image> <image> - <reportElement x="5" y="201" width="114" height="20"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "RESULTATS.jpg"]]></imageExpression> + <reportElement x="5" y="201" width="114" height="20" uuid="2f6dacdd-1c7d-47d4-8605-338ac14f1622"/> + <imageExpression><![CDATA[$P{imagesPath}+ "RESULTATS.jpg"]]></imageExpression> </image> <image> - <reportElement x="5" y="293" width="189" height="20"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "INTERPRETATIONS.jpg"]]></imageExpression> + <reportElement x="5" y="293" width="189" height="20" uuid="379b1764-0572-4467-9cf4-8aed32cc3446"/> + <imageExpression><![CDATA[$P{imagesPath}+ "INTERPRETATIONS.jpg"]]></imageExpression> </image> <staticText> - <reportElement x="129" y="163" width="423" height="13" isPrintWhenDetailOverflows="true"/> + <reportElement x="129" y="163" width="423" height="13" isPrintWhenDetailOverflows="true" uuid="7c54781d-65ef-442e-bbdb-75a092189adf"/> <textElement> <font size="9" isItalic="false" isStrikeThrough="false"/> </textElement> <text><![CDATA[COBAS 6800/8800 HIV-1 P/N]]></text> </staticText> <textField> - <reportElement x="18" y="245" width="100" height="18"/> + <reportElement x="18" y="245" width="100" height="18" uuid="b721c16a-eaef-4657-bf8f-7cc8bd360113"/> <textElement> <font size="12" isBold="true"/> </textElement> - <textFieldExpression class="java.lang.String"><![CDATA[$F{vih}]]></textFieldExpression> + <textFieldExpression><![CDATA[$F{vih}]]></textFieldExpression> </textField> <textField> - <reportElement x="130" y="96" width="354" height="15"/> - <textElement/> - <textFieldExpression class="java.lang.String"><![CDATA[$F{sampleTypeName}]]></textFieldExpression> + <reportElement x="130" y="96" width="354" height="15" uuid="b14c2c29-949b-4f15-84be-c7c6b1b78b00"/> + <textFieldExpression><![CDATA[$F{sampleTypeName}]]></textFieldExpression> </textField> </band> <band height="472"> <printWhenExpression><![CDATA[$F{virologyVlQaEvent}!=null]]></printWhenExpression> <staticText> - <reportElement x="0" y="80" width="552" height="20"/> + <reportElement x="0" y="80" width="552" height="20" uuid="26550431-fcdf-465e-af13-6cfee8071cc4"/> <textElement textAlignment="Center"> <font size="14" isBold="true"/> </textElement> <text><![CDATA[RAPPORT DE NON-CONFORMITE CLIENT]]></text> </staticText> <rectangle> - <reportElement x="1" y="106" width="170" height="40"/> + <reportElement x="1" y="106" width="170" height="40" uuid="2a012b58-6fac-429a-bbf4-497608eaed26"/> </rectangle> <staticText> - <reportElement x="11" y="112" width="157" height="34"/> + <reportElement x="11" y="112" width="157" height="34" uuid="34ed2871-892f-404d-baa8-d69b3305819b"/> <textElement textAlignment="Center"> <font size="12" isBold="true"/> </textElement> <text><![CDATA[MOTIF DU REFUS]]></text> </staticText> <rectangle> - <reportElement x="171" y="106" width="381" height="20"/> + <reportElement x="171" y="106" width="381" height="20" uuid="2cc890d5-551c-4c4a-ab1d-18b33a3494ce"/> </rectangle> <staticText> - <reportElement x="179" y="105" width="118" height="20"/> + <reportElement x="179" y="105" width="118" height="20" uuid="c1dffa7f-73a8-434b-86b0-f34ccbcf074f"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Echantillon en tube : ]]></text> </staticText> <staticText> - <reportElement x="302" y="105" width="241" height="20"/> - <textElement/> + <reportElement x="302" y="105" width="241" height="20" uuid="963c8414-f450-4e20-b6e4-342c0bc68e66"/> <text><![CDATA[Type de tube/Type d’échantillon]]></text> </staticText> <rectangle> - <reportElement x="171" y="126" width="188" height="20"/> + <reportElement x="171" y="126" width="188" height="20" uuid="70ad1b89-c66e-47f7-a901-54ace3a01bdb"/> </rectangle> <staticText> - <reportElement x="171" y="127" width="186" height="19"/> + <reportElement x="171" y="127" width="186" height="19" uuid="4d617341-7df8-44ee-93a7-412378918953"/> <textElement textAlignment="Center"/> <text><![CDATA[Tube EDTA/Sang total/Plasma]]></text> </staticText> <rectangle> - <reportElement x="359" y="126" width="193" height="20"/> + <reportElement x="359" y="126" width="193" height="20" uuid="721e11c7-7268-42f5-be27-0c8ad5f4466f"/> </rectangle> <staticText> - <reportElement x="359" y="127" width="191" height="20"/> + <reportElement x="359" y="127" width="191" height="20" uuid="220dad3c-b403-4cb8-9de7-ca65edefbb9c"/> <textElement textAlignment="Center"/> <text><![CDATA[Tube Sec/ Sérum ]]></text> </staticText> <rectangle> - <reportElement x="1" y="146" width="551" height="13"/> + <reportElement x="1" y="146" width="551" height="13" uuid="26eb1345-523e-4ad6-a1e8-9a363407ce1e"/> </rectangle> <staticText> - <reportElement x="5" y="146" width="165" height="13"/> + <reportElement x="5" y="146" width="165" height="13" uuid="b20c0a85-8b10-40cd-a00b-9c01bad8411d"/> <textElement> <font fontName="Arial"/> </textElement> <text><![CDATA[Echantillon Coagulé]]></text> </staticText> <staticText> - <reportElement x="173" y="146" width="183" height="13"> + <reportElement x="173" y="146" width="183" height="13" uuid="ec76e216-eac0-446e-8c32-9d08262d6b0a"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.coagulated"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.coagulated"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.coagulated"))]]></printWhenExpression> @@ -385,7 +387,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="146" width="183" height="13"> + <reportElement x="361" y="146" width="183" height="13" uuid="cdd04f1d-30df-4fcf-b503-c989a49ba67e"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.coagulated"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.coagulated"))]]></printWhenExpression> </reportElement> @@ -395,15 +397,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="159" width="551" height="13"/> + <reportElement x="1" y="159" width="551" height="13" uuid="34bd8972-0f70-4e48-85bb-8fdbf550bb11"/> </rectangle> <staticText> - <reportElement x="5" y="159" width="165" height="13"/> - <textElement/> + <reportElement x="5" y="159" width="165" height="13" uuid="53d1c863-cc7e-46f9-a0f1-71d6a6fbc9fa"/> <text><![CDATA[Echantillon Insuffisant]]></text> </staticText> <staticText> - <reportElement x="173" y="159" width="183" height="13"> + <reportElement x="173" y="159" width="183" height="13" uuid="a59052f3-5fc8-40ba-b149-43fa2d5b43dc"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.insufficient"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.insufficient"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.insufficient"))]]></printWhenExpression> @@ -414,7 +415,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement mode="Transparent" x="361" y="159" width="183" height="13"> + <reportElement mode="Transparent" x="361" y="159" width="183" height="13" uuid="9444f686-70a9-43d4-a4d7-371ef12e4018"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.insufficient"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.insufficient"))]]></printWhenExpression> </reportElement> @@ -424,15 +425,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="172" width="551" height="13"/> + <reportElement x="1" y="172" width="551" height="13" uuid="dbec1fab-c4ca-4e1f-88a7-a292a789aaba"/> </rectangle> <staticText> - <reportElement x="5" y="172" width="165" height="13"/> - <textElement/> + <reportElement x="5" y="172" width="165" height="13" uuid="25ae7a24-481e-4ca8-97c8-6ebbb94e5d14"/> <text><![CDATA[Echantillon Hémolysé]]></text> </staticText> <staticText> - <reportElement x="173" y="172" width="183" height="13"> + <reportElement x="173" y="172" width="183" height="13" uuid="9792c9c3-1f94-40ce-9f90-b89a908f3106"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.hemolytic"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.hemolytic"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.hemolytic"))]]></printWhenExpression> @@ -443,7 +443,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="172" width="183" height="13"> + <reportElement x="361" y="172" width="183" height="13" uuid="4551ba74-a6c9-4f11-aff7-f74b4634503e"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.hemolytic"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.hemolytic"))]]></printWhenExpression> </reportElement> @@ -453,15 +453,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="185" width="551" height="13"/> + <reportElement x="1" y="185" width="551" height="13" uuid="795aa6b9-1379-46ff-8fd8-f3493b5e33e4"/> </rectangle> <staticText> - <reportElement x="5" y="185" width="164" height="13"/> - <textElement/> + <reportElement x="5" y="185" width="164" height="13" uuid="e0c7cec9-ece5-43a0-a4e5-7949e519b7ec"/> <text><![CDATA[Echantillon lactescent]]></text> </staticText> <staticText> - <reportElement x="173" y="185" width="183" height="13"> + <reportElement x="173" y="185" width="183" height="13" uuid="712d96d5-0c83-4bf9-9f62-c9159587126f"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.Sample_LA"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.Sample_LA"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.Sample_LA"))]]></printWhenExpression> @@ -472,7 +471,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="185" width="183" height="13"> + <reportElement x="361" y="185" width="183" height="13" uuid="1cb5e066-0a6a-47cc-87a0-7f0336a56010"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.Sample_LA"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.Sample_LA"))]]></printWhenExpression> </reportElement> @@ -482,15 +481,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="198" width="551" height="13"/> + <reportElement x="1" y="198" width="551" height="13" uuid="9b49f2c9-3459-4483-8b20-dec08dce15db"/> </rectangle> <staticText> - <reportElement x="5" y="198" width="164" height="13"/> - <textElement/> + <reportElement x="5" y="198" width="164" height="13" uuid="1cbda379-46a0-4354-86bb-3988e80bdfdf"/> <text><![CDATA[Echantillon opalescent]]></text> </staticText> <staticText> - <reportElement x="173" y="198" width="183" height="13"> + <reportElement x="173" y="198" width="183" height="13" uuid="6696152e-85e7-4e56-ae03-87dd62f29628"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.Sample_OP"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.Sample_OP"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.Sample_OP"))]]></printWhenExpression> @@ -501,7 +499,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="198" width="183" height="13"> + <reportElement x="361" y="198" width="183" height="13" uuid="aff54b23-df4c-45b6-91df-429962f518ee"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.Sample_OP"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.Sample_OP"))]]></printWhenExpression> </reportElement> @@ -511,15 +509,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="211" width="551" height="13"/> + <reportElement x="1" y="211" width="551" height="13" uuid="8757b13f-8872-493d-a579-17e69725e09e"/> </rectangle> <staticText> - <reportElement x="5" y="211" width="164" height="13"/> - <textElement/> + <reportElement x="5" y="211" width="164" height="13" uuid="1a0c8adf-81e6-4f8c-96ed-6855490c60cc"/> <text><![CDATA[Echantillon mal ou non étiqueté]]></text> </staticText> <staticText> - <reportElement x="173" y="211" width="183" height="13"> + <reportElement x="173" y="211" width="183" height="13" uuid="c2357798-427b-4d82-9096-cec7b4321bf2"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.mislabled"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.mislabled"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.mislabled"))]]></printWhenExpression> @@ -530,7 +527,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="211" width="183" height="13"> + <reportElement x="361" y="211" width="183" height="13" uuid="a53e86a0-8bfa-491b-a982-050a1e1309e7"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.mislabled"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.mislabled"))]]></printWhenExpression> </reportElement> @@ -540,15 +537,14 @@ <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="1" y="224" width="551" height="13"/> + <reportElement x="1" y="224" width="551" height="13" uuid="ce3a7268-a730-4714-a52c-630634e7eafa"/> </rectangle> <staticText> - <reportElement x="5" y="224" width="166" height="13"/> - <textElement/> + <reportElement x="5" y="224" width="166" height="13" uuid="51334d98-3a4c-452c-938b-9455946d36ba"/> <text><![CDATA[Elution du disque DBS impossible]]></text> </staticText> <staticText> - <reportElement x="173" y="224" width="183" height="13"> + <reportElement x="173" y="224" width="183" height="13" uuid="d13d018b-c425-47e8-899d-ec2932623a33"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.edtaTube:qa_event.DBS_DI"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Sang:qa_event.DBS_DI"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Plasma:qa_event.DBS_DI"))]]></printWhenExpression> @@ -559,7 +555,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="361" y="224" width="183" height="13"> + <reportElement x="361" y="224" width="183" height="13" uuid="b196cf24-7288-48c5-99ec-c044355a8246"> <printWhenExpression><![CDATA[($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.dryTube:qa_event.DBS_DI"))|| ($F{allQaEvents}!=null && $F{allQaEvents}.contains("sample.type.Serum:qa_event.DBS_DI"))]]></printWhenExpression> </reportElement> @@ -569,235 +565,216 @@ <text><![CDATA[X]]></text> </staticText> <line> - <reportElement x="171" y="147" width="1" height="90"/> + <reportElement x="171" y="147" width="1" height="90" uuid="a6604df1-4d1e-4058-824d-027af2cbfc83"/> </line> <line> - <reportElement x="359" y="147" width="1" height="90"/> + <reportElement x="359" y="147" width="1" height="90" uuid="a1ced2af-661b-4c9d-80d9-8f564f4b356b"/> </line> <rectangle> - <reportElement x="1" y="237" width="551" height="32"/> + <reportElement x="1" y="237" width="551" height="32" uuid="e035fed8-f00b-41c8-a180-c65290a245b2"/> </rectangle> <staticText> - <reportElement x="5" y="240" width="296" height="13"/> - <textElement/> + <reportElement x="5" y="240" width="296" height="13" uuid="a95379e3-2aa5-42dd-99b2-a4132187fd14"/> <text><![CDATA[Fiche de prélèvement mal renseignée ]]></text> </staticText> <staticText> - <reportElement x="5" y="254" width="439" height="13"/> - <textElement/> + <reportElement x="5" y="254" width="439" height="13" uuid="9c779842-5f4e-45e1-bd84-20bedfe2088f"/> <text><![CDATA[Discordance d’information entre Fiche de prélèvement et Fiche démographique]]></text> </staticText> <rectangle> - <reportElement x="472" y="239" width="35" height="13"/> + <reportElement x="472" y="239" width="35" height="13" uuid="11ae0ec8-9e76-48d4-9b26-16795e231d61"/> </rectangle> <rectangle> - <reportElement x="472" y="254" width="35" height="13"/> + <reportElement x="472" y="254" width="35" height="13" uuid="de9439fb-31ca-47dd-a065-591433f1c5fa"/> </rectangle> <rectangle> - <reportElement x="1" y="269" width="551" height="32"/> + <reportElement x="1" y="269" width="551" height="32" uuid="fe0a2e85-9482-4835-87fe-8238c87551a4"/> </rectangle> <staticText> - <reportElement x="5" y="272" width="150" height="13"/> - <textElement/> + <reportElement x="5" y="272" width="150" height="13" uuid="574f9f0d-1839-4745-9b88-d01b09c85555"/> <text><![CDATA[Fiche sans Echantillon]]></text> </staticText> <rectangle> - <reportElement x="155" y="271" width="35" height="13"/> + <reportElement x="155" y="271" width="35" height="13" uuid="75120c71-8705-42d9-88dc-8aa3b5de2dc6"/> </rectangle> <staticText> - <reportElement x="5" y="286" width="149" height="13"/> - <textElement/> + <reportElement x="5" y="286" width="149" height="13" uuid="418ee7d0-0a82-45ab-8726-47278cf3018e"/> <text><![CDATA[Echantillon sans fiche ]]></text> </staticText> <rectangle> - <reportElement x="155" y="286" width="35" height="13"/> + <reportElement x="155" y="286" width="35" height="13" uuid="ffaf0e0c-b278-47f2-826d-675538e88f48"/> </rectangle> <staticText> - <reportElement x="235" y="272" width="235" height="13"/> - <textElement/> + <reportElement x="235" y="272" width="235" height="13" uuid="3a00587e-63ee-448b-836a-a9a4a016abe9"/> <text><![CDATA[Absence de l’identité du préleveur]]></text> </staticText> <rectangle> - <reportElement x="472" y="271" width="35" height="13"/> + <reportElement x="472" y="271" width="35" height="13" uuid="318e07f4-752b-432b-b708-577685ea53ec"/> </rectangle> <staticText> - <reportElement x="235" y="286" width="234" height="13"/> - <textElement/> + <reportElement x="235" y="286" width="234" height="13" uuid="11415887-d37d-4b76-8f5e-e1f360da3863"/> <text><![CDATA[Absence de l’heure du prélèvement]]></text> </staticText> <rectangle> - <reportElement x="472" y="286" width="35" height="13"/> + <reportElement x="472" y="286" width="35" height="13" uuid="f2f10863-edf7-4486-97ac-49e7fbae788f"/> </rectangle> <rectangle> - <reportElement x="1" y="301" width="551" height="32"/> + <reportElement x="1" y="301" width="551" height="32" uuid="8061631d-1fcb-40eb-88d5-6186b64e1c2f"/> </rectangle> <staticText> - <reportElement x="5" y="304" width="150" height="13"/> - <textElement/> + <reportElement x="5" y="304" width="150" height="13" uuid="e28036c6-dd89-4d29-b2d3-abbaceb23725"/> <text><![CDATA[Tube maculé de sang]]></text> </staticText> <rectangle> - <reportElement x="155" y="303" width="35" height="13"/> + <reportElement x="155" y="303" width="35" height="13" uuid="8561974e-0a60-4485-8e63-d0510adae8bb"/> </rectangle> <staticText> - <reportElement x="5" y="318" width="149" height="13"/> - <textElement/> + <reportElement x="5" y="318" width="149" height="13" uuid="a3ce97d6-fc80-4d01-ade6-a39d1e35fad8"/> <text><![CDATA[Fiche entachée de sang]]></text> </staticText> <rectangle> - <reportElement x="155" y="318" width="35" height="13"/> + <reportElement x="155" y="318" width="35" height="13" uuid="c67b8937-956d-4ea5-bfa9-d699c32224a0"/> </rectangle> <staticText> - <reportElement x="235" y="304" width="235" height="13"/> - <textElement/> + <reportElement x="235" y="304" width="235" height="13" uuid="095aae07-26ef-4853-bacf-61f15d7f4ada"/> <text><![CDATA[Echantillon pour charge virale de plus de 6h]]></text> </staticText> <rectangle> - <reportElement x="472" y="303" width="35" height="13"/> + <reportElement x="472" y="303" width="35" height="13" uuid="3efb1718-501a-43c3-9a91-60189edcac2b"/> </rectangle> <staticText> - <reportElement x="235" y="318" width="234" height="13"/> - <textElement/> + <reportElement x="235" y="318" width="234" height="13" uuid="7b46fca1-6315-43cb-a0fb-f180f5c2b5cc"/> <text><![CDATA[Erreur de tube de prélèvement]]></text> </staticText> <rectangle> - <reportElement x="472" y="318" width="35" height="13"/> + <reportElement x="472" y="318" width="35" height="13" uuid="86d1f354-aaf9-4f6a-b4b4-eed16fcf2914"/> </rectangle> <rectangle> - <reportElement x="1" y="333" width="551" height="22"/> + <reportElement x="1" y="333" width="551" height="22" uuid="b10da94f-dcba-4763-ba46-26b7a8d08b1d"/> </rectangle> <staticText> - <reportElement x="5" y="339" width="150" height="16"/> + <reportElement x="5" y="339" width="150" height="16" uuid="af78cabd-3561-456a-a588-3aaa00501074"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[DBS]]></text> </staticText> <rectangle> - <reportElement x="155" y="338" width="35" height="13"/> + <reportElement x="155" y="338" width="35" height="13" uuid="a1b89f89-2252-4f3d-bf00-8e7f93a9e906"/> </rectangle> <rectangle> - <reportElement x="1" y="355" width="551" height="38"/> + <reportElement x="1" y="355" width="551" height="38" uuid="6b4cc158-a4b1-482f-8973-870425563138"/> </rectangle> <staticText> - <reportElement x="5" y="361" width="150" height="16"/> + <reportElement x="5" y="361" width="150" height="16" uuid="76a97a68-177c-445c-97a2-7c3f29f2379c"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[AUTRES MOTIFS]]></text> </staticText> <rectangle> - <reportElement x="155" y="361" width="35" height="13"/> + <reportElement x="155" y="361" width="35" height="13" uuid="aa2869e1-4c3e-426b-809b-c9ed93f616ce"/> </rectangle> <staticText> - <reportElement x="7" y="379" width="543" height="13"/> - <textElement/> + <reportElement x="7" y="379" width="543" height="13" uuid="4c525974-5baf-422f-8d13-f1e6923a694d"/> <text><![CDATA[A décrire :…………………………………………………………………….................................................................………….]]></text> </staticText> <rectangle> - <reportElement x="1" y="435" width="551" height="34"/> + <reportElement x="1" y="435" width="551" height="34" uuid="31a2152e-38e0-4c05-bc38-8bc85ddf21c8"/> </rectangle> <staticText> - <reportElement x="5" y="435" width="85" height="16"/> + <reportElement x="5" y="435" width="85" height="16" uuid="e0e652b6-50c6-4fb5-9515-0fdafd5c1835"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[CONCLUSION :]]></text> </staticText> <staticText> - <reportElement x="5" y="450" width="195" height="16"/> + <reportElement x="5" y="450" width="195" height="16" uuid="860ac303-42bd-459c-80b6-deea9ba2c9e9"/> <textElement> <font size="11" isBold="true" isItalic="true"/> </textElement> <text><![CDATA[Prière refaire le prélèvement sur : ]]></text> </staticText> <staticText> - <reportElement x="89" y="435" width="361" height="16"/> + <reportElement x="89" y="435" width="361" height="16" uuid="fa4bce6e-d407-47d9-9467-d81fec9001af"/> <textElement> <font size="11"/> </textElement> <text><![CDATA[L’échantillon ne peut être traité ou analysé ce jour. ]]></text> </staticText> <staticText> - <reportElement x="198" y="451" width="352" height="16"/> + <reportElement x="198" y="451" width="352" height="16" uuid="902a9929-fbb1-47a9-baad-3d91fe3e427a"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Tube EDTA Tube sec Carte DBS Whatman 903]]></text> </staticText> <staticText> - <reportElement x="15" y="396" width="57" height="16"/> + <reportElement x="15" y="396" width="57" height="16" uuid="05633e9d-6d0e-45c5-affe-40e9b7861b1e"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Section:]]></text> </staticText> <staticText> - <reportElement x="77" y="396" width="36" height="16"/> - <textElement/> + <reportElement x="77" y="396" width="36" height="16" uuid="0b1b3630-5fd1-4f4d-8ad6-9f61d71a6fdf"/> <text><![CDATA[Saisie]]></text> </staticText> <rectangle> - <reportElement x="115" y="397" width="14" height="14"/> + <reportElement x="115" y="397" width="14" height="14" uuid="a651c007-3cea-4817-a8b1-980a791b1644"/> </rectangle> <staticText> - <reportElement x="147" y="396" width="62" height="16"/> - <textElement/> + <reportElement x="147" y="396" width="62" height="16" uuid="78a49747-0579-4e9d-b6ef-eb75fb38807a"/> <text><![CDATA[Réception]]></text> </staticText> <rectangle> - <reportElement x="203" y="397" width="14" height="14"/> + <reportElement x="203" y="397" width="14" height="14" uuid="e9a1acd7-de98-4ec7-b1fc-da0aff1cbac9"/> </rectangle> <staticText> - <reportElement x="238" y="396" width="56" height="16"/> - <textElement/> + <reportElement x="238" y="396" width="56" height="16" uuid="b5075746-f766-42f6-a626-ea6dab1254d2"/> <text><![CDATA[Biochimie]]></text> </staticText> <rectangle> - <reportElement x="292" y="397" width="14" height="14"/> + <reportElement x="292" y="397" width="14" height="14" uuid="d5fc8fd1-f6aa-4b2a-a0d7-2ee49e40dfec"/> </rectangle> <staticText> - <reportElement x="321" y="396" width="100" height="16"/> - <textElement/> + <reportElement x="321" y="396" width="100" height="16" uuid="14b23751-35b6-46b6-be1b-88c02936204f"/> <text><![CDATA[Immunologie(CD4) ]]></text> </staticText> <rectangle> - <reportElement x="426" y="397" width="14" height="14"/> + <reportElement x="426" y="397" width="14" height="14" uuid="bec7ab7a-0e71-4ac9-95a3-4cc086355777"/> </rectangle> <staticText> - <reportElement x="456" y="397" width="66" height="16"/> - <textElement/> + <reportElement x="456" y="397" width="66" height="16" uuid="325010b6-e5c0-4e32-a682-8d891103fb48"/> <text><![CDATA[Charge virale]]></text> </staticText> <rectangle> - <reportElement x="527" y="397" width="14" height="14"/> + <reportElement x="527" y="397" width="14" height="14" uuid="fe159ec0-d81e-4dd0-ae3b-b24f0d4ef609"/> </rectangle> <staticText> - <reportElement x="78" y="416" width="123" height="16"/> - <textElement/> + <reportElement x="78" y="416" width="123" height="16" uuid="501620dc-2f62-4d3c-a588-7a7798c06d3d"/> <text><![CDATA[Diagnostic précoce (EID) ]]></text> </staticText> <rectangle> - <reportElement x="203" y="417" width="14" height="14"/> + <reportElement x="203" y="417" width="14" height="14" uuid="f68673dc-909e-4813-95f5-72a31be2b1b6"/> </rectangle> <staticText> - <reportElement x="238" y="416" width="54" height="16"/> - <textElement/> + <reportElement x="238" y="416" width="54" height="16" uuid="9ea49ed4-da75-4b7e-8067-ebfcc9160d03"/> <text><![CDATA[Sérologie VIH]]></text> </staticText> <rectangle> - <reportElement x="292" y="417" width="14" height="14"/> + <reportElement x="292" y="417" width="14" height="14" uuid="ff58b8fe-3bcb-4067-bba5-fd283bfbd4ac"/> </rectangle> <staticText> - <reportElement x="352" y="416" width="68" height="16"/> - <textElement/> + <reportElement x="352" y="416" width="68" height="16" uuid="e716afef-160c-4968-a306-2698105877c7"/> <text><![CDATA[Hématologie]]></text> </staticText> <rectangle> - <reportElement x="426" y="417" width="14" height="14"/> + <reportElement x="426" y="417" width="14" height="14" uuid="c109c534-23c2-408b-9f09-1d7b9a7555e2"/> </rectangle> <staticText> - <reportElement x="473" y="239" width="34" height="15"> + <reportElement x="473" y="239" width="34" height="15" uuid="91184b41-140d-4c63-a309-432b2c9fe749"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.formNotCorrect")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -806,7 +783,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="473" y="254" width="34" height="15"> + <reportElement x="473" y="254" width="34" height="15" uuid="ad55303b-8980-4398-8ab1-76a51fbf3e1d"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Error_Prev_Demo")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -815,7 +792,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="156" y="271" width="34" height="15"> + <reportElement x="156" y="271" width="34" height="15" uuid="cf80b4c5-009f-4877-be24-9fec84dca65c"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.noSample")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -824,7 +801,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="156" y="286" width="34" height="15"> + <reportElement x="156" y="286" width="34" height="15" uuid="fba1be4e-dd6a-47a7-8242-bdf78b6e8cbc"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.noForm")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -833,7 +810,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="473" y="272" width="34" height="15"> + <reportElement x="473" y="272" width="34" height="15" uuid="8652468d-f5c2-4b2e-92d1-dd51345db0f9"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.No_ID_Prev")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -842,7 +819,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="473" y="287" width="34" height="15"> + <reportElement x="473" y="287" width="34" height="15" uuid="b35b9966-ecf2-4535-9080-14cfd7447f12"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.No_HR_Prev")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -851,7 +828,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="156" y="304" width="34" height="15"> + <reportElement x="156" y="304" width="34" height="15" uuid="c7ca1842-daf7-4641-b6b5-74f3ab2c5adb"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.bloodstained.tube")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -860,7 +837,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="156" y="318" width="34" height="15"> + <reportElement x="156" y="318" width="34" height="15" uuid="59e2dad4-4f46-4158-9527-e54a6bc48255"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.bloodstained.form")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -869,7 +846,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="473" y="318" width="34" height="15"> + <reportElement x="473" y="318" width="34" height="15" uuid="d8121803-a0db-4cc0-abb4-a7fa59a94276"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Error_Sample")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -878,7 +855,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="473" y="303" width="34" height="15"> + <reportElement x="473" y="303" width="34" height="15" uuid="8e7fbbfb-20cf-4359-9a90-8fc011632e74"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Sample_VL_Late")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -887,7 +864,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="527" y="399" width="14" height="12"> + <reportElement x="527" y="399" width="14" height="12" uuid="7837ff65-3ce9-42ad-8b06-519e4e96f54f"> <printWhenExpression><![CDATA[$F{virologyVlQaEvent}!=null]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -896,7 +873,7 @@ <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="203" y="399" width="14" height="12"> + <reportElement x="203" y="399" width="14" height="12" uuid="e9fbb895-9c08-48d3-83bd-888e0d2cb0f9"> <printWhenExpression><![CDATA[$F{receptionQaEvent}!=null]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -912,43 +889,48 @@ <pageFooter> <band height="143" splitType="Prevent"> <line> - <reportElement key="line-3" x="0" y="0" width="550" height="1"/> + <reportElement key="line-3" x="0" y="0" width="550" height="1" uuid="fc09d8f6-6853-4869-8663-5bef081e0b9e"/> <graphicElement> <pen lineWidth="0.75" lineStyle="Solid"/> </graphicElement> </line> <image> - <reportElement x="12" y="6" width="317" height="12"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+ "RefVal.jpg"]]></imageExpression> + <reportElement x="12" y="6" width="317" height="12" uuid="67a730c5-3d1b-4019-9f7e-a8ac55d0740b"/> + <imageExpression><![CDATA[$P{imagesPath}+ "RefVal.jpg"]]></imageExpression> </image> <staticText> - <reportElement x="10" y="88" width="534" height="19"/> + <reportElement x="10" y="88" width="534" height="19" uuid="3e429c79-24d0-47f7-a944-c10389504948"/> <textElement> <font size="10"/> </textElement> <text><![CDATA[Valeur charge virale : < LL=virus HIV-1 indétectable dans le sang périphérique]]></text> </staticText> <staticText> - <reportElement x="12" y="65" width="408" height="19"/> + <reportElement x="12" y="65" width="408" height="19" uuid="6ef822fb-4b30-4b3d-bd19-a7e5aededda0"/> <textElement> <font size="10"/> </textElement> - <text><![CDATA[Seuil de détection de la technique W/PSC : 599 copies/mL]]></text> + <text><![CDATA[Seuil de détection de la technique CV/PSC : 599 copies/mL]]></text> </staticText> <staticText> - <reportElement x="10" y="21" width="408" height="19"/> + <reportElement x="10" y="21" width="408" height="19" uuid="0e4e96a8-5fa8-45b1-ab65-384fcc9d9c5e"/> <textElement> <font size="10"/> </textElement> <text><![CDATA[Seuil de détection de la technique CV/PL : 20 copies /mL]]></text> </staticText> <staticText> - <reportElement x="10" y="43" width="408" height="19"/> + <reportElement x="10" y="43" width="408" height="19" uuid="9ec062e1-8409-4d70-a08d-a742a8728efe"/> <textElement> <font size="10"/> </textElement> <text><![CDATA[Seuil de détection de la technique CV/DBS : 400 copies /mL]]></text> </staticText> + <textField> + <reportElement x="439" y="127" width="112" height="16" isPrintWhenDetailOverflows="true" uuid="e9ccc6cc-58c2-4f88-9a5b-54397150dae9"/> + <textElement textAlignment="Right"/> + <textFieldExpression><![CDATA["Page 1 sur 1"]]></textFieldExpression> + </textField> </band> </pageFooter> <summary> diff --git a/src/main/resources/reports/RetroCI_Patient_EID.jasper b/src/main/resources/reports/RetroCI_Patient_EID.jasper index 41351f42f5..d516bbe95a 100644 Binary files a/src/main/resources/reports/RetroCI_Patient_EID.jasper and b/src/main/resources/reports/RetroCI_Patient_EID.jasper differ diff --git a/src/main/resources/reports/RetroCI_Patient_EID.jrxml b/src/main/resources/reports/RetroCI_Patient_EID.jrxml index 95b0b8323b..25e1a52be7 100644 --- a/src/main/resources/reports/RetroCI_Patient_EID.jrxml +++ b/src/main/resources/reports/RetroCI_Patient_EID.jrxml @@ -2,9 +2,9 @@ <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="RetroCI_Patient_EID" pageWidth="612" pageHeight="862" columnWidth="552" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20"> <property name="ireport.scriptlethandling" value="0"/> <property name="ireport.encoding" value="UTF-8"/> - <property name="ireport.zoom" value="1.0"/> + <property name="ireport.zoom" value="1.5"/> <property name="ireport.x" value="0"/> - <property name="ireport.y" value="205"/> + <property name="ireport.y" value="1425"/> <import value="net.sf.jasperreports.engine.*"/> <import value="java.util.*"/> <import value="net.sf.jasperreports.engine.data.*"/> @@ -300,17 +300,17 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <band height="448"> <printWhenExpression><![CDATA[$F{virologyEidQaEvent}!=null]]></printWhenExpression> <rectangle> - <reportElement x="0" y="102" width="551" height="13"/> + <reportElement x="0" y="74" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="102" width="165" height="13"/> + <reportElement x="4" y="74" width="165" height="13"/> <textElement> <font fontName="Arial"/> </textElement> <text><![CDATA[ Age de l’enfant > 18 mois]]></text> </staticText> <staticText> - <reportElement x="425" y="102" width="115" height="13"> + <reportElement x="425" y="74" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.adult")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -319,15 +319,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="115" width="551" height="13"/> + <reportElement x="0" y="87" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="115" width="230" height="13"/> + <reportElement x="4" y="87" width="230" height="13"/> <textElement/> <text><![CDATA[ Date de prélèvement au-delà d’un (1) mois]]></text> </staticText> <staticText> - <reportElement x="425" y="115" width="115" height="13"> + <reportElement x="425" y="87" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Date_1")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -336,15 +336,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="128" width="551" height="13"/> + <reportElement x="0" y="100" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="128" width="204" height="13"/> + <reportElement x="4" y="100" width="204" height="13"/> <textElement/> <text><![CDATA[ DBS: Nombre de spot rempli < 3]]></text> </staticText> <staticText> - <reportElement x="425" y="128" width="115" height="13"> + <reportElement x="425" y="100" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_3")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -353,15 +353,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="141" width="551" height="13"/> + <reportElement x="0" y="113" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="141" width="164" height="13"/> + <reportElement x="4" y="113" width="164" height="13"/> <textElement/> <text><![CDATA[ Diamètre des spots < 5mm]]></text> </staticText> <staticText> - <reportElement x="425" y="141" width="115" height="13"> + <reportElement x="425" y="113" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Diametre")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -370,15 +370,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="154" width="551" height="13"/> + <reportElement x="0" y="126" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="154" width="164" height="13"/> + <reportElement x="4" y="126" width="164" height="13"/> <textElement/> <text><![CDATA[ DBS spot de sang coagulé]]></text> </staticText> <staticText> - <reportElement x="425" y="154" width="115" height="13"> + <reportElement x="425" y="126" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_C")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -387,15 +387,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="167" width="551" height="13"/> + <reportElement x="0" y="139" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="167" width="164" height="13"/> + <reportElement x="4" y="139" width="164" height="13"/> <textElement/> <text><![CDATA[ DBS spot de sang insuffisant]]></text> </staticText> <staticText> - <reportElement x="425" y="167" width="115" height="13"> + <reportElement x="425" y="139" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_I")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -404,15 +404,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="180" width="551" height="13"/> + <reportElement x="0" y="152" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="4" y="180" width="166" height="13"/> + <reportElement x="4" y="152" width="166" height="13"/> <textElement/> <text><![CDATA[ Elution du disque DBS impossible]]></text> </staticText> <staticText> - <reportElement x="425" y="180" width="115" height="13"> + <reportElement x="425" y="152" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_DI")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -421,15 +421,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="193" width="551" height="13"/> + <reportElement x="0" y="165" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="193" width="166" height="13"/> + <reportElement x="3" y="165" width="166" height="13"/> <textElement/> <text><![CDATA[ DBS spot de sang dilué par l’alcool]]></text> </staticText> <staticText> - <reportElement x="424" y="193" width="115" height="13"> + <reportElement x="424" y="165" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_D")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -438,15 +438,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="206" width="551" height="13"/> + <reportElement x="0" y="178" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="207" width="372" height="13"/> + <reportElement x="3" y="179" width="372" height="13"/> <textElement/> <text><![CDATA[ Carte DBS sans enveloppe glassine (si plusieurs DBS dans un sachet Ziplock)]]></text> </staticText> <staticText> - <reportElement x="425" y="207" width="114" height="13"> + <reportElement x="425" y="179" width="114" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_E")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -455,15 +455,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="219" width="551" height="13"/> + <reportElement x="0" y="191" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="219" width="347" height="13"/> + <reportElement x="3" y="191" width="347" height="13"/> <textElement/> <text><![CDATA[ Carte DBS non conforme (différente du Whatman 903)]]></text> </staticText> <staticText> - <reportElement x="424" y="219" width="115" height="13"> + <reportElement x="424" y="191" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_NC")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -472,15 +472,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="232" width="551" height="13"/> + <reportElement x="0" y="204" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="232" width="166" height="13"/> + <reportElement x="3" y="204" width="166" height="13"/> <textElement/> <text><![CDATA[ DBS non identifié]]></text> </staticText> <staticText> - <reportElement x="424" y="232" width="115" height="13"> + <reportElement x="424" y="204" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_NI")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -489,15 +489,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="245" width="551" height="13"/> + <reportElement x="0" y="217" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="245" width="372" height="13"/> + <reportElement x="3" y="217" width="372" height="13"/> <textElement/> <text><![CDATA[ DBS mal identifié (Identité discordante sur DBS et fiche)]]></text> </staticText> <staticText> - <reportElement x="424" y="245" width="115" height="13"> + <reportElement x="424" y="217" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_MI")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -506,15 +506,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="258" width="551" height="13"/> + <reportElement x="0" y="230" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="258" width="166" height="13"/> + <reportElement x="3" y="230" width="166" height="13"/> <textElement/> <text><![CDATA[ DBS sans fiche]]></text> </staticText> <staticText> - <reportElement x="424" y="258" width="115" height="13"> + <reportElement x="424" y="230" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.DBS_SF")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -523,15 +523,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="271" width="551" height="13"/> + <reportElement x="0" y="243" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="271" width="288" height="13"/> + <reportElement x="3" y="243" width="288" height="13"/> <textElement/> <text><![CDATA[ Fiche de prélèvement entachée de sang]]></text> </staticText> <staticText> - <reportElement x="424" y="271" width="115" height="13"> + <reportElement x="424" y="243" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.bloodstained.form")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -540,15 +540,15 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <rectangle> - <reportElement x="0" y="284" width="551" height="13"/> + <reportElement x="0" y="256" width="551" height="13"/> </rectangle> <staticText> - <reportElement x="3" y="284" width="331" height="13"/> + <reportElement x="3" y="256" width="331" height="13"/> <textElement/> <text><![CDATA[ Fiche de prélèvement sans échantillon DBS]]></text> </staticText> <staticText> - <reportElement x="424" y="284" width="115" height="13"> + <reportElement x="424" y="256" width="115" height="13"> <printWhenExpression><![CDATA[$F{allQaEvents}!=null && $F{allQaEvents}.contains("qa_event.Fiche_no_DBS")]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"> @@ -557,204 +557,208 @@ b. Si l’enfant est sous allaitement maternel, répéter la PCR 6 semaines apr <text><![CDATA[X]]></text> </staticText> <line> - <reportElement x="391" y="103" width="1" height="194"/> + <reportElement x="391" y="75" width="1" height="194"/> </line> <rectangle> - <reportElement x="0" y="332" width="551" height="38"/> + <reportElement x="0" y="278" width="551" height="38"/> </rectangle> <staticText> - <reportElement x="4" y="338" width="150" height="16"/> + <reportElement x="4" y="284" width="150" height="16"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[AUTRES MOTIFS]]></text> </staticText> <rectangle> - <reportElement x="154" y="338" width="35" height="13"/> + <reportElement x="154" y="284" width="35" height="13"/> </rectangle> <staticText> - <reportElement x="6" y="356" width="543" height="13"/> + <reportElement x="6" y="302" width="543" height="13"/> <textElement/> <text><![CDATA[A décrire :…………………………………………………………………….................................................................………….]]></text> </staticText> <rectangle> - <reportElement x="0" y="412" width="551" height="34"/> + <reportElement x="0" y="358" width="551" height="34"/> </rectangle> <staticText> - <reportElement x="4" y="412" width="85" height="16"/> + <reportElement x="4" y="358" width="85" height="16"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[CONCLUSION :]]></text> </staticText> <staticText> - <reportElement x="4" y="427" width="195" height="16"/> + <reportElement x="4" y="373" width="195" height="16"/> <textElement> <font size="11" isBold="true" isItalic="true"/> </textElement> <text><![CDATA[Prière refaire le prélèvement sur : ]]></text> </staticText> <staticText> - <reportElement x="88" y="412" width="361" height="16"/> + <reportElement x="88" y="358" width="361" height="16"/> <textElement> <font size="11"/> </textElement> <text><![CDATA[L’échantillon ne peut être traité ou analysé ce jour. ]]></text> </staticText> <staticText> - <reportElement x="197" y="428" width="352" height="16"/> + <reportElement x="197" y="374" width="352" height="16"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Tube EDTA Tube sec Carte DBS Whatman 903]]></text> </staticText> <staticText> - <reportElement x="14" y="373" width="57" height="16"/> + <reportElement x="14" y="319" width="57" height="16"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Section:]]></text> </staticText> <staticText> - <reportElement x="76" y="373" width="36" height="16"/> + <reportElement x="76" y="319" width="36" height="16"/> <textElement/> <text><![CDATA[Saisie]]></text> </staticText> <rectangle> - <reportElement x="114" y="374" width="14" height="14"/> + <reportElement x="114" y="320" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="146" y="373" width="62" height="16"/> + <reportElement x="146" y="319" width="62" height="16"/> <textElement/> <text><![CDATA[Réception]]></text> </staticText> <rectangle> - <reportElement x="202" y="374" width="14" height="14"/> + <reportElement x="202" y="320" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="237" y="373" width="56" height="16"/> + <reportElement x="237" y="319" width="56" height="16"/> <textElement/> <text><![CDATA[Biochimie]]></text> </staticText> <rectangle> - <reportElement x="291" y="374" width="14" height="14"/> + <reportElement x="291" y="320" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="320" y="373" width="100" height="16"/> + <reportElement x="320" y="319" width="100" height="16"/> <textElement/> <text><![CDATA[Immunologie(CD4) ]]></text> </staticText> <rectangle> - <reportElement x="425" y="374" width="14" height="14"/> + <reportElement x="425" y="320" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="455" y="374" width="66" height="16"/> + <reportElement x="455" y="320" width="66" height="16"/> <textElement/> <text><![CDATA[Charge virale]]></text> </staticText> <rectangle> - <reportElement x="526" y="374" width="14" height="14"/> + <reportElement x="526" y="320" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="77" y="393" width="123" height="16"/> + <reportElement x="77" y="339" width="123" height="16"/> <textElement/> <text><![CDATA[Diagnostic précoce (EID) ]]></text> </staticText> <rectangle> - <reportElement x="202" y="394" width="14" height="14"/> + <reportElement x="202" y="340" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="204" y="395" width="11" height="13"> + <reportElement x="204" y="341" width="11" height="13"> <printWhenExpression><![CDATA[$F{virologyEidQaEvent}!=null]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"/> <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="237" y="393" width="54" height="16"/> + <reportElement x="237" y="339" width="54" height="16"/> <textElement/> <text><![CDATA[Sérologie VIH]]></text> </staticText> <rectangle> - <reportElement x="291" y="394" width="14" height="14"/> + <reportElement x="291" y="340" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="351" y="393" width="68" height="16"/> + <reportElement x="351" y="339" width="68" height="16"/> <textElement/> <text><![CDATA[Hématologie]]></text> </staticText> <rectangle> - <reportElement x="425" y="394" width="14" height="14"/> + <reportElement x="425" y="340" width="14" height="14"/> </rectangle> <rectangle> - <reportElement x="0" y="62" width="170" height="40"/> + <reportElement x="0" y="34" width="170" height="40"/> </rectangle> <rectangle> - <reportElement x="170" y="62" width="381" height="20"/> + <reportElement x="170" y="34" width="381" height="20"/> </rectangle> <rectangle> - <reportElement x="170" y="82" width="381" height="20"/> + <reportElement x="170" y="54" width="381" height="20"/> </rectangle> <staticText> - <reportElement x="178" y="61" width="118" height="20"/> + <reportElement x="178" y="33" width="118" height="20"/> <textElement> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Echantillon en tube : ]]></text> </staticText> <staticText> - <reportElement x="-1" y="36" width="552" height="20"/> + <reportElement x="-1" y="8" width="552" height="20"/> <textElement textAlignment="Center"> <font size="14" isBold="true"/> </textElement> <text><![CDATA[RAPPORT DE NON-CONFORMITE CLIENT]]></text> </staticText> <staticText> - <reportElement x="301" y="61" width="241" height="20"/> + <reportElement x="301" y="33" width="241" height="20"/> <textElement/> <text><![CDATA[Type de tube/Type d’échantillon]]></text> </staticText> <staticText> - <reportElement x="10" y="68" width="157" height="34"/> + <reportElement x="10" y="40" width="157" height="34"/> <textElement textAlignment="Center"> <font size="12" isBold="true"/> </textElement> <text><![CDATA[MOTIF DU REFUS]]></text> </staticText> <staticText> - <reportElement x="178" y="83" width="361" height="19"/> + <reportElement x="178" y="55" width="361" height="19"/> <textElement textAlignment="Center"> <font size="11" isBold="true"/> </textElement> <text><![CDATA[Carte DBS Whatman 903]]></text> </staticText> <rectangle> - <reportElement x="265" y="427" width="14" height="14"/> + <reportElement x="265" y="373" width="14" height="14"/> </rectangle> <rectangle> - <reportElement x="359" y="427" width="14" height="14"/> + <reportElement x="359" y="373" width="14" height="14"/> </rectangle> <rectangle> - <reportElement x="521" y="427" width="14" height="14"/> + <reportElement x="521" y="373" width="14" height="14"/> </rectangle> <staticText> - <reportElement x="523" y="428" width="11" height="13"/> + <reportElement x="523" y="374" width="11" height="13"/> <textElement textAlignment="Center"/> <text><![CDATA[X]]></text> </staticText> <staticText> - <reportElement x="204" y="375" width="11" height="13"> + <reportElement x="204" y="321" width="11" height="13"> <printWhenExpression><![CDATA[$F{receptionQaEvent}!=null]]></printWhenExpression> </reportElement> <textElement textAlignment="Center"/> <text><![CDATA[X]]></text> </staticText> + <image onErrorType="Blank"> + <reportElement x="4" y="5" width="337" height="12"/> + <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+"PRECAUTIONS.jpg"]]></imageExpression> + </image> </band> </detail> <columnFooter> - <band height="100" splitType="Stretch"> + <band height="90" splitType="Stretch"> <staticText> - <reportElement key="staticText-2" x="4" y="23" width="551" height="77"/> + <reportElement key="staticText-2" x="2" y="22" width="551" height="59"/> <textElement> <font isBold="true"/> </textElement> @@ -773,24 +777,24 @@ La performance de ce test a été évaluée uniquement sur HIV-1 group O et N, e <pen lineStyle="Dashed"/> </graphicElement> </line> - <image onErrorType="Blank"> - <reportElement x="4" y="5" width="337" height="12"/> - <imageExpression class="java.lang.String"><![CDATA[$P{imagesPath}+"PRECAUTIONS.jpg"]]></imageExpression> - </image> </band> </columnFooter> <pageFooter> - <band height="20" splitType="Stretch"> + <band height="30" splitType="Stretch"> <textField pattern="dd/MM/yyyy"> - <reportElement x="451" y="0" width="100" height="20"/> + <reportElement x="452" y="14" width="100" height="16"/> <textElement/> <textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression> </textField> + <textField> + <reportElement x="7" y="14" width="112" height="16" isPrintWhenDetailOverflows="true"/> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression class="java.lang.String"><![CDATA["Page 1 sur 1"]]></textFieldExpression> + </textField> </band> </pageFooter> - <lastPageFooter> - <band height="5" splitType="Prevent"/> - </lastPageFooter> <summary> <band splitType="Stretch"/> </summary> diff --git a/src/main/resources/reports/RetroCI_Patient_EID_info.jasper b/src/main/resources/reports/RetroCI_Patient_EID_info.jasper index e830e23cfa..f4e05903c3 100644 Binary files a/src/main/resources/reports/RetroCI_Patient_EID_info.jasper and b/src/main/resources/reports/RetroCI_Patient_EID_info.jasper differ diff --git a/src/main/resources/reports/TBPatientReport.jasper b/src/main/resources/reports/TBPatientReport.jasper new file mode 100644 index 0000000000..eb97a60b96 Binary files /dev/null and b/src/main/resources/reports/TBPatientReport.jasper differ diff --git a/src/main/resources/reports/TBPatientReport.jrxml b/src/main/resources/reports/TBPatientReport.jrxml new file mode 100644 index 0000000000..9698a2202c --- /dev/null +++ b/src/main/resources/reports/TBPatientReport.jrxml @@ -0,0 +1,923 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="PatientReport" pageWidth="612" pageHeight="792" whenNoDataType="AllSectionsNoDetail" columnWidth="552" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" resourceBundle="languages/message" whenResourceMissingType="Empty" uuid="d612f334-d625-401a-9542-6d1fca793e90"> + <property name="ireport.scriptlethandling" value="0"/> + <property name="ireport.encoding" value="UTF-8"/> + <property name="ireport.zoom" value="1.5"/> + <property name="ireport.x" value="0"/> + <property name="ireport.y" value="162"/> + <import value="net.sf.jasperreports.engine.*"/> + <import value="java.util.*"/> + <import value="net.sf.jasperreports.engine.data.*"/> + <parameter name="SUBREPORT_DIR" class="java.lang.String"> + <defaultValueExpression><![CDATA["../reports/"]]></defaultValueExpression> + </parameter> + <parameter name="siteId" class="java.lang.String" isForPrompting="false"> + <defaultValueExpression><![CDATA[""]]></defaultValueExpression> + </parameter> + <parameter name="siteName" class="java.lang.String" isForPrompting="false"/> + <parameter name="directorName" class="java.lang.String"/> + <parameter name="headerName" class="java.lang.String" isForPrompting="false"> + <defaultValueExpression><![CDATA["GeneralHeader.jasper"]]></defaultValueExpression> + </parameter> + <parameter name="usePageNumbers" class="java.lang.String" isForPrompting="false"> + <defaultValueExpression><![CDATA["true"]]></defaultValueExpression> + </parameter> + <parameter name="additionalSiteInfo" class="java.lang.String" isForPrompting="false"/> + <parameter name="useSTNumber" class="java.lang.Boolean" isForPrompting="false"> + <defaultValueExpression><![CDATA[Boolean.TRUE]]></defaultValueExpression> + </parameter> + <parameter name="correctedReport" class="java.lang.Boolean" isForPrompting="false"> + <defaultValueExpression><![CDATA[true]]></defaultValueExpression> + </parameter> + <parameter name="billingNumberLabel" class="java.lang.String" isForPrompting="false"/> + <parameter name="footerName" class="java.lang.String" isForPrompting="false"> + <defaultValueExpression><![CDATA["CILNSPFooter.jasper"]]></defaultValueExpression> + </parameter> + <parameter name="leftHeaderImage" class="java.io.InputStream" isForPrompting="false"/> + <parameter name="rightHeaderImage" class="java.io.InputStream" isForPrompting="false"/> + <parameter name="imagesPath" class="java.lang.String"/> + <parameter name="useBillingNumber" class="java.lang.Boolean" isForPrompting="false"> + <defaultValueExpression><![CDATA[Boolean.FALSE]]></defaultValueExpression> + </parameter> + <queryString> + <![CDATA[]]> + </queryString> + <field name="nationalId" class="java.lang.String"/> + <field name="gender" class="java.lang.String"/> + <field name="stNumber" class="java.lang.String"/> + <field name="testName" class="java.lang.String"/> + <field name="result" class="java.lang.String"/> + <field name="accessionNumber" class="java.lang.String"/> + <field name="recievedDate" class="java.lang.String"/> + <field name="conclusion" class="java.lang.String"/> + <field name="contactInfo" class="java.lang.String"/> + <field name="siteInfo" class="java.lang.String"/> + <field name="uom" class="java.lang.String"/> + <field name="note" class="java.lang.String"/> + <field name="age" class="java.lang.String"/> + <field name="testSection" class="java.lang.String"/> + <field name="testRefRange" class="java.lang.String"/> + <field name="dept" class="java.lang.String"/> + <field name="commune" class="java.lang.String"/> + <field name="completeFlag" class="java.lang.String"/> + <field name="panelName" class="java.lang.String"/> + <field name="separator" class="java.lang.Boolean"/> + <field name="orderFinishDate" class="java.lang.String"/> + <field name="orderDate" class="java.lang.String"/> + <field name="patientSiteNumber" class="java.lang.String"/> + <field name="patientName" class="java.lang.String"/> + <field name="abnormalResult" class="java.lang.Boolean"/> + <field name="collectionDateTime" class="java.lang.String"/> + <field name="correctedResult" class="java.lang.Boolean"/> + <field name="parentMarker" class="java.lang.Boolean"/> + <field name="alerts" class="java.lang.String"/> + <field name="subjectNumber" class="java.lang.String"/> + <field name="billingNumber" class="java.lang.String"/> + <field name="healthRegion" class="java.lang.String"/> + <field name="healthDistrict" class="java.lang.String"/> + <field name="sampleId" class="java.lang.String"/> + <field name="sampleType" class="java.lang.String"/> + <field name="analysisStatus" class="java.lang.String"/> + <field name="labOrderType" class="java.lang.String"/> + <field name="sampleSortOrder" class="java.lang.String"/> + <field name="tbOrderReason" class="java.lang.String"/> + <field name="tbDiagnosticReason" class="java.lang.String"/> + <field name="tbFollowupReason" class="java.lang.String"/> + <field name="tbAnalysisMethod" class="java.lang.String"/> + <field name="tbSampleAspect" class="java.lang.String"/> + <field name="tbFollowupPeriodLine1" class="java.lang.String"/> + <field name="tbFollowupPeriodLine2" class="java.lang.String"/> + <field name="prescriber" class="java.lang.String"/> + <group name="person" isStartNewPage="true" isResetPageNumber="true" footerPosition="ForceAtBottom"> + <groupExpression><![CDATA[$F{subjectNumber}]]></groupExpression> + <groupFooter> + <band height="61"> + <textField evaluationTime="Group" evaluationGroup="person" pattern=""> + <reportElement x="373" y="40" width="100" height="20" isRemoveLineWhenBlank="true" uuid="396b7540-121d-4a13-9bf1-9d436d2d7a9a"/> + <textElement verticalAlignment="Middle"> + <font size="9" isBold="false"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.date}]]></textFieldExpression> + </textField> + <textField evaluationTime="Group" evaluationGroup="person" pattern=""> + <reportElement x="370" y="0" width="183" height="61" isRemoveLineWhenBlank="true" uuid="511d4db7-878f-4be0-911d-c31de6fdb275"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9" isBold="false"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.signValidation}]]></textFieldExpression> + </textField> + <textField evaluationTime="Group" evaluationGroup="person" pattern=""> + <reportElement x="0" y="0" width="370" height="61" isRemoveLineWhenBlank="true" uuid="cb6c624d-3174-4cfc-aca4-adb7b4e2db07"/> + <box topPadding="0" leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9" isBold="false"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.labInfomation}]]></textFieldExpression> + </textField> + <image onErrorType="Blank"> + <reportElement x="371" y="16" width="178" height="43" isRemoveLineWhenBlank="true" isPrintInFirstWholeBand="true" uuid="b8d6074f-983c-46d8-bf13-8ccebd3ae450"/> + <imageExpression><![CDATA[$P{imagesPath}+ "RTSign.jpg"]]></imageExpression> + </image> + </band> + </groupFooter> + </group> + <group name="Accession Number" isStartNewPage="true" isResetPageNumber="true" isReprintHeaderOnEachPage="true"> + <groupExpression><![CDATA[$F{accessionNumber}]]></groupExpression> + <groupHeader> + <band height="88" splitType="Prevent"> + <frame> + <reportElement x="0" y="55" width="553" height="29" isRemoveLineWhenBlank="true" forecolor="#66FF66" backcolor="#FF9999" uuid="097a7bd2-51b5-4b31-9361-55a48037fcc7"> + <printWhenExpression><![CDATA[$V{PAGE_NUMBER} > 1]]></printWhenExpression> + </reportElement> + <textField isBlankWhenNull="true"> + <reportElement stretchType="RelativeToBandHeight" x="100" y="15" width="166" height="14" uuid="54414201-7401-4a0a-8b22-2261ea442699"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{contactInfo}]]></textFieldExpression> + </textField> + <textField> + <reportElement stretchType="RelativeToBandHeight" mode="Opaque" x="0" y="15" width="100" height="14" backcolor="#E6E6E6" uuid="16d339e5-244b-4bc0-8f0f-168d6df94866"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.prescriber}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement stretchType="RelativeToBandHeight" x="366" y="15" width="187" height="14" uuid="ca67db0b-f444-4071-abad-94516bc97599"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{siteInfo}]]></textFieldExpression> + </textField> + <textField> + <reportElement stretchType="RelativeToBandHeight" mode="Opaque" x="266" y="15" width="100" height="14" backcolor="#E6E6E6" uuid="478e6898-46aa-4949-997e-86eb2c3f41a0"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.referringSite}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="1" width="100" height="14" backcolor="#E6E6E6" uuid="a5d18f5c-3822-4941-a112-fc52baba67f8"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.patientCode}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="100" y="1" width="112" height="14" uuid="e0613cb3-e5a2-4eb0-a041-c3f72653295e"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.0" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.0" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{subjectNumber}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="331" y="1" width="95" height="14" backcolor="#E6E6E6" uuid="45f57968-83ca-479c-b7b5-a220c3ebdbb2"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.ordinanceNo}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="434" y="1" width="119" height="14" uuid="0f49395e-f77f-4f8a-9019-69a324f7c1a9"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{accessionNumber}]]></textFieldExpression> + </textField> + </frame> + <frame> + <reportElement x="0" y="0" width="554" height="84" isRemoveLineWhenBlank="true" forecolor="#FF6666" backcolor="#33FFFF" uuid="28a0cb23-3dbf-495b-81f1-3ece268ccff0"> + <printWhenExpression><![CDATA[$V{PAGE_NUMBER} == 1]]></printWhenExpression> + </reportElement> + <textField pattern="" isBlankWhenNull="true"> + <reportElement mode="Opaque" x="357" y="0" width="58" height="28" backcolor="#E6E6E6" uuid="ba3306cb-ef59-43ae-9a85-507a0845ffdc"/> + <box leftPadding="3"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement textAlignment="Right" verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.age}]]></textFieldExpression> + </textField> + <textField pattern="" isBlankWhenNull="true"> + <reportElement x="415" y="0" width="51" height="28" uuid="b617f53e-69e4-4677-b962-5cfdb502232c"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{age}]]></textFieldExpression> + </textField> + <textField pattern="" isBlankWhenNull="true"> + <reportElement x="516" y="0" width="37" height="28" uuid="646f021f-0106-4807-b22b-fcb988034786"> + <printWhenExpression><![CDATA[!"0".equals($F{gender})]]></printWhenExpression> + </reportElement> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{gender}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="466" y="0" width="50" height="28" backcolor="#E6E6E6" uuid="5c2660bc-df5d-46a8-aa3f-39ed220db460"/> + <box leftPadding="3"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.sex}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="0" width="111" height="28" backcolor="#E6E6E6" uuid="b09cd436-7eb8-4b88-9c31-537f33f48762"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.5" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.5" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.patientCode}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="113" y="0" width="244" height="28" uuid="6d8ea6f1-1d79-4647-b4fc-d708a8e1027c"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineStyle="Solid"/> + <leftPen lineWidth="0.0" lineStyle="Solid"/> + <bottomPen lineWidth="0.5" lineStyle="Solid"/> + <rightPen lineWidth="0.0" lineStyle="Solid"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{subjectNumber}]]></textFieldExpression> + </textField> + <textField> + <reportElement stretchType="RelativeToBandHeight" mode="Opaque" x="0" y="42" width="111" height="14" backcolor="#E6E6E6" uuid="0d313749-68ec-4d24-8758-303340201e2a"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineColor="#CCCCCC"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.prescriber}]]></textFieldExpression> + </textField> + <textField> + <reportElement stretchType="RelativeToBandHeight" x="111" y="28" width="442" height="14" uuid="19157c4d-565e-4e55-9d1e-4ab2c5219749"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{patientName}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement stretchType="RelativeToBandHeight" x="113" y="42" width="158" height="14" uuid="a36b1fa1-4dbe-4936-af78-4addfc7d9cab"/> + <box leftPadding="4"> + <bottomPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{contactInfo}]]></textFieldExpression> + </textField> + <textField> + <reportElement stretchType="RelativeToBandHeight" mode="Opaque" x="271" y="42" width="100" height="14" backcolor="#E6E6E6" uuid="8c886a7c-fcc3-4962-ab1d-01d976589b96"/> + <box leftPadding="4"> + <topPen lineWidth="0.5" lineColor="#CCCCCC"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.referingsite}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement stretchType="RelativeToBandHeight" x="371" y="42" width="182" height="14" isPrintWhenDetailOverflows="true" uuid="7b0a62cf-8ae3-4c0b-841c-02ab5e96a9cc"/> + <box leftPadding="4"> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{siteInfo}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="56" width="111" height="14" backcolor="#E6E6E6" uuid="10eb7e38-19d4-413b-a245-98fa6529ef41"/> + <box leftPadding="4"> + <topPen lineWidth="1.0" lineColor="#000000"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.ordinanceNo}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="111" y="56" width="160" height="14" uuid="bbe0cd65-afd5-4aeb-9667-1d47fe5bab68"/> + <box leftPadding="4"> + <topPen lineWidth="1.0"/> + <bottomPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{accessionNumber}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="70" width="163" height="14" backcolor="#E6E6E6" uuid="396e8321-b06a-45df-85e1-a5758f53d3d7"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5" lineColor="#000000"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.orderDate}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="271" y="70" width="163" height="14" backcolor="#E6E6E6" uuid="619ab4d2-50ff-4233-9009-3425498cac02"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5" lineColor="#000000"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.receiptDate}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="163" y="70" width="108" height="14" uuid="d67d4ade-e9f2-418d-be6d-4afc6aed986a"/> + <box leftPadding="4"> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{orderDate}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="434" y="70" width="119" height="14" uuid="d3844e5e-0423-47ba-b85b-4382c3d195ef"/> + <box leftPadding="4"> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{recievedDate}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Opaque" x="0" y="28" width="111" height="14" backcolor="#E6E6E6" uuid="5e6ecd01-2e17-412d-b365-b6a569102246"/> + <box leftPadding="4"> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textElement verticalAlignment="Middle" markup="none"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$R{label.patient_name}]]></textFieldExpression> + </textField> + </frame> + </band> + </groupHeader> + <groupFooter> + <band splitType="Stretch"/> + </groupFooter> + </group> + <group name="section name" isReprintHeaderOnEachPage="true"> + <groupExpression><![CDATA[$F{testSection}]]></groupExpression> + <groupHeader> + <band height="118" splitType="Prevent"> + <frame> + <reportElement mode="Transparent" x="0" y="88" width="553" height="29" backcolor="#FFFFFF" uuid="7fe3242a-9b9a-4741-a32b-e8c3b0fe753d"/> + <box> + <pen lineWidth="0.5"/> + <topPen lineWidth="0.5"/> + <leftPen lineWidth="0.5"/> + <bottomPen lineWidth="0.5"/> + <rightPen lineWidth="0.5"/> + </box> + <textField> + <reportElement mode="Transparent" x="102" y="10" width="130" height="17" isPrintWhenDetailOverflows="true" backcolor="#FFFFFF" uuid="ccb4c1fe-67dd-4e78-805f-360f847fdfb1"/> + <textElement textAlignment="Center" verticalAlignment="Bottom"> + <font size="9" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.testName}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="1" y="10" width="101" height="17" isPrintWhenDetailOverflows="true" backcolor="#FFFFFF" uuid="16205c1c-2bb3-4fe4-a957-3cb2fbe2d8c7"/> + <textElement textAlignment="Center" verticalAlignment="Bottom"> + <font size="9" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.completedDate}]]></textFieldExpression> + </textField> + </frame> + <rectangle> + <reportElement x="1" y="2" width="200" height="20" backcolor="#EAEAEA" uuid="9c8634e3-beba-4a67-96b5-15a55a96bd7b"/> + </rectangle> + <textField> + <reportElement mode="Transparent" x="4" y="2" width="170" height="18" backcolor="#FFFFFF" uuid="209d2779-774a-4c7c-a3b5-a5c03d2c4bc4"/> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.sampleType}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="1" y="22" width="200" height="20" uuid="d156f5db-ed9b-42de-973a-4808a5375a02"/> + </rectangle> + <textField isBlankWhenNull="true"> + <reportElement x="5" y="21" width="169" height="20" uuid="a1bc6a33-f933-4152-a86a-137030371e04"/> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$F{sampleType}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="201" y="2" width="187" height="20" backcolor="#EAEAEA" uuid="4bd78bce-069c-4eb5-9650-171dc0690578"/> + </rectangle> + <rectangle> + <reportElement x="201" y="22" width="187" height="20" uuid="7519c53a-a1ad-45e1-9561-ef6a407ece71"/> + </rectangle> + <textField isBlankWhenNull="true"> + <reportElement x="204" y="22" width="172" height="20" uuid="1deac295-b5d5-4701-ad6e-02ee277d22c2"/> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$F{tbOrderReason}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="204" y="2" width="156" height="20" backcolor="#FFFFFF" uuid="12fa24b6-476a-4999-9de1-f4c074445bc6"/> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.orderReason}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="388" y="22" width="163" height="20" uuid="d1cfe420-4337-4808-aae4-2bbb60d23cc4"/> + </rectangle> + <rectangle> + <reportElement x="388" y="2" width="163" height="20" backcolor="#EAEAEA" uuid="a0bbcd72-eed4-4e9c-9624-164b49443d77"/> + </rectangle> + <textField> + <reportElement mode="Transparent" x="389" y="2" width="156" height="20" backcolor="#FFFFFF" uuid="f1de659a-fbfc-4f2e-a87a-7efc8e7ca83a"/> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.analysisMethod}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="392" y="22" width="146" height="20" uuid="4f881bf8-eb59-4a5d-afcd-7405708b1681"/> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$F{tbAnalysisMethod}]]></textFieldExpression> + </textField> + <rectangle> + <reportElement x="1" y="62" width="200" height="20" uuid="e4f9c18b-a2b3-4db5-87a2-a9ee73a00f08"/> + </rectangle> + <rectangle> + <reportElement x="201" y="62" width="187" height="20" uuid="4ddd0a84-bba2-40e1-898f-bea6135eacc9"/> + </rectangle> + <rectangle> + <reportElement x="388" y="42" width="163" height="20" backcolor="#EAEAEA" uuid="93839e7e-4dd7-4840-a073-f654e0eabce2"/> + </rectangle> + <rectangle> + <reportElement x="201" y="42" width="187" height="20" backcolor="#EAEAEA" uuid="a005374a-d1db-4e73-a2eb-ae919a1ce3f2"/> + </rectangle> + <rectangle> + <reportElement x="1" y="42" width="200" height="20" backcolor="#EAEAEA" uuid="32d6e8e1-c5c3-4c77-955c-562bf5fd7f7b"/> + </rectangle> + <rectangle> + <reportElement x="388" y="62" width="163" height="20" uuid="9030aef8-01d8-4263-8ebe-c511e615175c"/> + </rectangle> + <textField> + <reportElement mode="Transparent" x="8" y="43" width="185" height="18" backcolor="#FFFFFF" uuid="0d6f73f8-f221-437d-be5d-c52c0263f7b3"> + <printWhenExpression><![CDATA[$F{tbDiagnosticReason} != null]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.diagnostic.reason}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="434" y="98" width="120" height="17" isPrintWhenDetailOverflows="true" backcolor="#FFFFFF" uuid="63148547-cc4a-4a54-8208-5417b9235a3f"/> + <textElement verticalAlignment="Bottom"> + <font size="9" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.sample.aspect}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="214" y="43" width="166" height="18" backcolor="#FFFFFF" uuid="89e308f1-8a81-4972-b91c-4501a8f8f8b5"> + <printWhenExpression><![CDATA[$F{tbFollowupPeriodLine2} != null]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.followup.period}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="205" y="62" width="171" height="20" uuid="5af27e3d-f0c6-4b89-8f7c-502ecb95b17c"/> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$F{tbFollowupPeriodLine1}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="205" y="62" width="168" height="20" uuid="f5075bc0-d5fa-401a-a3ac-d5d2f6b09548"/> + <textElement verticalAlignment="Middle"/> + <textFieldExpression><![CDATA[$F{tbFollowupPeriodLine2}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="9" y="43" width="185" height="18" backcolor="#FFFFFF" uuid="e7412f34-16c9-4084-b08a-7039b8d6cae3"> + <printWhenExpression><![CDATA[$F{tbFollowupReason} != null]]></printWhenExpression> + </reportElement> + <textElement verticalAlignment="Middle"> + <font size="10" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.tb.followup.reason}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="7" y="62" width="194" height="20" isPrintWhenDetailOverflows="true" uuid="56ed7fd7-7f56-437b-b308-21ef631f8658"/> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{tbDiagnosticReason}]]></textFieldExpression> + </textField> + <textField isBlankWhenNull="true"> + <reportElement x="5" y="63" width="196" height="20" isPrintWhenDetailOverflows="true" uuid="d1165694-2f3c-4c7d-be6c-0a79ca082ebc"/> + <textElement verticalAlignment="Middle"> + <font size="9"/> + </textElement> + <textFieldExpression><![CDATA[$F{tbFollowupReason}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="380" y="98" width="54" height="17" isPrintWhenDetailOverflows="true" uuid="a823e1bd-d695-406c-b2a4-c1e12e52005c"/> + <textElement textAlignment="Center" verticalAlignment="Bottom" markup="none"> + <font size="9" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.status}]]></textFieldExpression> + </textField> + <textField> + <reportElement mode="Transparent" x="232" y="98" width="148" height="17" isPrintWhenDetailOverflows="true" backcolor="#FFFFFF" uuid="0f5ca873-81d6-4a44-b472-bb36d7392aa1"/> + <textElement textAlignment="Center" verticalAlignment="Bottom"> + <font size="9" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$R{report.outcome}]]></textFieldExpression> + </textField> + </band> + </groupHeader> + <groupFooter> + <band/> + </groupFooter> + </group> + <background> + <band splitType="Stretch"/> + </background> + <title> + <band height="2" splitType="Stretch"> + <line> + <reportElement key="line" x="0" y="-45" width="534" height="1" forecolor="#000000" uuid="86c71ee1-1053-451b-a32f-54f203d1a833"/> + <graphicElement> + <pen lineWidth="2.0" lineStyle="Solid"/> + </graphicElement> + </line> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/scripts/entryByProjectUtils.js b/src/main/resources/static/scripts/entryByProjectUtils.js index 7ac66a974b..dd01f22d12 100644 --- a/src/main/resources/static/scripts/entryByProjectUtils.js +++ b/src/main/resources/static/scripts/entryByProjectUtils.js @@ -211,6 +211,7 @@ function BaseLoader() { clearField(document.getElementById("farv." + fieldId)); clearField(document.getElementById("eid." + fieldId)); clearField(document.getElementById("vl." + fieldId)); + clearField(document.getElementById("rt." + fieldId)); clearField(document.getElementById("rtn." + fieldId)); } @@ -230,6 +231,7 @@ function BaseLoader() { this.setField("rtn." + fieldId, value); this.setField("eid." + fieldId, value); this.setField("vl." + fieldId, value); + this.setField("rt." + fieldId, value); }; /** @@ -259,6 +261,7 @@ function BaseLoader() { */ function PatientLoader() { this.url = "provider=PatientSearchPopulateProvider"; + this.existing = null; /** * This member indicates that value of the subjectNumber loaded from a sampleNumber @@ -358,6 +361,7 @@ function PatientLoader() { handlePatientBirthDateChange($("farv.dateOfBirth"), $("farv.interviewDate"), false, $("farv.age")); handlePatientBirthDateChange($("eid.dateOfBirth"), $("eid.interviewDate"), false, null, $('eid.month'), $('eid.ageWeek')); handlePatientBirthDateChange($("vl.dateOfBirth"), $("vl.interviewDate"), false, $("vl.age")); + handlePatientBirthDateChange($("rt.dateOfBirth"), $("rt.interviewDate"), false, $("rt.age")); handlePatientBirthDateChange($("rtn.dateOfBirth"), $("rtn.interviewDate"), false, $("rtn.age"), $("rtn.month")); } @@ -729,6 +733,7 @@ function ObservationHistoryLoader() { farv.refresh(); eid.refresh(); vl.refresh(); + rt.refresh(); if (rtn != null) { rtn.refresh(); } @@ -916,9 +921,9 @@ function BaseProjectChecker() { this.checkGenderForVlPregnancyOrSuckle = function () { //Observation[YES_NO] set No option selected by default when selected gender = "F" - if($("vl.gender").value === 'F'){ - $("vl.vlPregnancy").value=1251; //1251 is th dictionary ID for "No" response - $("vl.vlSuckle").value=1251; + if($(this.idPre+"gender").value === 'F'){ + $(this.idPre+"vlPregnancy").value=1251; //1251 is th dictionary ID for "No" response + $(this.idPre+"vlSuckle").value=1251; } } @@ -927,7 +932,7 @@ function BaseProjectChecker() { checkRequiredField($(this.idPre + "gender"), blanksAllowed); comparePatientField( this.idPre + "gender", false, blanksAllowed); var selectedValue = $(this.idPre + "gender").value; - if(this.idPre === 'vl.'){// do it only for viral load form + if(this.idPre === 'vl.' || this.idPre === 'rt.'){// do it only for viral load form if(selectedValue==='F'){ $(this.idPre + "vlPregnancyRow").show(); $(this.idPre + "vlSuckleRow").show(); diff --git a/src/main/resources/static/scripts/jquery_ui/external/jquery/jquery.js b/src/main/resources/static/scripts/jquery_ui/external/jquery/jquery.js new file mode 100644 index 0000000000..fc6c299b73 --- /dev/null +++ b/src/main/resources/static/scripts/jquery_ui/external/jquery/jquery.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
* +   + +
*<%=MessageUtil.getContextualMessage("quick.entry.accession.number")%> + +
+ +
', 'false' );makeDirty();" + maxlength="5" />
* +
* <%=DateUtil.getDateUserPrompt()%> + +
+ +
* +   + + +
* +   + + +
+
+
* <%=DateUtil.getDateUserPrompt()%> + +
  +
* <%=DateUtil.getDateUserPrompt()%> + +
  +
+
+
+
diff --git a/src/main/webapp/pages/patient/CI/rtnStudy.jsp b/src/main/webapp/pages/patient/CI/rtnStudy.jsp index d5884f572e..85b39e270d 100644 --- a/src/main/webapp/pages/patient/CI/rtnStudy.jsp +++ b/src/main/webapp/pages/patient/CI/rtnStudy.jsp @@ -118,6 +118,7 @@ rtn = new RtnProjectChecker(); +
@@ -135,6 +136,7 @@ rtn = new RtnProjectChecker(); +
@@ -234,7 +236,7 @@ rtn = new RtnProjectChecker(); -
+
@@ -324,8 +326,9 @@ rtn = new RtnProjectChecker(); onchange="makeDirty();compareAllObservationHistoryFields(true)" id='rtn.${disease.name}'> - + +
@@ -342,8 +345,9 @@ rtn = new RtnProjectChecker(); onchange="makeDirty();compareAllObservationHistoryFields(true)" id='rtn.${disease.name}'> - + +
@@ -416,6 +420,7 @@ rtn = new RtnProjectChecker(); +
@@ -427,6 +432,7 @@ rtn = new RtnProjectChecker(); +
\ No newline at end of file diff --git a/src/main/webapp/pages/patient/CI/vlStudy.jsp b/src/main/webapp/pages/patient/CI/vlStudy.jsp index 9f6f014dea..327b72e137 100644 --- a/src/main/webapp/pages/patient/CI/vlStudy.jsp +++ b/src/main/webapp/pages/patient/CI/vlStudy.jsp @@ -2,687 +2,585 @@ import="org.openelisglobal.common.action.IActionConstants, org.openelisglobal.common.util.DateUtil"%> -<%@ page isELIgnored="false" %> +<%@ page isELIgnored="false"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="ajax" uri="/tags/ajaxtags" %> - +<%@ taglib prefix="ajax" uri="/tags/ajaxtags"%> + + this.checkDate = function(field, blanksAllowed) { + makeDirty(); + if (field == null) + return; // just so we don't have to have this field on all forms, but is listed in checkAllSampleFields + checkValidDate(field); + checkRequiredField(field, blanksAllowed); + compareSampleField(field.id, false, blanksAllowed); + }; + + this.checkVLRequestReason = function() { + clearFormElements("vl.vlOtherReasonForRequest"); + this.displayedByReasonOther(); + }; + this.displayedByReasonOther = function() { + var field = $("vl.vlReasonForRequest"); + showElements((field.selectedIndex == 5), "vl.reasonOtherRow"); + }; + + this.checkInterruptedARVTreatment = function() { + clearFormElements("vl.arvTreatmentInitDate,vl.arvTreatmentRegime,vl.currentARVTreatmentINNs0,vl.currentARVTreatmentINNs1,vl.currentARVTreatmentINNs2,vl.currentARVTreatmentINNs3"); + this.displayedByInterruptedARVTreatment(); + }; + + this.displayedByInterruptedARVTreatment = function() { + var field = $("vl.currentARVTreatment"); + showElements( + (field.selectedIndex == 1), + "vl.arvTreatmentInitDateRow,vl.arvTreatmentTherapRow,vl.onGoingARVTreatmentINNsRow,vl.currentARVTreatmentINNRow0,vl.currentARVTreatmentINNRow1,vl.currentARVTreatmentINNRow2,vl.currentARVTreatmentINNRow3"); + }; + + this.checkVLBenefit = function() { + clearFormElements("vl.priorVLLab,vl.priorVLValue,vl.priorVLDate"); + this.displayedByVLBenefit(); + }; + this.displayedByVLBenefit = function() { + var field = $("vl.vlBenefit"); + showElements((field.selectedIndex == 1), + "vl.priorVLLabRow,vl.priorVLValueRow,vl.priorVLDateRow"); + }; + function IsNumeric(field, e) { + var keyCode = e.which ? e.which : e.keyCode + var ret = ((keyCode >= 48 && keyCode <= 57) || specialKeys + .indexOf(keyCode) != -1); + document.getElementById("error").style.display = ret ? "none" + : "inline"; + return ret; + } + ; + + this.refresh = function() { + this.refreshBase(); + this.displayedByVLBenefit(); + this.displayedByReasonOther(); + this.displayedByInterruptedARVTreatment(); + }; + } + + VLProjectChecker.prototype = new BaseProjectChecker(); + /// the object which knows about VL questions and which fields to show etc. + vl = new VLProjectChecker(); +

- - +
+ - - +
- - + +
- + - + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + onchange="vl.checkSiteSubjectNumber(true, false); makeDirty();" /> +
+ + + + + - + - - + - + - + - - + onchange="vl.checkDateOfBirth(false)" cssClass="text" + id="vl.dateOfBirth" maxlength="10" /> +
- - - + + + - + - - + +
- - - - - - - - + + - - - - - - + + + + + - - + +
+ + + + + + + - - - - <%-- _________________________________________________ --%> - + + + + + + <%-- _________________________________________________ --%> + + - - + +
- + - - + + onchange="vl.checkDate(this,false);" cssClass="text" + id="vl.arvTreatmentInitDate" maxlength="10" /> +
- - + + - - + +
- - + + - + - - + + - +
- - <%-- __________________________________________________________________________________________________ --%> - - + + + + + <%-- __________________________________________________________________________________________________ --%> + + - - + +
- - + + - - + + + + + + - - <%-- _________________________________________________ --%> - - + <%-- _________________________________________________ --%> + + - + - + - - + + - + - - - - + + + + - - + + onchange="vl.checkDate(this,false);" cssClass="text" + id="vl.initcd4Date" maxlength="10" /> +
+ + + - <%-- _________________________________________________ --%> - - + <%-- _________________________________________________ --%> + + - + - + - - + + - + - - - - + + + + - - + + onchange="vl.checkDate(this,false);" cssClass="text" + id="vl.demandcd4Date" maxlength="10" /> +
- <%-- __________________________________________________________________________________________________ --%> - + + + + <%-- __________________________________________________________________________________________________ --%> + - - + +
- - + + - - - + + + - + - - - + + + - - + + - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - - - - - - - - - - - + - + - - + +
* - + - + - + -
-
* - - - - - + + + -
-
- + +
+
* <%=DateUtil.getDateUserPrompt()%> - -
+
+
  +
* <%=DateUtil.getDateUserPrompt()%> +
  +
- - - -
-
* -  <%=DateUtil.getDateUserPrompt()%> - - -
-
-   - - -
-
* -  <%=DateUtil.getDateUserPrompt()%> - - -
-
-   - - -
-
+ - - - -
-
+
+ - -
-
+
* - - -
- ', false ); makeDirty();" - maxlength="5" /> -
+
+ +
', false ); makeDirty();" + maxlength="5" />
-
* -  <%=DateUtil.getDateUserPrompt()%> +  <%=DateUtil.getDateUserPrompt()%> - -
-
- - - - -
-
+ +
* - - - - - + + + -
-
- - - - - - -
- - - - - - -
+ + + +
- - - + - + -
-
* + + + +


- - - + - + -


- - - + - + -
-


- -
- - - -
-
+
- - - -
-
+
- - - -
-


- -
- - - -
-
+
- - - -
-
+
- - - -
-


- - - + - + -
-
 

 


- - - - - - -
- - - -
- +
+ + + +
+
- - +
+
+
- -
- -
- -
- - +
diff --git a/src/main/webapp/pages/patient/patientSearch.jsp b/src/main/webapp/pages/patient/patientSearch.jsp index b59f86bbd8..75960918f7 100644 --- a/src/main/webapp/pages/patient/patientSearch.jsp +++ b/src/main/webapp/pages/patient/patientSearch.jsp @@ -303,7 +303,6 @@ function enableSearchButton(eventCode){ } function handleSelectedPatient(){ - console.log("patientSearch:HandleSelectedPatient: "); var accessionNumber = ""; if(jQuery("#searchCriteria").val() == 5){//lab number accessionNumber = jQuery("#searchValue").val(); diff --git a/src/main/webapp/pages/patient/retroCIEntryByProject.jsp b/src/main/webapp/pages/patient/retroCIEntryByProject.jsp index 6176b1f50c..56ba402529 100644 --- a/src/main/webapp/pages/patient/retroCIEntryByProject.jsp +++ b/src/main/webapp/pages/patient/retroCIEntryByProject.jsp @@ -1,8 +1,8 @@ <%@ page language="java" contentType="text/html; charset=UTF-8" import="org.openelisglobal.common.action.IActionConstants, org.openelisglobal.login.valueholder.UserSessionData, - org.owasp.encoder.Encode, - org.openelisglobal.common.util.Versioning,java.util.HashSet,org.owasp.encoder.Encode"%> + org.openelisglobal.common.util.*,org.openelisglobal.internationalization.MessageUtil, + java.util.HashSet,org.owasp.encoder.Encode"%> <%@ page isELIgnored="false" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> @@ -110,7 +110,7 @@ function clearFormElements(fieldIds) { - + + + <%-- --%>
- +
-
+
+
- + + + + * +  <%=DateUtil.getDateUserPrompt()%> + + +
+ + + +   + +
+ + + * +  <%=DateUtil.getDateUserPrompt()%> + + +
+ + + +   + +
+ + + + + + +
+ + + + + + +
+ + + * + <%=MessageUtil.getContextualMessage("quick.entry.accession.number")%> + + + +
+ +
', false );makeDirty();" + maxlength="5" />
+ + + + + + * + + +   + +
+ - + + + + + + +
--%> + + + + * + + +   + + +
+ + + + + +   + + +
+ + + + + + +   + + +
+ + + + * + + +   + + +
+ + +
+ + <%-- _________________________________________________ --%> + + + + +   + + +
+ + + + + + +
+ + + + + + +   + + +
+ + + + + + + + + + + ${iter.index}) + + +
+ +
+ +
+ + <%-- _________________________________________________ --%> + + + + + +   + + +
+ + + + + + +
+ + + +
+ + <%-- _________________________________________________ --%> + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + <%-- _________________________________________________ --%> + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + <%-- _________________________________________________ --%> + + + + + +   + +
+ + + + + + + +
+ + + + + + +
+ + + + + + +
+ + +
+ + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + + +   + + +
+ + + + + + +
+ + + + + + + + + +
+ + + + + + + +
+ + + + + + +
+ + + + + + + + + + +
+ + +
+
diff --git a/src/main/webapp/pages/sample/sampleTbAdd.jsp b/src/main/webapp/pages/sample/sampleTbAdd.jsp new file mode 100644 index 0000000000..8041fd4d43 --- /dev/null +++ b/src/main/webapp/pages/sample/sampleTbAdd.jsp @@ -0,0 +1,676 @@ +<%@page import="org.openelisglobal.common.util.SystemConfiguration"%> +<%@page import="org.openelisglobal.common.action.IActionConstants"%> +<%@ page language="java" contentType="text/html; charset=UTF-8" + import="org.openelisglobal.common.formfields.FormFields, + org.openelisglobal.sample.util.AccessionNumberUtil, + org.openelisglobal.common.formfields.FormFields.Field, + org.openelisglobal.common.util.ConfigurationProperties, + org.openelisglobal.common.util.IdValuePair, + org.openelisglobal.common.util.ConfigurationProperties.Property, + org.openelisglobal.common.util.DateUtil, + org.openelisglobal.internationalization.MessageUtil, + org.openelisglobal.common.util.Versioning"%> +<%@ page isELIgnored="false"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<%@ taglib prefix="ajax" uri="/tags/ajaxtags"%> + + + + + + + + + + + + + + + + + + + + + + + +
+ <%=MessageUtil.getContextualMessage("referring.order.number")%>: + + + <%=MessageUtil.getContextualMessage("referring.order.not.found")%> +
+
+ + +
+ + <%=MessageUtil.getContextualMessage("sample.entry.order.label")%> + * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
<%=MessageUtil.getContextualMessage("quick.entry.accession.number")%> + :* + +
: *<%=DateUtil.getDateUserPrompt()%> +
<%=MessageUtil.getContextualMessage("quick.entry.received.date")%> + : * <%=DateUtil.getDateUserPrompt()%> +
<%=MessageUtil.getContextualMessage("sample.tb.reference.unit")%> + : * + + +
<%=MessageUtil.getContextualMessage("sample.entry.provider.name")%>: +
<%=MessageUtil.getContextualMessage("sample.entry.provider.firstName")%>: +
 
+
+
+
+
+ + <%=MessageUtil.getContextualMessage("sample.entry.patient")%> + * + + + + + + + + + + + + + + + + + + + + + + + + +
: * :
::
 <%=DateUtil.getDateUserPrompt()%>: + * +
: +
+ +
+
: * + + + +
 
+
+
+
+
+ + <%=MessageUtil.getContextualMessage("sample.entry.sampleList.label")%> + * +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <%-- + + + + + + + +
<%=MessageUtil.getContextualMessage("sample.tb.specimen.nature")%> + : * + + +
<%=MessageUtil.getContextualMessage("sample.tb.order.reasons")%> + : * + + +
: + *
<%=MessageUtil.getContextualMessage("sample.tb.diagnostic.reasons")%> + : * + + +
<%=MessageUtil.getContextualMessage("sample.tb.followup.reasons")%> + : * + + + + + + + + + + +
<%=MessageUtil.getContextualMessage("sample.tb.diagnostic.methods")%>: + * + + + +
<%=MessageUtil.getContextualMessage("sample.tb.aspects")%> + : * + + +
+
+
+ + + + + + + + + +
+ + + +
+ + + + + + + + + + +
 
+
+ + + + + + + + + +
  
+
+
+
+
+
+
+ +
+ \ No newline at end of file diff --git a/src/main/webapp/pages/siteinformation/siteInformation.jsp b/src/main/webapp/pages/siteinformation/siteInformation.jsp index 9d98e46fb7..e1b3f3d7bd 100644 --- a/src/main/webapp/pages/siteinformation/siteInformation.jsp +++ b/src/main/webapp/pages/siteinformation/siteInformation.jsp @@ -90,7 +90,7 @@ -