[Mpuls-commits] r578 - in wasko/branches/1.0: . waskaweb/controllers waskaweb/model
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Tue Aug 25 16:43:14 CEST 2009
Author: frank
Date: 2009-08-25 16:43:13 +0200 (Tue, 25 Aug 2009)
New Revision: 578
Modified:
wasko/branches/1.0/ChangeLog.txt
wasko/branches/1.0/waskaweb/controllers/case.py
wasko/branches/1.0/waskaweb/controllers/case_overview.py
wasko/branches/1.0/waskaweb/controllers/statement.py
wasko/branches/1.0/waskaweb/model/case.py
wasko/branches/1.0/waskaweb/model/phase_transition.py
wasko/branches/1.0/waskaweb/model/phases_factory.py
Log:
Establish new barriers for anonymization
Modified: wasko/branches/1.0/ChangeLog.txt
===================================================================
--- wasko/branches/1.0/ChangeLog.txt 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/ChangeLog.txt 2009-08-25 14:43:13 UTC (rev 578)
@@ -1,8 +1,40 @@
2009-08-25 Frank Koormann <frank.koormann at intevation.de>
+ Establish new barriers for anonymization (cases must be evaluable):
+ - finished CM or post-care phase are anonymizable
+ - exception: running CM mark as aborted is anonymizable, further
+ unfilled mandatory fields are set to "unknown"
+
+ * waskaweb/model/phase_transition.py (phase_end, phase_start):
+ New, return true if the current phase is corresponding.
+
+ * waskaweb/model/phases_factory.py (currentPhase):
+ New, initialize phase object.
+
+ * waskaweb/model/case.py (Case.getId): New.
+ (State.phasesAreCompleted): New, true if current phase is complete.
+ This implements special handling of aborted CM phase.
+
+ * waskaweb/controllers/case_overview.py
+ (CaseOverviewController._filterBundle): phasesAreCompleted added.
+
+ * waskaweb/controllers/statement.py: Updated messages.
+ (StatementController.declinePrivacyStatement): phasesAreCompleted and
+ _completeAnonymizedCase added.
+
+ * waskaweb/controllers/case.py: Updated messages.
+ (_determineAnonymizedCaseEndPhase): Helper, determine phase to be set.
+ (_completeAnonymizedCase): Helper, this implements the special
+ handling of aborted CM phase.
+ (CaseController.markForAnonymizeFromOverview,
+ CaseController.markForAnonymize): phasesAreCompleted and
+ _completeAnonymizedCase added.
+
+2009-08-25 Frank Koormann <frank.koormann at intevation.de>
+
* waskaweb/templates/casemanagement/caselist.mako:
Sync pending deletion and pending anonymization behavior: Cases are
- browsable for admins.
+ browseable for admins.
2009-08-19 Frank Koormann <frank.koormann at intevation.de>
Modified: wasko/branches/1.0/waskaweb/controllers/case.py
===================================================================
--- wasko/branches/1.0/waskaweb/controllers/case.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/controllers/case.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -58,6 +58,7 @@
from waskaweb.lib.helpers import dd_mm_YYYY, HH_MM
+from waskaweb.model import UNKNOWN_INT, UNKNOWN_DATE
from waskaweb.model.repeatgroup import AidObject, AidList
from waskaweb.model.user import *
from waskaweb.model.statement import *
@@ -72,12 +73,18 @@
from waskaweb.lib.security import checkRole
from waskaweb.model.document import listDocuments
from waskaweb.model.casedocument import DataSaveException
-from waskaweb.model.data import FilteredNodeComponentProxy
+from waskaweb.model.data import FilteredNodeComponentProxy, \
+ DateLeaf, IntLeaf, \
+ TextLeaf, \
+ RadioNode, ChoiceNode
from waskaweb.model.logbook import Logbook, LogbookEntry, LogbookEntryChecker
from waskaweb.model.phases import Phase
from waskaweb.model.phases_factory import RequiredFields
-from waskaweb.model.phase_transition import symbol_phase, phase_neighbors
+from waskaweb.model.phase_transition import symbol_phase, phase_symbol, \
+ phase_neighbors, phase_start, \
+ PHASE_DESCRIPTIONS, \
+ CLEAR_START, CLEAR_ENDE
from waskaweb.converter.wasko_v1v2 import WaskoV1V2
@@ -116,7 +123,7 @@
ANONYMIZE_CONFIRM = u"""Fallakte anonymisieren?"""
ANONYMIZE_CONFIRM_TEXT = u"""Wollen Sie wirklich die Fallakte anonymisieren und die personenbezogenen Daten unwiederbringlich verlieren?. Die Fallakte steht danach nicht mehr zur Bearbeitung zur Verfügung. Die anonymisierte Fallakte wird weiterhin in der Auswertung berücksichtigt werden."""
-MARKANONYMIZE_CONFIRM_TEXT = u"""Wollen Sie wirklich die Fallakte zum Anonymisieren freigeben? Die Fallakte steht Ihnen danach nicht mehr zur Bearbeitung zur Verfügung und wird der Administration zur Anonymisierung vorgelegt."""
+MARKANONYMIZE_CONFIRM_TEXT = u"""<p>Wollen Sie wirklich die Fallakte zum Anonymisieren freigeben? Die Fallakte steht Ihnen danach nicht mehr zur Bearbeitung zur Verfügung und wird der Administration zur Anonymisierung vorgelegt.</p><p><b>Die Fallakte wird in der Phase </b>'%s'<b> anonymisiert!</b>"""
ANONYMIZE_SUCCESS = u"""Fallakte anonymisiert!"""
ANONYMIZE_SUCCESS_TEXT = u"""Die personenbezogenen Daten der Fallakte wurden gelöscht und die Fallakte aus der Übersicht entfernt. Bitte klicken Sie auf "OK", um zur Fallaktenübersicht fortzufahren."""
@@ -126,7 +133,9 @@
MARKANONYMIZE_SUCCESS_TEXT = u"""Die Fallakten wurde zur Anonymisierung freigeben und liegt der Administration zur endgültigen Anonymisierung vor. Bitte klicken Sie auf "OK", um zur Fallaktenübersicht fortzufahren."""
MARKANONYMIZE_INCOMPLETE_PHASE_FAILED = u"""Anonymisierung nicht möglich."""
-MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT = u"""Eine Anonymisierung ist für dieser Fallakte derzeit nicht möglich. Bitte prüfen Sie, ob Sie Daten der Fallakte konsistent sind, und ob alle nötigen Pflichtfelder für die aktuelle oder zurückliegende Phasen ausgefüllt wurden. Erfüllen Sie die genannten Anforderungen zur Anonymisierung und Wiederholen Sie den Vorgang. Klicken Sie auf "OK", um fortzufahren."""
+MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT = u"""<p>Eine Anonymisierung ist für diese Fallakte derzeit nicht möglich: Es sind nur ausreichend valide Fallakten anonymisierbar.</p><p>Bitte prüfen Sie, ob die Daten der Fallakte konsistent sind und ob alle nötigen Pflichtfelder für die zurückliegenden Phasen ausgefüllt wurden. Ferner muss die Phase beendet sein.</p><p>Sollte es sich bei dem Fall hingegen um einen Abbruch handeln, dokumentieren Sie dies entsprechend bei 'Art der Beendigung' als Abbruch und füllen Sie 'Datum Beendigung CM' aus.</p><p>Erfüllen Sie die genannten Anforderungen zur Anonymisierung und wiederholen Sie den Vorgang.<br>Klicken Sie auf "OK", um fortzufahren.</p>"""
+MARKANONYMIZE_CLEARING_PHASE_FAILED_TEXT = u"""<p>Eine Anonymisierung ist für Fälle in der Eingangsdokumentation nicht vorgesehen.</p><p>Bitte löschen Sie diesen Fall entsprechend der Verwaltungsfunktion:<br>Überblick - Verwaltung - Abbruch der Eingangsdokumentation.</p><p>Klicken Sie auf "OK", um fortzufahren.</p>"""
+
IMPORT_FAILED = u"""Die Fallakte wurde nicht importiert!"""
IMPORT_FAILED_TEXT = u"""Bei dem Importieren der Datei ist ein Fehler aufgetreten. Es konnten keine Daten der Fallakte importiert werden. Klicken Sie auf "OK", um zum Import-Dialog fortzufahren."""
@@ -229,6 +238,51 @@
return render('/statement/dialogs/missing_statement.mako')
return decorator(validate)
+
+def _determineAnonymizedCaseEndPhase(case):
+ '''Determine the phase to be set for the anonymized case'''
+ current_phase = case.getState().getPhase()
+ if phase_start(current_phase):
+ end_phase = current_phase + 1
+ else:
+ end_phase = current_phase
+ return end_phase
+
+def _completeAnonymizedCase(case):
+ '''Fill all missing fields with "unknown" before mark for anonymization.
+
+ case: Case object
+ '''
+ required_fields = RequiredFields(g.formedTree)
+ # Special code to set "unbekannt" for missing fields.
+ end_phase = _determineAnonymizedCaseEndPhase(case)
+ fields = {}
+ missing = required_fields.missingFields(
+ phase_symbol(end_phase))
+ for field in missing:
+ fieldname = field.getName()
+ if isinstance(field, DateLeaf):
+ fields[fieldname] = '01.01.0001'
+ elif isinstance(field, IntLeaf):
+ fields[fieldname] = '-9999999'
+ elif isinstance(field, TextLeaf):
+ fields[fieldname] = 'unbekannt'
+ elif isinstance(field, RadioNode) \
+ or isinstance(field, ChoiceNode) :
+ if fieldname in ('hilfm_1','hilfm_2','hilfm_3'):
+ if g.formedTree.getData(fieldname) == -1:
+ fields[fieldname] = '0'
+ elif fieldname == 'cm_end_art':
+ pass # Due to a bug in rules/missing fields
+ # this is added to the list
+ else:
+ fields[fieldname] = '-3'
+ # Store
+ g.formedTree.setData(fields, case.getId())
+ # Set the phase
+ case.getState().setPhase(end_phase)
+
+
class CaseController(CasebaseController):
def __before__(self):
@@ -1313,21 +1367,28 @@
case = load_case(id)
# Check if the case is in a consistent state (all required fields
# are filled)
- if not case.getState().phasesAreConsistent() and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER):
+ if (not case.getState().phasesAreConsistent() or not case.getState().phasesAreCompleted()) and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER):
c.notification_for = MARKANONYMIZE_INCOMPLETE_PHASE_FAILED
- c.notification_text = MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT
+ if case.getState().getPhase() in (CLEAR_START, CLEAR_ENDE):
+ c.notification_text = \
+ MARKANONYMIZE_CLEARING_PHASE_FAILED_TEXT
+ else:
+ c.notification_text = \
+ MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT
c.url_ok = h.url_for(controller="/case_overview")
return render('/casemanagement/dialogs/failed_markanonymize_phase_incomplete_from_overview.mako')
if confirmed == 1:
state = case.getState().setState(4)
if state:
+ _completeAnonymizedCase(case)
c.success_for = MARKANONYMIZE_SUCCESS
c.success_text = MARKANONYMIZE_SUCCESS_TEXT
c.url_ok = h.url_for(controller="/case_overview")
return render('/casemanagement/dialogs/success_markanonymize.mako')
else:
c.confirm_for = ANONYMIZE_CONFIRM
- c.question = MARKANONYMIZE_CONFIRM_TEXT
+ c.question = MARKANONYMIZE_CONFIRM_TEXT % \
+ PHASE_DESCRIPTIONS[_determineAnonymizedCaseEndPhase(case)]
c.url_yes = "/case/markForAnonymize/%s/1" % id
c.url_no = h.url_for(controller="/case_overview")
return render('/casemanagement/dialogs/confirm_markanonymizeFromOverview.mako')
@@ -1344,21 +1405,28 @@
c.form_navigation = self._getFormNavigation()
# Check if the case is in a consistent state (all required fields
# are filled)
- if not case.getState().phasesAreConsistent() and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER):
+ if (not case.getState().phasesAreConsistent() or not case.getState().phasesAreCompleted()) and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER):
c.notification_for = MARKANONYMIZE_INCOMPLETE_PHASE_FAILED
- c.notification_text = MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT
+ if case.getState().getPhase() in (CLEAR_START, CLEAR_ENDE):
+ c.notification_text = \
+ MARKANONYMIZE_CLEARING_PHASE_FAILED_TEXT
+ else:
+ c.notification_text = \
+ MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT
c.url_ok = "/case/digest/%s" % id
return render('/casemanagement/dialogs/failed_markanonymize_phase_incomplete.mako')
if confirmed == 1:
state = case.getState().setState(4)
if state:
+ _completeAnonymizedCase(case)
c.success_for = MARKANONYMIZE_SUCCESS
c.success_text = MARKANONYMIZE_SUCCESS_TEXT
c.url_ok = h.url_for(controller="/case_overview")
return render('/casemanagement/dialogs/success_markanonymize.mako')
else:
c.confirm_for = ANONYMIZE_CONFIRM
- c.question = MARKANONYMIZE_CONFIRM_TEXT
+ c.question = MARKANONYMIZE_CONFIRM_TEXT % \
+ PHASE_DESCRIPTIONS[_determineAnonymizedCaseEndPhase(case)]
c.url_yes = "/case/markForAnonymize/%s/1" % id
c.url_no = "/case/digest/%s" % id
return render('/casemanagement/dialogs/confirm_markanonymize.mako')
Modified: wasko/branches/1.0/waskaweb/controllers/case_overview.py
===================================================================
--- wasko/branches/1.0/waskaweb/controllers/case_overview.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/controllers/case_overview.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -475,7 +475,7 @@
filtered = []
for case in case_bundle.getCases(filtered_cases):
state = case.getState()
- if filter_inconsistent and (not state.phasesAreConsistent() and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER)):
+ if filter_inconsistent and ((not state.phasesAreConsistent() or not state.phasesAreCompleted()) and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER)):
continue
if state.getState() in allowedstates:
filtered.append(case.id)
Modified: wasko/branches/1.0/waskaweb/controllers/statement.py
===================================================================
--- wasko/branches/1.0/waskaweb/controllers/statement.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/controllers/statement.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -32,17 +32,24 @@
import logging
from waskaweb.lib.base import *
+from waskaweb.lib.search import INCONSISTENCY_CHECK_AFTER
from waskaweb.controllers.CaseBase import CasebaseController
from waskaweb.model.repeatgroup import AidList
from waskaweb.model.agency import *
from waskaweb.model.case import *
from waskaweb.model.statement import *
from waskaweb.lib.security import checkRole
-
+from waskaweb.model.phase_transition import PHASE_DESCRIPTIONS, \
+ CLEAR_START, CLEAR_ENDE
from waskaweb.controllers.case import ANONYMIZE_CONFIRM, \
MARKANONYMIZE_CONFIRM_TEXT, \
MARKANONYMIZE_SUCCESS, \
- MARKANONYMIZE_SUCCESS_TEXT
+ MARKANONYMIZE_SUCCESS_TEXT, \
+ MARKANONYMIZE_INCOMPLETE_PHASE_FAILED, \
+ MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT,\
+ MARKANONYMIZE_CLEARING_PHASE_FAILED_TEXT, \
+ _completeAnonymizedCase, \
+ _determineAnonymizedCaseEndPhase
log = logging.getLogger(__name__)
@@ -57,6 +64,10 @@
#SET_EE_DECLINE_SUCCESS_TEXT = u"""Die personenbezogenen Daten der Fallakte wurden gelöscht und die Fallakte aus der Übersicht entfernt. Bitte klicken Sie auf "OK", um zur Fallaktenübersicht fortzufahren."""
SET_EE_DECLINE_FAILED_HEADER = u"""Fallakte wurde nicht anonymisiert!"""
SET_EE_DECLINE_FAILED_TEXT = u"""Bei dem Anonymisieren der Fallakte ist ein Fehler aufgetreten. Die Fallakte wurde nicht anonymisiert. Bitte klicken Sie auf "OK", um zur Fallaktenübersicht fortzufahren."""
+MARK_EE_DECLINE_INCOMPLETE_PHASE_FAILED = u"""Die Einwilligungserklärung wurde nicht zurückgezogen!"""
+MARK_EE_DECLINE_INCOMPLETE_PHASE_FAILED_TEXT = u"""<p>Das Zurückziehen der Einwilligungserklärung führt zur Anonymisierung der Akte.</p>%s""" % MARKANONYMIZE_INCOMPLETE_PHASE_FAILED_TEXT
+MARK_EE_DECLINE_CLEARING_PHASE_FAILED_TEXT = u"""<p>Das Zurückziehen der Einwilligungserklärung führt zur Anonymisierung der Akte.</p>%s""" % MARKANONYMIZE_CLEARING_PHASE_FAILED_TEXT
+
class StatementController(CasebaseController):
def __before__(self):
@@ -140,6 +151,16 @@
confirmed = self._checkBool(confirmed)
case = self._loadCase(id)
c.form_navigation = self._getFormNavigation()
+ if (not case.getState().phasesAreConsistent() or not case.getState().phasesAreCompleted()) and case.isYoungerThan(INCONSISTENCY_CHECK_AFTER):
+ c.notification_for = MARK_EE_DECLINE_INCOMPLETE_PHASE_FAILED
+ if case.getState().getPhase() in (CLEAR_START, CLEAR_ENDE):
+ c.notification_text = \
+ MARK_EE_DECLINE_CLEARING_PHASE_FAILED_TEXT
+ else:
+ c.notification_text = \
+ MARK_EE_DECLINE_INCOMPLETE_PHASE_FAILED_TEXT
+ c.url_ok = "/case/digest/%s" % id
+ return render('/casemanagement/dialogs/failed_markanonymize_phase_incomplete.mako')
if confirmed:
try:
statement = case.getPrivacyStatement()
@@ -147,6 +168,7 @@
# Mark case for anonymizion
case.getState().setState(4)
+ _completeAnonymizedCase(case)
# TODO: Think about refreshing the state of the privacy statement
# in the statement model
session_case = session.get('case')
@@ -163,7 +185,8 @@
return render('/statement/dialogs/ee_decline_failed.mako')
else:
c.confirm_for = ANONYMIZE_CONFIRM
- c.question = MARKANONYMIZE_CONFIRM_TEXT
+ c.question = MARKANONYMIZE_CONFIRM_TEXT % \
+ PHASE_DESCRIPTIONS[_determineAnonymizedCaseEndPhase(case)]
c.url_yes = h.url_for(
controller="statement", \
action="declinePrivacyStatement", \
Modified: wasko/branches/1.0/waskaweb/model/case.py
===================================================================
--- wasko/branches/1.0/waskaweb/model/case.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/model/case.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -52,9 +52,11 @@
from waskaweb.model.statement import PrivacyStatement, AidPlanStatement, DiscretionStatement
from waskaweb.model.document import listDocuments
-from waskaweb.model.phase_transition import phase_description
-from waskaweb.model.phases_factory import RequiredFields
+from waskaweb.model.phase_transition import phase_description, phase_end, \
+ CM_START, CLEAR_START, CLEAR_ENDE
+from waskaweb.model.phases_factory import RequiredFields
+
from waskaweb.lib.helpers import dd_mm_yyyy_HH_MM, dd_mm_YYYY
from os import tmpnam, unlink
@@ -877,6 +879,9 @@
traceback.print_exc(file=sys.stderr)
return False
+ def getId(self):
+ return self.id
+
def getMode(self):
session = self.getSessionCase()
return session.getMode()
@@ -1225,6 +1230,33 @@
#if case.id in error_cases: return False
return True
+ def phasesAreCompleted(self):
+ '''Returns True if the required fields for the ending of the
+ current phase pair are completed and the phase ist finished.
+ Else False.'''
+ cf = self.getPhase()
+ rf = RequiredFields(g.formedTree)
+ current_phase = rf.currentPhase(cf)
+
+ # WASKO requires a special handling of CM_START:
+ # - if CM_START is completed and
+ # - cm_end_art == 3 (Abbruch) and
+ # - datum_cm_ende is set.
+ if cf == CM_START:
+ if current_phase.isRecursiveComplete() \
+ and g.formedTree.getData('cm_end_art') == 3 \
+ and g.formedTree.getData('datum_cm_ende') \
+ and str(g.formedTree.getData('datum_cm_ende')) != '0001-01-01':
+ return True
+ else:
+ return False
+ elif cf == CLEAR_START or cf == CLEAR_ENDE:
+ return False
+ elif phase_end(cf) and current_phase.isRecursiveComplete():
+ return True
+ else:
+ return False
+
def getAccessTime(self, format=None):
if format:
try:
Modified: wasko/branches/1.0/waskaweb/model/phase_transition.py
===================================================================
--- wasko/branches/1.0/waskaweb/model/phase_transition.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/model/phase_transition.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -38,6 +38,9 @@
NB_START = 4
NB_ENDE = 5
+PHASE_STARTINGS = (CLEAR_START,CM_START,NB_START)
+PHASE_ENDINGS = (CLEAR_ENDE,CM_ENDE,NB_ENDE)
+
# dictionary for GUI
PHASE_DESCRIPTIONS = {
UNKNOWN : u"Unbekannt",
@@ -122,4 +125,12 @@
print >> sys.stderr, "missing key in phase_neighbors:", ke
return False
+def phase_end(phase):
+ '''Return True if the current phase is the end part of a phase pair.'''
+ return phase in PHASE_ENDINGS
+
+def phase_start(phase):
+ '''Return True if the current phase is the start part of a phase pair.'''
+ return phase in PHASE_STARTINGS
+
# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8:
Modified: wasko/branches/1.0/waskaweb/model/phases_factory.py
===================================================================
--- wasko/branches/1.0/waskaweb/model/phases_factory.py 2009-08-25 13:47:52 UTC (rev 577)
+++ wasko/branches/1.0/waskaweb/model/phases_factory.py 2009-08-25 14:43:13 UTC (rev 578)
@@ -308,4 +308,15 @@
return pairs
+ def currentPhase(required_fields, current_phase):
+
+ symbol = phase_symbol(current_phase)
+ cur_phase = Phase(
+ current_phase,
+ True,
+ required_fields.isPhaseComplete(symbol),
+ required_fields.getPhaseTime(symbol),
+ required_fields.getLinkListForPhase(symbol, None, None))
+ return cur_phase
+
# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
More information about the Mpuls-commits
mailing list