changeset 4862:bcdb9d00c7b3

task #16043: Migration to GNU Health 4.0: Migrate health_orthanc
author Luis Falcon <falcon@gnuhealth.org>
date Fri, 14 Jan 2022 21:43:01 +0000
parents e1567c3d934f
children 3a5171e5694f
files tryton/health_orthanc/__init__.py tryton/health_orthanc/data/data.xml tryton/health_orthanc/health_orthanc.py tryton/health_orthanc/tryton.cfg tryton/health_orthanc/wizard/wizard.py
diffstat 5 files changed, 96 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/tryton/health_orthanc/__init__.py
+++ b/tryton/health_orthanc/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
 ##############################################################################
 #
 #    GNU Health: The Free Health and Hospital Information System
@@ -20,20 +19,21 @@
 ##############################################################################
 
 from trytond.pool import Pool
-from .health_orthanc import *
-from .wizard import *
+from . import health_orthanc
+from . import wizard
 
 
 def register():
     Pool.register(
-        AddOrthancInit,
-        AddOrthancResult,
-        OrthancServerConfig,
-        OrthancStudy,
-        OrthancPatient,
-        TestResult,
-        Patient,
+        wizard.wizard.AddOrthancInit,
+        wizard.wizard.AddOrthancResult,
+        health_orthanc.OrthancServerConfig,
+        health_orthanc.OrthancStudy,
+        health_orthanc.OrthancPatient,
+        health_orthanc.TestResult,
+        health_orthanc.Patient,
         module="health_orthanc",
         type_="model",
     )
-    Pool.register(FullSyncOrthanc, module="health_orthanc", type_="wizard")
+    Pool.register(
+        wizard.wizard.FullSyncOrthanc, module="health_orthanc", type_="wizard")
--- a/tryton/health_orthanc/data/data.xml
+++ b/tryton/health_orthanc/data/data.xml
@@ -12,20 +12,6 @@
             <field name="group" ref="health.group_health_admin"/>
         </record>
 
-        <!-- Sync Orthanc servers -->
-        <record model="ir.cron" id="cron_orthanc_sync">
-            <field name="name">Sync Orthanc servers</field>
-            <field name="request_user" ref="res.user_admin"/>
-            <field name="user" ref="user_orthanc"/>
-            <field name="active" eval="True"/>
-            <field name="interval_number" eval="15"/>
-            <field name="interval_type">minutes</field>
-            <field name="number_calls" eval="-1"/>
-            <field name="repeat_missed" eval="False"/>
-            <field name="model">gnuhealth.orthanc.config</field>
-            <field name="function">sync</field>
-        </record>
-
         <!-- Access rights
                 Default = Deny models and menu access
                 Providers = Read studies and patients with relevant menu access
--- a/tryton/health_orthanc/health_orthanc.py
+++ b/tryton/health_orthanc/health_orthanc.py
@@ -1,7 +1,12 @@
-# -*- coding: utf-8 -*-
 ##############################################################################
 #
 #    GNU Health: The Free Health and Hospital Information System
+#                   
+#                   *** ORTHANC INTEGRATION PACKAGE ***
+#
+#    Copyright (C) 2019-2022 Chris Zimmerman <chris@teffalump.com>
+#    Copyright (C) 2021-2022 Luis Falcon <falcon@gnuhealth.org>
+#    Copyright (C) 2021-2022 GNU Solidario <info@gnusolidario.org>
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
@@ -45,36 +50,44 @@
     __name__ = "gnuhealth.orthanc.config"
     _rec_name = "label"
 
-    label = fields.Char("Label", required=True, help="Label for server (eg., remote1)")
+    label = fields.Char(
+        "Label", required=True, help="Label for server (eg., remote1)")
+
     domain = fields.Char(
-        "URL", required=True, help="The full URL of the Orthanc server"
-    )
+        "URL", required=True, help="The full URL of the Orthanc server")
+
     user = fields.Char(
-        "Username", required=True, help="Username for Orthanc REST server"
-    )
+        "Username", required=True, help="Username for Orthanc REST server")
+
     password = fields.Char(
-        "Password", required=True, help="Password for Orthanc REST server"
-    )
-    last = fields.BigInteger("Last Index", readonly=True, help="Index of last change")
+        "Password", required=True, help="Password for Orthanc REST server")
+
+    last = fields.BigInteger(
+        "Last Index", readonly=True, help="Index of last change")
+
     sync_time = fields.DateTime(
-        "Sync Time", readonly=True, help="Time of last server sync"
-    )
+        "Sync Time", readonly=True, help="Time of last server sync")
+
     validated = fields.Boolean(
-        "Validated", help="Whether the server details have been successfully checked"
-    )
+        "Validated", help="Whether the server details have been "
+        "successfully checked")
+
     since_sync = fields.Function(
         fields.TimeDelta("Since last sync", help="Time since last sync"),
-        "get_since_sync",
-    )
+        "get_since_sync",)
+
     since_sync_readable = fields.Function(
         fields.Char("Since last sync", help="Time since last sync"),
         "get_since_sync_readable",
     )
-    patients = fields.One2Many("gnuhealth.orthanc.patient", "server", "Patients")
+    patients = fields.One2Many(
+        "gnuhealth.orthanc.patient", "server", "Patients")
+
     studies = fields.One2Many("gnuhealth.orthanc.study", "server", "Studies")
     link = fields.Function(
-        fields.Char("URL", help="Link to server in Orthanc Explorer"), "get_link"
-    )
+        fields.Char(
+            "URL",
+            help="Link to server in Orthanc Explorer"), "get_link")
 
     def get_link(self, name):
         pre = "".join([self.domain.rstrip("/"), "/"])
@@ -104,14 +117,16 @@
         study = pool.get("gnuhealth.orthanc.study")
 
         if not servers:
-            servers = cls.search([("domain", "!=", None), ("validated", "=", True)])
+            servers = cls.search([("domain", "!=", None),
+                                  ("validated", "=", True)])
 
         logger.info("Starting sync")
         for server in servers:
             if not server.validated:
                 continue
             logger.info("Getting new changes for <{}>".format(server.label))
-            orthanc = RestClient(server.domain, auth=auth(server.user, server.password))
+            orthanc = RestClient(server.domain,
+                                 auth=auth(server.user, server.password))
             curr = server.last
             new_patients = set()
             update_patients = set()
@@ -123,7 +138,8 @@
                     changes = orthanc.get_changes(since=curr)
                 except:
                     server.validated = False
-                    logger.exception("Invalid details for <{}>".format(server.label))
+                    logger.exception(
+                        "Invalid details for <{}>".format(server.label))
                     break
                 for change in changes["Changes"]:
                     type_ = change["ChangeType"]
@@ -138,7 +154,8 @@
                     else:
                         pass
                 curr = changes["Last"]
-                if changes["Done"] == True:
+
+                if changes["Done"] is True:
                     logger.info("<{}> at newest change".format(server.label))
                     break
 
@@ -163,7 +180,8 @@
             server.last = curr
             server.sync_time = datetime.now()
             logger.info(
-                "<{}> sync complete: {} new patients, {} update patients, {} new studies, {} updated studies".format(
+                "<{}> sync complete: {} new patients, {} \
+                update patients, {} new studies, {} updated studies".format(
                     server.label,
                     len(new_patients),
                     len(update_patients),
@@ -215,10 +233,12 @@
     studies = fields.One2Many(
         "gnuhealth.orthanc.study", "patient", "Studies", readonly=True
     )
-    server = fields.Many2One("gnuhealth.orthanc.config", "Server", readonly=True)
+    server = fields.Many2One(
+        "gnuhealth.orthanc.config", "Server", readonly=True)
     link = fields.Function(
-        fields.Char("URL", help="Link to patient in Orthanc Explorer"), "get_link"
-    )
+        fields.Char(
+            "URL", help="Link to patient in Orthanc Explorer"), "get_link"
+            )
 
     def get_link(self, name):
         pre = "".join([self.server.domain.rstrip("/"), "/"])
@@ -263,26 +283,27 @@
     def update_patients(cls, patients, server):
         """Update patients"""
 
-        Patient = pool.get("gnuhealth.patient")
-
         entries = cls.get_info_from_dicom(patients)
         updates = []
         for entry in entries:
             try:
                 patient = cls.search(
-                    [("uuid", "=", entry["uuid"]), ("server", "=", server)], limit=1
+                    [("uuid", "=", entry["uuid"]),
+                     ("server", "=", server)], limit=1
                 )[0]
                 patient.name = entry["name"]
                 patient.bd = entry["bd"]
                 patient.ident = entry["ident"]
-                if not patient.patient:  # don't update unless no patient attached
+                # don't update unless no patient attached
+                if not patient.patient:
                     try:
                         g_patient = Patient.search(
                             [("puid", "=", entry["ident"])], limit=1
                         )[0]
                         patient.patient = g_patient
                         logger.info(
-                            "New Matching PUID found for {}".format(entry["ident"])
+                            "New Matching PUID found for {}".
+                            format(entry["ident"])
                         )
                     except:
                         pass
@@ -290,7 +311,8 @@
                 logger.info("Updating patient {}".format(entry["uuid"]))
             except:
                 continue
-                logger.warning("Unable to update patient {}".format(entry["uuid"]))
+                logger.warning("Unable to update patient {}".
+                               format(entry["uuid"]))
         cls.save(updates)
 
     @classmethod
@@ -303,7 +325,8 @@
         entries = cls.get_info_from_dicom(patients)
         for entry in entries:
             try:
-                g_patient = Patient.search([("puid", "=", entry["ident"])], limit=1)[0]
+                g_patient = Patient.search(
+                    [("puid", "=", entry["ident"])], limit=1)[0]
                 logger.info("Matching PUID found for {}".format(entry["uuid"]))
             except:
                 g_patient = None
@@ -317,20 +340,26 @@
 
     __name__ = "gnuhealth.orthanc.study"
 
-    patient = fields.Many2One("gnuhealth.orthanc.patient", "Patient", readonly=True)
+    patient = fields.Many2One(
+        "gnuhealth.orthanc.patient", "Patient", readonly=True)
+
     uuid = fields.Char("UUID", readonly=True, required=True)
     description = fields.Char("Description", readonly=True)
     date = fields.Date("Date", readonly=True)
     ident = fields.Char("ID", readonly=True)
     institution = fields.Char(
-        "Institution", readonly=True, help="Imaging center where study was undertaken"
+        "Institution", readonly=True,
+        help="Imaging center where study was undertaken"
     )
     ref_phys = fields.Char("Referring Physician", readonly=True)
     req_phys = fields.Char("Requesting Physician", readonly=True)
-    server = fields.Many2One("gnuhealth.orthanc.config", "Server", readonly=True)
+    server = fields.Many2One(
+        "gnuhealth.orthanc.config", "Server", readonly=True)
+
     link = fields.Function(
-        fields.Char("URL", help="Link to study in Orthanc Explorer"), "get_link"
-    )
+        fields.Char(
+            "URL", help="Link to study in Orthanc Explorer"), "get_link")
+
     imaging_test = fields.Many2One("gnuhealth.imaging.test.result", "Test")
 
     def get_link(self, name):
@@ -367,7 +396,8 @@
             except:
                 date = None
             try:
-                description = study["MainDicomTags"]["RequestedProcedureDescription"]
+                description = \
+                    study["MainDicomTags"]["RequestedProcedureDescription"]
             except:
                 description = None
             data.append(
@@ -377,11 +407,13 @@
                     "description": description,
                     "date": date,
                     "ident": study.get("MainDicomTags").get("StudyID"),
-                    "institution": study.get("MainDicomTags").get("InstitutionName"),
+                    "institution": study.get(
+                        "MainDicomTags").get("InstitutionName"),
                     "ref_phys": study.get("MainDicomTags").get(
                         "ReferringPhysicianName"
                     ),
-                    "req_phys": study.get("MainDicomTags").get("RequestingPhysician"),
+                    "req_phys": study.get(
+                        "MainDicomTags").get("RequestingPhysician"),
                 }
             )
         return data
@@ -395,7 +427,8 @@
         for entry in entries:
             try:
                 study = cls.search(
-                    [("uuid", "=", entry["uuid"]), ("server", "=", server)], limit=1
+                    [("uuid", "=", entry["uuid"]),
+                        ("server", "=", server)], limit=1
                 )[0]
                 study.description = entry["description"]
                 study.date = entry["date"]
@@ -407,7 +440,8 @@
                 logger.info("Updating study {}".format(entry["uuid"]))
             except:
                 continue
-                logger.warning("Unable to update study {}".format(entry["uuid"]))
+                logger.warning(
+                    "Unable to update study {}".format(entry["uuid"]))
         cls.save(updates)
 
     @classmethod
@@ -421,7 +455,8 @@
         for entry in entries:
             try:
                 patient = Patient.search(
-                    [("uuid", "=", entry["parent_patient"]), ("server", "=", server)],
+                    [("uuid", "=",
+                      entry["parent_patient"]), ("server", "=", server)],
                     limit=1,
                 )[0]
             except:
--- a/tryton/health_orthanc/tryton.cfg
+++ b/tryton/health_orthanc/tryton.cfg
@@ -1,5 +1,5 @@
 [tryton]
-version=3.8.0
+version=3.9.0
 depends:
     health_imaging
 
--- a/tryton/health_orthanc/wizard/wizard.py
+++ b/tryton/health_orthanc/wizard/wizard.py
@@ -1,8 +1,8 @@
-# -*- coding: utf-8 -*-
 ##############################################################################
 #
 #    GNU Health: The Free Health and Hospital Information System
 #
+#                   *** ORTHANC INTEGRATION PACKAGE ***
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@
 from datetime import datetime
 from trytond.model import ModelView, fields
 from trytond.wizard import Wizard, StateTransition, StateView, Button
-from trytond.transaction import Transaction
 from trytond.pool import Pool
 from requests.auth import HTTPBasicAuth as auth
 from requests.exceptions import HTTPError
@@ -39,7 +38,8 @@
     __name__ = "gnuhealth.orthanc.add.init"
 
     label = fields.Char(
-        "Label", required=True, help="The label of the Orthanc server. Must be unique"
+        "Label", required=True,
+        help="The label of the Orthanc server. Must be unique"
     )
     domain = fields.Char(
         "URL", required=True, help="The full URL of the Orthanc server"
@@ -81,7 +81,8 @@
     )
 
     def transition_first_sync(self):
-        """Import and create all current patients and studies on remote DICOM server
+        """ Import and create all current patients
+            and studies on remote DICOM server
         """
 
         pool = Pool()