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