Package Gnumed :: Package business :: Module gmDocuments
[frames] | no frames]

Source Code for Module Gnumed.business.gmDocuments

  1  """This module encapsulates a document stored in a GNUmed database. 
  2   
  3  @copyright: GPL v2 or later 
  4  """ 
  5  #============================================================ 
  6  __version__ = "$Revision: 1.118 $" 
  7  __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
  8   
  9  import sys, os, shutil, os.path, types, time, logging 
 10  from cStringIO import StringIO 
 11  from pprint import pprint 
 12   
 13   
 14  if __name__ == '__main__': 
 15          sys.path.insert(0, '../../') 
 16  from Gnumed.pycommon import gmExceptions, gmBusinessDBObject, gmPG2, gmTools, gmMimeLib 
 17   
 18   
 19  _log = logging.getLogger('gm.docs') 
 20  _log.info(__version__) 
 21   
 22  MUGSHOT=26 
 23  DOCUMENT_TYPE_VISUAL_PROGRESS_NOTE = u'visual progress note' 
 24  DOCUMENT_TYPE_PRESCRIPTION = u'prescription' 
 25  #============================================================ 
26 -class cDocumentFolder:
27 """Represents a folder with medical documents for a single patient.""" 28
29 - def __init__(self, aPKey = None):
30 """Fails if 31 32 - patient referenced by aPKey does not exist 33 """ 34 self.pk_patient = aPKey # == identity.pk == primary key 35 if not self._pkey_exists(): 36 raise gmExceptions.ConstructorError, "No patient with PK [%s] in database." % aPKey 37 38 # register backend notification interests 39 # (keep this last so we won't hang on threads when 40 # failing this constructor for other reasons ...) 41 # if not self._register_interests(): 42 # raise gmExceptions.ConstructorError, "cannot register signal interests" 43 44 _log.debug('instantiated document folder for patient [%s]' % self.pk_patient)
45 #--------------------------------------------------------
46 - def cleanup(self):
47 pass
48 #-------------------------------------------------------- 49 # internal helper 50 #--------------------------------------------------------
51 - def _pkey_exists(self):
52 """Does this primary key exist ? 53 54 - true/false/None 55 """ 56 # patient in demographic database ? 57 rows, idx = gmPG2.run_ro_queries(queries = [ 58 {'cmd': u"select exists(select pk from dem.identity where pk = %s)", 'args': [self.pk_patient]} 59 ]) 60 if not rows[0][0]: 61 _log.error("patient [%s] not in demographic database" % self.pk_patient) 62 return None 63 return True
64 #-------------------------------------------------------- 65 # API 66 #--------------------------------------------------------
68 cmd = u""" 69 SELECT pk_doc 70 FROM blobs.v_doc_med 71 WHERE 72 pk_patient = %(pat)s 73 AND 74 type = %(typ)s 75 AND 76 ext_ref = %(ref)s 77 ORDER BY 78 clin_when DESC 79 LIMIT 1 80 """ 81 args = { 82 'pat': self.pk_patient, 83 'typ': DOCUMENT_TYPE_PRESCRIPTION, 84 'ref': u'FreeDiams' 85 } 86 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 87 if len(rows) == 0: 88 _log.info('no FreeDiams prescription available for patient [%s]' % self.pk_patient) 89 return None 90 prescription = cDocument(aPK_obj = rows[0][0]) 91 return prescription
92 #--------------------------------------------------------
93 - def get_latest_mugshot(self):
94 cmd = u"select pk_obj from blobs.v_latest_mugshot where pk_patient=%s" 95 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_patient]}]) 96 if len(rows) == 0: 97 _log.info('no mugshots available for patient [%s]' % self.pk_patient) 98 return None 99 mugshot = cDocumentPart(aPK_obj=rows[0][0]) 100 return mugshot
101 #--------------------------------------------------------
102 - def get_mugshot_list(self, latest_only=True):
103 if latest_only: 104 cmd = u"select pk_doc, pk_obj from blobs.v_latest_mugshot where pk_patient=%s" 105 else: 106 cmd = u""" 107 select 108 vdm.pk_doc as pk_doc, 109 dobj.pk as pk_obj 110 from 111 blobs.v_doc_med vdm 112 blobs.doc_obj dobj 113 where 114 vdm.pk_type = (select pk from blobs.doc_type where name = 'patient photograph') 115 and vdm.pk_patient = %s 116 and dobj.fk_doc = vdm.pk_doc 117 """ 118 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_patient]}]) 119 return rows
120 #--------------------------------------------------------
121 - def get_doc_list(self, doc_type=None):
122 """return flat list of document IDs""" 123 124 args = { 125 'ID': self.pk_patient, 126 'TYP': doc_type 127 } 128 129 cmd = u""" 130 select vdm.pk_doc 131 from blobs.v_doc_med vdm 132 where 133 vdm.pk_patient = %%(ID)s 134 %s 135 order by vdm.clin_when""" 136 137 if doc_type is None: 138 cmd = cmd % u'' 139 else: 140 try: 141 int(doc_type) 142 cmd = cmd % u'and vdm.pk_type = %(TYP)s' 143 except (TypeError, ValueError): 144 cmd = cmd % u'and vdm.pk_type = (select pk from blobs.doc_type where name = %(TYP)s)' 145 146 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 147 doc_ids = [] 148 for row in rows: 149 doc_ids.append(row[0]) 150 return doc_ids
151 #--------------------------------------------------------
152 - def get_visual_progress_notes(self, episodes=None, encounter=None):
153 return self.get_documents ( 154 doc_type = DOCUMENT_TYPE_VISUAL_PROGRESS_NOTE, 155 episodes = episodes, 156 encounter = encounter 157 )
158 #--------------------------------------------------------
159 - def get_documents(self, doc_type=None, episodes=None, encounter=None):
160 """Return list of documents.""" 161 162 args = { 163 'pat': self.pk_patient, 164 'type': doc_type, 165 'enc': encounter 166 } 167 where_parts = [u'pk_patient = %(pat)s'] 168 169 if doc_type is not None: 170 try: 171 int(doc_type) 172 where_parts.append(u'pk_type = %(type)s') 173 except (TypeError, ValueError): 174 where_parts.append(u'pk_type = (SELECT pk FROM blobs.doc_type WHERE name = %(type)s)') 175 176 if (episodes is not None) and (len(episodes) > 0): 177 where_parts.append(u'pk_episode IN %(epi)s') 178 args['epi'] = tuple(episodes) 179 180 if encounter is not None: 181 where_parts.append(u'pk_encounter = %(enc)s') 182 183 cmd = u"%s\nORDER BY clin_when" % (_sql_fetch_document_fields % u' AND '.join(where_parts)) 184 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 185 186 return [ cDocument(row = {'pk_field': 'pk_doc', 'idx': idx, 'data': r}) for r in rows ]
187 #--------------------------------------------------------
188 - def add_document(self, document_type=None, encounter=None, episode=None):
189 return create_document(document_type = document_type, encounter = encounter, episode = episode)
190 #============================================================ 191 _sql_fetch_document_part_fields = u"select * from blobs.v_obj4doc_no_data where %s" 192
193 -class cDocumentPart(gmBusinessDBObject.cBusinessDBObject):
194 """Represents one part of a medical document.""" 195 196 _cmd_fetch_payload = _sql_fetch_document_part_fields % u"pk_obj = %s" 197 _cmds_store_payload = [ 198 u"""update blobs.doc_obj set 199 seq_idx = %(seq_idx)s, 200 comment = gm.nullify_empty_string(%(obj_comment)s), 201 filename = gm.nullify_empty_string(%(filename)s), 202 fk_intended_reviewer = %(pk_intended_reviewer)s 203 where 204 pk=%(pk_obj)s and 205 xmin=%(xmin_doc_obj)s""", 206 u"""select xmin_doc_obj from blobs.v_obj4doc_no_data where pk_obj = %(pk_obj)s""" 207 ] 208 _updatable_fields = [ 209 'seq_idx', 210 'obj_comment', 211 'pk_intended_reviewer', 212 'filename' 213 ] 214 #-------------------------------------------------------- 215 # retrieve data 216 #--------------------------------------------------------
217 - def export_to_file(self, aTempDir = None, aChunkSize = 0, filename=None):
218 219 if self._payload[self._idx['size']] == 0: 220 return None 221 222 if filename is None: 223 suffix = None 224 # preserve original filename extension if available 225 if self._payload[self._idx['filename']] is not None: 226 name, suffix = os.path.splitext(self._payload[self._idx['filename']]) 227 suffix = suffix.strip() 228 if suffix == u'': 229 suffix = None 230 # get unique filename 231 filename = gmTools.get_unique_filename ( 232 prefix = 'gm-doc_obj-page_%s-' % self._payload[self._idx['seq_idx']], 233 suffix = suffix, 234 tmp_dir = aTempDir 235 ) 236 237 success = gmPG2.bytea2file ( 238 data_query = { 239 'cmd': u'SELECT substring(data from %(start)s for %(size)s) FROM blobs.doc_obj WHERE pk=%(pk)s', 240 'args': {'pk': self.pk_obj} 241 }, 242 filename = filename, 243 chunk_size = aChunkSize, 244 data_size = self._payload[self._idx['size']] 245 ) 246 247 if success: 248 return filename 249 250 return None
251 #--------------------------------------------------------
252 - def get_reviews(self):
253 cmd = u""" 254 select 255 reviewer, 256 reviewed_when, 257 is_technically_abnormal, 258 clinically_relevant, 259 is_review_by_responsible_reviewer, 260 is_your_review, 261 coalesce(comment, '') 262 from blobs.v_reviewed_doc_objects 263 where pk_doc_obj = %s 264 order by 265 is_your_review desc, 266 is_review_by_responsible_reviewer desc, 267 reviewed_when desc 268 """ 269 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_obj]}]) 270 return rows
271 #--------------------------------------------------------
272 - def get_containing_document(self):
273 return cDocument(aPK_obj = self._payload[self._idx['pk_doc']])
274 #-------------------------------------------------------- 275 # store data 276 #--------------------------------------------------------
277 - def update_data_from_file(self, fname=None):
278 # sanity check 279 if not (os.access(fname, os.R_OK) and os.path.isfile(fname)): 280 _log.error('[%s] is not a readable file' % fname) 281 return False 282 283 gmPG2.file2bytea ( 284 query = u"UPDATE blobs.doc_obj SET data=%(data)s::bytea WHERE pk=%(pk)s", 285 filename = fname, 286 args = {'pk': self.pk_obj} 287 ) 288 289 # must update XMIN now ... 290 self.refetch_payload() 291 return True
292 #--------------------------------------------------------
293 - def set_reviewed(self, technically_abnormal=None, clinically_relevant=None):
294 # row already there ? 295 cmd = u""" 296 select pk 297 from blobs.reviewed_doc_objs 298 where 299 fk_reviewed_row = %s and 300 fk_reviewer = (select pk from dem.staff where db_user = current_user)""" 301 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_obj]}]) 302 303 # INSERT needed 304 if len(rows) == 0: 305 cols = [ 306 u"fk_reviewer", 307 u"fk_reviewed_row", 308 u"is_technically_abnormal", 309 u"clinically_relevant" 310 ] 311 vals = [ 312 u'%(fk_row)s', 313 u'%(abnormal)s', 314 u'%(relevant)s' 315 ] 316 args = { 317 'fk_row': self.pk_obj, 318 'abnormal': technically_abnormal, 319 'relevant': clinically_relevant 320 } 321 cmd = u""" 322 insert into blobs.reviewed_doc_objs ( 323 %s 324 ) values ( 325 (select pk from dem.staff where db_user=current_user), 326 %s 327 )""" % (', '.join(cols), ', '.join(vals)) 328 329 # UPDATE needed 330 if len(rows) == 1: 331 pk_row = rows[0][0] 332 args = { 333 'abnormal': technically_abnormal, 334 'relevant': clinically_relevant, 335 'pk_row': pk_row 336 } 337 cmd = u""" 338 update blobs.reviewed_doc_objs set 339 is_technically_abnormal = %(abnormal)s, 340 clinically_relevant = %(relevant)s 341 where 342 pk=%(pk_row)s""" 343 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 344 345 return True
346 #--------------------------------------------------------
347 - def set_as_active_photograph(self):
348 if self._payload[self._idx['type']] != u'patient photograph': 349 return False 350 # set seq_idx to current max + 1 351 rows, idx = gmPG2.run_ro_queries ( 352 queries = [{ 353 'cmd': u'select coalesce(max(seq_idx)+1, 1) from blobs.doc_obj where fk_doc=%(doc_id)s', 354 'args': {'doc_id': self._payload[self._idx['pk_doc']]} 355 }] 356 ) 357 self._payload[self._idx['seq_idx']] = rows[0][0] 358 self._is_modified = True 359 self.save_payload()
360 #--------------------------------------------------------
361 - def display_via_mime(self, tmpdir=None, chunksize=0, block=None):
362 363 fname = self.export_to_file(aTempDir = tmpdir, aChunkSize = chunksize) 364 if fname is None: 365 return False, '' 366 367 success, msg = gmMimeLib.call_viewer_on_file(fname, block = block) 368 if not success: 369 return False, msg 370 371 return True, ''
372 #============================================================ 373 _sql_fetch_document_fields = u""" 374 SELECT 375 *, 376 COALESCE ( 377 (SELECT array_agg(seq_idx) FROM blobs.doc_obj b_do WHERE b_do.fk_doc = b_vdm.pk_doc), 378 ARRAY[]::integer[] 379 ) 380 AS seq_idx_list 381 FROM 382 blobs.v_doc_med b_vdm 383 WHERE 384 %s 385 """ 386
387 -class cDocument(gmBusinessDBObject.cBusinessDBObject):
388 """Represents one medical document.""" 389 390 _cmd_fetch_payload = _sql_fetch_document_fields % u"pk_doc = %s" 391 _cmds_store_payload = [ 392 u"""update blobs.doc_med set 393 fk_type = %(pk_type)s, 394 fk_episode = %(pk_episode)s, 395 fk_encounter = %(pk_encounter)s, 396 clin_when = %(clin_when)s, 397 comment = gm.nullify_empty_string(%(comment)s), 398 ext_ref = gm.nullify_empty_string(%(ext_ref)s) 399 where 400 pk = %(pk_doc)s and 401 xmin = %(xmin_doc_med)s""", 402 u"""select xmin_doc_med from blobs.v_doc_med where pk_doc = %(pk_doc)s""" 403 ] 404 405 _updatable_fields = [ 406 'pk_type', 407 'comment', 408 'clin_when', 409 'ext_ref', 410 'pk_episode', 411 'pk_encounter' # mainly useful when moving visual progress notes to their respective encounters 412 ] 413 #--------------------------------------------------------
414 - def refetch_payload(self, ignore_changes=False):
415 try: del self.__has_unreviewed_parts 416 except AttributeError: pass 417 418 return super(cDocument, self).refetch_payload(ignore_changes = ignore_changes)
419 #--------------------------------------------------------
420 - def get_descriptions(self, max_lng=250):
421 """Get document descriptions. 422 423 - will return a list of rows 424 """ 425 if max_lng is None: 426 cmd = u"SELECT pk, text FROM blobs.doc_desc WHERE fk_doc = %s" 427 else: 428 cmd = u"SELECT pk, substring(text from 1 for %s) FROM blobs.doc_desc WHERE fk_doc=%%s" % max_lng 429 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_obj]}]) 430 return rows
431 #--------------------------------------------------------
432 - def add_description(self, description=None):
433 cmd = u"insert into blobs.doc_desc (fk_doc, text) values (%s, %s)" 434 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': [self.pk_obj, description]}]) 435 return True
436 #--------------------------------------------------------
437 - def update_description(self, pk=None, description=None):
438 cmd = u"update blobs.doc_desc set text = %(desc)s where fk_doc = %(doc)s and pk = %(pk_desc)s" 439 gmPG2.run_rw_queries(queries = [ 440 {'cmd': cmd, 'args': {'doc': self.pk_obj, 'pk_desc': pk, 'desc': description}} 441 ]) 442 return True
443 #--------------------------------------------------------
444 - def delete_description(self, pk=None):
445 cmd = u"delete from blobs.doc_desc where fk_doc = %(doc)s and pk = %(desc)s" 446 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'doc': self.pk_obj, 'desc': pk}}]) 447 return True
448 #--------------------------------------------------------
449 - def _get_parts(self):
450 cmd = _sql_fetch_document_part_fields % u"pk_doc = %s" 451 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self.pk_obj]}], get_col_idx = True) 452 return [ cDocumentPart(row = {'pk_field': 'pk_obj', 'idx': idx, 'data': r}) for r in rows ]
453 454 parts = property(_get_parts, lambda x:x) 455 #--------------------------------------------------------
456 - def add_part(self, file=None):
457 """Add a part to the document.""" 458 # create dummy part 459 cmd = u""" 460 insert into blobs.doc_obj ( 461 fk_doc, data, seq_idx 462 ) VALUES ( 463 %(doc_id)s, 464 ''::bytea, 465 (select coalesce(max(seq_idx)+1, 1) from blobs.doc_obj where fk_doc=%(doc_id)s) 466 )""" 467 rows, idx = gmPG2.run_rw_queries ( 468 queries = [ 469 {'cmd': cmd, 'args': {'doc_id': self.pk_obj}}, 470 {'cmd': u"select currval('blobs.doc_obj_pk_seq')"} 471 ], 472 return_data = True 473 ) 474 # init document part instance 475 pk_part = rows[0][0] 476 new_part = cDocumentPart(aPK_obj = pk_part) 477 if not new_part.update_data_from_file(fname=file): 478 _log.error('cannot import binary data from [%s] into document part' % file) 479 gmPG2.run_rw_queries ( 480 queries = [ 481 {'cmd': u"delete from blobs.doc_obj where pk = %s", 'args': [pk_part]} 482 ] 483 ) 484 return None 485 new_part['filename'] = file 486 new_part.save_payload() 487 488 return new_part
489 #--------------------------------------------------------
490 - def add_parts_from_files(self, files=None, reviewer=None):
491 492 new_parts = [] 493 494 for filename in files: 495 new_part = self.add_part(file = filename) 496 if new_part is None: 497 msg = 'cannot instantiate document part object' 498 _log.error(msg) 499 return (False, msg, filename) 500 new_parts.append(new_part) 501 502 if reviewer is not None: 503 new_part['pk_intended_reviewer'] = reviewer # None == Null 504 success, data = new_part.save_payload() 505 if not success: 506 msg = 'cannot set reviewer to [%s]' % reviewer 507 _log.error(msg) 508 _log.error(str(data)) 509 return (False, msg, filename) 510 511 return (True, '', new_parts)
512 #--------------------------------------------------------
513 - def export_parts_to_files(self, export_dir=None, chunksize=0):
514 fnames = [] 515 for part in self.parts: 516 # FIXME: add guess_extension_from_mimetype 517 fname = os.path.basename(gmTools.coalesce ( 518 part['filename'], 519 u'%s%s%s_%s' % (part['l10n_type'], gmTools.coalesce(part['ext_ref'], '-', '-%s-'), _('part'), part['seq_idx']) 520 )) 521 if export_dir is not None: 522 fname = os.path.join(export_dir, fname) 523 fnames.append(part.export_to_file(aChunkSize = chunksize, filename = fname)) 524 return fnames
525 #--------------------------------------------------------
527 try: 528 return self.__has_unreviewed_parts 529 except AttributeError: 530 pass 531 532 cmd = u"SELECT EXISTS(SELECT 1 FROM blobs.v_obj4doc_no_data WHERE pk_doc = %(pk)s AND reviewed IS FALSE)" 533 args = {'pk': self.pk_obj} 534 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 535 self.__has_unreviewed_parts = rows[0][0] 536 537 return self.__has_unreviewed_parts
538 539 has_unreviewed_parts = property(_get_has_unreviewed_parts, lambda x:x) 540 #--------------------------------------------------------
541 - def set_reviewed(self, technically_abnormal=None, clinically_relevant=None):
542 # FIXME: this is probably inefficient 543 for part in self.parts: 544 if not part.set_reviewed(technically_abnormal, clinically_relevant): 545 return False 546 return True
547 #--------------------------------------------------------
548 - def set_primary_reviewer(self, reviewer=None):
549 for part in self.parts: 550 part['pk_intended_reviewer'] = reviewer 551 success, data = part.save_payload() 552 if not success: 553 _log.error('cannot set reviewer to [%s]' % reviewer) 554 _log.error(str(data)) 555 return False 556 return True
557 #------------------------------------------------------------
558 -def create_document(document_type=None, encounter=None, episode=None):
559 """Returns new document instance or raises an exception. 560 """ 561 cmd = u"""INSERT INTO blobs.doc_med (fk_type, fk_encounter, fk_episode) VALUES (%(type)s, %(enc)s, %(epi)s) RETURNING pk""" 562 try: 563 int(document_type) 564 except ValueError: 565 cmd = u""" 566 INSERT INTO blobs.doc_med ( 567 fk_type, 568 fk_encounter, 569 fk_episode 570 ) VALUES ( 571 coalesce ( 572 (SELECT pk from blobs.doc_type bdt where bdt.name = %(type)s), 573 (SELECT pk from blobs.doc_type bdt where _(bdt.name) = %(type)s) 574 ), 575 %(enc)s, 576 %(epi)s 577 ) RETURNING pk""" 578 579 args = {'type': document_type, 'enc': encounter, 'epi': episode} 580 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 581 doc = cDocument(aPK_obj = rows[0][0]) 582 return doc
583 #------------------------------------------------------------
584 -def search_for_document(patient_id=None, type_id=None):
585 """Searches for documents with the given patient and type ID. 586 587 No type ID returns all documents for the patient. 588 """ 589 # sanity checks 590 if patient_id is None: 591 raise ValueError('need patient id to search for document') 592 593 args = {'pat_id': patient_id, 'type_id': type_id} 594 if type_id is None: 595 cmd = u"SELECT pk_doc from blobs.v_doc_med WHERE pk_patient = %(pat_id)s" 596 else: 597 cmd = u"SELECT pk_doc from blobs.v_doc_med WHERE pk_patient = %(pat_id)s and pk_type = %(type_id)s" 598 599 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 600 601 docs = [] 602 for row in rows: 603 docs.append(cDocument(row[0])) 604 return docs
605 #------------------------------------------------------------
606 -def delete_document(document_id=None, encounter_id=None):
607 # will cascade to doc_obj and doc_desc 608 cmd = u"select blobs.delete_document(%(pk)s, %(enc)s)" 609 args = {'pk': document_id, 'enc': encounter_id} 610 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 611 return
612 #------------------------------------------------------------
613 -def reclassify_documents_by_type(original_type=None, target_type=None):
614 615 _log.debug('reclassifying documents by type') 616 _log.debug('original: %s', original_type) 617 _log.debug('target: %s', target_type) 618 619 if target_type['pk_doc_type'] == original_type['pk_doc_type']: 620 return True 621 622 cmd = u""" 623 update blobs.doc_med set 624 fk_type = %(new_type)s 625 where 626 fk_type = %(old_type)s 627 """ 628 args = {u'new_type': target_type['pk_doc_type'], u'old_type': original_type['pk_doc_type']} 629 630 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 631 632 return True
633 634 #============================================================
635 -class cDocumentType(gmBusinessDBObject.cBusinessDBObject):
636 """Represents a document type.""" 637 _cmd_fetch_payload = u"""select * from blobs.v_doc_type where pk_doc_type=%s""" 638 _cmds_store_payload = [ 639 u"""update blobs.doc_type set 640 name = %(type)s 641 where 642 pk=%(pk_obj)s and 643 xmin=%(xmin_doc_type)s""", 644 u"""select xmin_doc_type from blobs.v_doc_type where pk_doc_type = %(pk_obj)s""" 645 ] 646 _updatable_fields = ['type'] 647 #--------------------------------------------------------
648 - def set_translation(self, translation=None):
649 650 if translation.strip() == '': 651 return False 652 653 if translation.strip() == self._payload[self._idx['l10n_type']].strip(): 654 return True 655 656 rows, idx = gmPG2.run_rw_queries ( 657 queries = [ 658 {'cmd': u'select i18n.i18n(%s)', 'args': [self._payload[self._idx['type']]]}, 659 {'cmd': u'select i18n.upd_tx((select i18n.get_curr_lang()), %(orig)s, %(tx)s)', 660 'args': { 661 'orig': self._payload[self._idx['type']], 662 'tx': translation 663 } 664 } 665 ], 666 return_data = True 667 ) 668 if not rows[0][0]: 669 _log.error('cannot set translation to [%s]' % translation) 670 return False 671 672 return self.refetch_payload()
673 674 #------------------------------------------------------------
675 -def get_document_types():
676 rows, idx = gmPG2.run_ro_queries ( 677 queries = [{'cmd': u"SELECT * FROM blobs.v_doc_type"}], 678 get_col_idx = True 679 ) 680 doc_types = [] 681 for row in rows: 682 row_def = { 683 'pk_field': 'pk_doc_type', 684 'idx': idx, 685 'data': row 686 } 687 doc_types.append(cDocumentType(row = row_def)) 688 return doc_types
689 #------------------------------------------------------------
690 -def create_document_type(document_type=None):
691 # check for potential dupes: 692 cmd = u'select pk from blobs.doc_type where name = %s' 693 rows, idx = gmPG2.run_ro_queries ( 694 queries = [{'cmd': cmd, 'args': [document_type]}] 695 ) 696 if len(rows) == 0: 697 cmd1 = u"insert into blobs.doc_type (name) values (%s)" 698 cmd2 = u"select currval('blobs.doc_type_pk_seq')" 699 rows, idx = gmPG2.run_rw_queries ( 700 queries = [ 701 {'cmd': cmd1, 'args': [document_type]}, 702 {'cmd': cmd2} 703 ], 704 return_data = True 705 ) 706 return cDocumentType(aPK_obj = rows[0][0])
707 #------------------------------------------------------------
708 -def delete_document_type(document_type=None):
709 if document_type['is_in_use']: 710 return False 711 gmPG2.run_rw_queries ( 712 queries = [{ 713 'cmd': u'delete from blobs.doc_type where pk=%s', 714 'args': [document_type['pk_doc_type']] 715 }] 716 ) 717 return True
718 #------------------------------------------------------------
719 -def get_ext_ref():
720 """This needs *considerably* more smarts.""" 721 dirname = gmTools.get_unique_filename ( 722 prefix = '', 723 suffix = time.strftime(".%Y%m%d-%H%M%S", time.localtime()) 724 ) 725 # extract name for dir 726 path, doc_ID = os.path.split(dirname) 727 return doc_ID
728 #============================================================ 729 # main 730 #------------------------------------------------------------ 731 if __name__ == '__main__': 732 733 if len(sys.argv) < 2: 734 sys.exit() 735 736 if sys.argv[1] != u'test': 737 sys.exit() 738 739 #--------------------------------------------------------
740 - def test_doc_types():
741 742 print "----------------------" 743 print "listing document types" 744 print "----------------------" 745 746 for dt in get_document_types(): 747 print dt 748 749 print "------------------------------" 750 print "testing document type handling" 751 print "------------------------------" 752 753 dt = create_document_type(document_type = 'dummy doc type for unit test 1') 754 print "created:", dt 755 756 dt['type'] = 'dummy doc type for unit test 2' 757 dt.save_payload() 758 print "changed base name:", dt 759 760 dt.set_translation(translation = 'Dummy-Dokumenten-Typ fuer Unit-Test') 761 print "translated:", dt 762 763 print "deleted:", delete_document_type(document_type = dt) 764 765 return
766 #--------------------------------------------------------
767 - def test_adding_doc_part():
768 769 print "-----------------------" 770 print "testing document import" 771 print "-----------------------" 772 773 docs = search_for_document(patient_id=12) 774 doc = docs[0] 775 print "adding to doc:", doc 776 777 fname = sys.argv[1] 778 print "adding from file:", fname 779 part = doc.add_part(file=fname) 780 print "new part:", part 781 782 return
783 #--------------------------------------------------------
784 - def test_get_documents():
785 doc_folder = cDocumentFolder(aPKey=12) 786 787 #photo = doc_folder.get_latest_mugshot() 788 #print type(photo), photo 789 790 docs = doc_folder.get_documents() 791 for doc in docs: 792 print type(doc), doc 793 print doc.parts
794 #pprint(gmBusinessDBObject.jsonclasshintify(docs)) 795 #-------------------------------------------------------- 796 from Gnumed.pycommon import gmI18N 797 gmI18N.activate_locale() 798 gmI18N.install_domain() 799 800 #test_doc_types() 801 #test_adding_doc_part() 802 test_get_documents() 803 804 # print get_ext_ref() 805 806 #============================================================ 807