Gnumed Value Objects: 1. Introduction: Clinical items contain a group of fields that are always accessed together, typically through specific database views (eg. allergy items are accessed through v_i18n_patient_allergies database view). Each item is retrieved and stored as a dictionary of pairs field name -> value. Working with multiple items requires dealing with lists of such dictionaries, wich can be difficult and little object oriented. A value object is a class that groups related attributes/fields, forming a composite value. This class is used as the return type of a business method and provides an easy to deal with, object oriented way of abstract/represent and work with any clinical item. Clinical items need not correspond to clin_root_item descendants 1:1. The basic design rules of Gnumed Value Objects are: - Instances DO EXIST in the database - Each instance verifies its existence upon instantiation - Each instance does NOT verify FK targets existence - Each clinical item knows how to store updatable data and fetch all its attibutes in/for the respective base tables (eg allergy) - Creation of new entries in the database is NOT supported - Lazy fetching of fields is NOT supported 2. Design: a) cClinItem: Is the base class of all Gnumed clinical items. Most heavy lifting is done generically in this class. Fields: pk: clinical item primary key (eg. 'id', from 'allergy' for cAllergy). Used for fetching/updating attributes. _payload: list containing the values of all item fields in an ORDERED way. eg: [1, 5, 14, 5, 5, 11, 'Substance A', None, None, 'Penicillin', None, 'developed urticaria/dyspnoe this morning, eg. 12h after first tablet', , , 1, 'allergy', 'Reaction Y'] _idx: dictionary that maps field name -> order index in _payload list eg: {'id_item': 1, 'reaction': 11, 'substance': 6, 'id_episode': 4, 'generics': 8, 'id_patient': 2, 'generic_specific': 12, 'atc_code': 10, 'definite': 13, 'id_encounter': 5, 'comment': 16, 'substance_code': 7, 'id_health_issue': 3, 'id_type': 14, 'allergene': 9, 'type': 15, 'id': 0} _is_modified: boolean flag that indicates if any field of the item has been modified. Methods: __init__(self, aPKey = None, **kwargs): constructor. Takes primary key as argument. ### DOC PENDING **kwargs __del__(self): clean up code. __str__(self): raw string representation, useful for diagnostic dumps (_payload string representation). __getitem__(self, attribute): accessor method for object attributes. __setitem__(self, attribute, value): setter method for object attributes. _pre_init(self, **kwargs): ### DOC PENDING _post_init(self, **kwargs): ### DOC PENDING get_fields(self): retrieves a list containing all backend fetched field names (both updatable and not). get_updatable_fields(self): retrieves a list containing updatable field names eg: ['substance', 'substance_code', 'generics', 'allergene', 'atc_code', 'id_type', 'generic_specific', 'definite', 'reaction'] refetch_payload(self): fetchs all the attributes from backend. This can be used to force updates after a DB level notify. If the load goes right, True is returned. If the fetch operation couldn't be performed, False is returned. Tipically, False will be returned if refetch is invoked after the instance was programatically modified. save_payload(self): persists all the attributes if some of them have been modified (if _is_modified == True). b) Concrete items: Clinical item derived classes (eg. cAllergy) all but defines class level variables that will be accessed by cClinItem to perform all the value object tasks. _cmd_fetch_payload: query string that will be passed to gmPG.run_ro_query(). It must retrieve all column names along its values. eg: """select * from v_i18n_patient_allergies where id=%s""" _updatable_fields: list of updatable fields. _cmds_store_payload: It's important to perform row locking before writting operation. It is implemented as a *list* of cmds that will be passed to gmPG.run_commit(). self._payload values will be added in a parameter dict, hence the SQL cmds need to use the %(arg_name)s substitution format and arg_name must bean updatable field. eg: """select 1 from allergy where id=%(id)s for update""", """update allergy set substance=%(substance)s, substance_code=%(substance_code)s ... where id=%(id)s""" 3. Usage: a) General usage: allg = cAllergy(pk): instantiates a new allergy item, which will be found and retrieved from backed by its primary key 'pk'. print allg: dumps every attribute value attVal = vacc[att]: retrieves the value for attribute 'att' and asigns it to 'attVal' variable allg[att] = attVal: sets the attribute 'att' as 'attVal' value, if it's effectively updatable. If any non-updatable field is being modified, an exception is raised. allg.save_payload(): will persist the all attributes if any of them was modified. allg.get_fields(): yields a list of attributes allg.get_updatable_fields(): yields a list of updatable attributes alg.refetch_payload(): refresh attributes by reloading them from backend b) Example usage: allg = cAllergy(1) print allg attVal = allg['substance'] allg['substance'] = 'Substance X' allg.save_payload() allg.get_fields() allg.get_updatable_fields() alg.refetch_payload() 4. Development status: cClinItem: Done cHealthIssue: Pending cVaccination: Done cLabRequest: Done cLabResult: Done cAllergy: Done cReferral: Pending cRequest: Pending cPrescription: Pending