[Mpuls-commits] r435 - in wasko/trunk: . waskaweb/controllers waskaweb/lib waskaweb/model waskaweb/templates/casemanagement

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Mar 26 18:09:20 CET 2009


Author: teichmann
Date: 2009-03-26 18:09:19 +0100 (Thu, 26 Mar 2009)
New Revision: 435

Modified:
   wasko/trunk/ChangeLog.txt
   wasko/trunk/waskaweb/controllers/case_overview.py
   wasko/trunk/waskaweb/lib/excel.py
   wasko/trunk/waskaweb/lib/exportselection.py
   wasko/trunk/waskaweb/lib/renderer.py
   wasko/trunk/waskaweb/model/case.py
   wasko/trunk/waskaweb/templates/casemanagement/overview.mako
Log:
Re-added excel export.


Modified: wasko/trunk/ChangeLog.txt
===================================================================
--- wasko/trunk/ChangeLog.txt	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/ChangeLog.txt	2009-03-26 17:09:19 UTC (rev 435)
@@ -1,3 +1,21 @@
+2009-03-26	Sascha L. Teichmann <sascha.teichmann at intevation.de>
+
+	* waskaweb/model/case.py: Do not use temporary file any more.
+
+	* waskaweb/controllers/case_overview.py: set rendering for logbook
+	  and documents to flase in parts selection of XLS export.
+
+	* waskaweb/lib/excel.py: Rewrote it to scatter the master table
+	  to worksheets "Phase A", "Phase B" and "Phase C".
+
+	* waskaweb/lib/renderer.py: Corrected rendering of conditionals
+
+	* waskaweb/lib/exportselection.py: store projection of master
+	  table in parts selector.
+
+	* waskaweb/templates/casemanagement/overview.mako: Reenable excel
+	  export.
+
 2009-03-25	Torsten Irlaender  <torsten.irlaender at intevation.de> 
 
 	* waskaweb/controllers/caselifetime.py,

Modified: wasko/trunk/waskaweb/controllers/case_overview.py
===================================================================
--- wasko/trunk/waskaweb/controllers/case_overview.py	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/controllers/case_overview.py	2009-03-26 17:09:19 UTC (rev 435)
@@ -779,6 +779,8 @@
         c.store_action       = h.url_for(action="storeSelectedXLSParts")
         c.back_url           = h.url_for(controller='/case_overview', action='exportXLS', confirmed=1)
         c.back_title         = "XLS Export"
+        c.selectLogbook      = False
+        c.selectDocuments    = False
         page = render('casemanagement/selectParts.mako')
         return formencode.htmlfill.render(unicode(page, 'utf-8'),defaults=selection_checker.selections)
 

Modified: wasko/trunk/waskaweb/lib/excel.py
===================================================================
--- wasko/trunk/waskaweb/lib/excel.py	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/lib/excel.py	2009-03-26 17:09:19 UTC (rev 435)
@@ -30,20 +30,39 @@
 
 from types import StringTypes, IntType, LongType
 
-from pyExcelerator import Workbook
+from waskaweb.model.data     import WidgetCollector
 
 from exportselection import CasePartsSelection, SelectorFactory
 
+from StringIO import StringIO
+
+from pylons import g
+
+import sys
+
 FETCH_ALL_IDS = \
 """SELECT id FROM master_tbl_view"""
 
-RG_VIEWS = (
-    ("Kompetenzfeststellung", "kompetenzfestellung"),
-    ("Angebote BQ",           "angebote_berufliche_qualifizierung"),
-    ("Angebote BV",           "angebote_berufsvorbereitung"),
-    ("Angebote BB",           "angebote_bildenden_bereich"),
-    ("Angebote LB",           "angebote_lebensbewaeltigung"))
+class MyStringIO(StringIO):
 
+    def close(self):
+        pass
+
+    def real_close(self):
+        MyStringIO.close(self)
+
+class FakeStr(str):
+    def __init__(self, buf):
+        self.buf = buf
+
+def fake_file(x, *args):
+    return isinstance(x, FakeStr) and x.buf or file(x, *args)
+
+import pyExcelerator
+
+pyExcelerator.CompoundDoc.file = fake_file
+
+
 BLACK_LIST = set(['id', 'master_id', 'uuid_id', 'bearbeiter_id'])
 
 
@@ -57,107 +76,91 @@
         return x
     return str(x)
 
-class Sheet:
+class Sheet(object):
 
-    def __init__(self, worksheet, relation):
-        self.worksheet    = worksheet
-        self.relation     = relation
-        self.row          = 1
-        self.column_names = None
-        self.column       = 0
-        self.max_column   = 0
+    def __init__(self, worksheet, column_names):
 
+        for idx, name in enumerate(column_names):
+            worksheet.write(0, idx, name)
+
+        self.worksheet = worksheet
+        self.row       = 1
+        self.column    = 0
+
     def next_row(self):
-        if self.column > self.max_column:
-            self.max_column = self.column
+        self.row += 1
         self.column = 0
-        self.row += 1
 
-    def add_dataset(self, dataset):
-        if self.column_names is None:
-            self.column_names = [x[0] for x in dataset]
+    def add_data(self, value):
+        if not value is None:
+            self.worksheet.write(self.row, self.column, to_str(value))
+        self.column += 1
 
-        column    = self.column
-        row       = self.row
-        worksheet = self.worksheet
-        for x in dataset:
-            x = x[1]
-            if not x is None:
-                worksheet.write(row, column, to_str(x))
-            column += 1
-        self.column = column
+class Book:
 
-    def generate_header(self):
-        if self.column_names is None:
-            return
+    def __init__(self, selector):
+        self.selector = selector
 
-        num_names = max(1, len(self.column_names))
-        repeats = self.max_column / num_names
+        self.workbook  = pyExcelerator.Workbook()
 
-        worksheet = self.worksheet
+        phase_a_collector = WidgetCollector()
+        phase_b_collector = WidgetCollector()
+        phase_c_collector = WidgetCollector()
 
-        j = 0
-        for i in xrange(repeats):
-            suffix = i != 0 and ("$%d" % i) or ""
-            for name in self.column_names:
-                worksheet.write(0, j, "%s%s" % (name, suffix))
-                j += 1
+        phase_ee = g.formedTree.findByName('ee')
+        phase_a  = g.formedTree.findByName('phase-a')
+        phase_b  = g.formedTree.findByName('phase-b')
+        phase_c  = g.formedTree.findByName('phase-c')
 
-    def add_row(self, row):
-        columns = row._index.items() # XXX: hackish!
-        columns.sort(lambda a, b: cmp(a[1], b[1]))
-        self.add_dataset([(a[0], row[a[1]]) for a in columns if a[0] not in BLACK_LIST])
+        phase_ee.visit(phase_a_collector.visitor)
+        phase_a .visit(phase_a_collector.visitor)
+        phase_b .visit(phase_b_collector.visitor)
+        phase_c .visit(phase_c_collector.visitor)
 
-    def fetch_data(self, mid, cur, selector):
-        stmnt = selector.getSelectStatementByView(self.relation)
-        if not stmnt:
-            return
-        cur.execute(stmnt, { 'id': mid })
-        while True:
-            row = cur.fetchone()
-            if not row: break
-            self.add_row(row)
+        sheet_a = self.workbook.add_sheet("Phase A")
+        sheet_b = self.workbook.add_sheet("Phase B")
+        sheet_c = self.workbook.add_sheet("Phase C")
 
-class Master(Sheet):
-    def __init__(self, worksheet, relation):
-        Sheet.__init__(self, worksheet, relation)
+        projection = set(selector.master_projection)
 
-    def fetch_data(self, mid, cur, selector):
-        stmnt = selector.getSelectStatementByView(self.relation)
-        if not stmnt: return
-        cur.execute(stmnt, { 'id': mid })
-        row = cur.fetchone()
-        if not row: return
-        self.add_row(row)
+        a_names = [w.getName() for w in phase_a_collector.widgets if w.getName() in projection]
+        b_names = [w.getName() for w in phase_b_collector.widgets if w.getName() in projection]
+        c_names = [w.getName() for w in phase_c_collector.widgets if w.getName() in projection]
 
-class Book:
+        phase_a_sheet = Sheet(sheet_a, a_names)
+        phase_b_sheet = Sheet(sheet_b, b_names)
+        phase_c_sheet = Sheet(sheet_c, c_names)
 
-    def __init__(self, selector):
-        self.selector = selector
+        self.sheets = [phase_a_sheet, phase_b_sheet, phase_c_sheet]
 
-        self.workbook  = Workbook()
+        name2phase =      dict([(n, phase_a_sheet) for n in a_names])
+        name2phase.update(dict([(n, phase_b_sheet) for n in b_names]))
+        name2phase.update(dict([(n, phase_c_sheet) for n in c_names]))
 
-        sheets = [Master(self.workbook.add_sheet("Hauptdatensatz"), 'master_tbl')]
+        self.name2phase = name2phase
 
-        for rg in RG_VIEWS:
-            sheets.append(Sheet(self.workbook.add_sheet(rg[0]), rg[1]))
-
-        self.sheets = sheets
-
     def add_cases(self, case_ids, cur):
+        stmnt = self.selector.getSelectStatementByView("master_tbl")
+        if not stmnt: return
+        mid = {}
+        name2phase, sheets = self.name2phase, self.sheets
         for case_id in case_ids:
+            mid['id'] = case_id
+            cur.execute(stmnt, mid)
+            row = cur.fetchone()
+            if not row: continue
+            for desc, value in zip(cur.description, row):
+                try:
+                    name2phase[desc[0]].add_data(value)
+                except KeyError:
+                    pass
             for sheet in self.sheets:
-                sheet.fetch_data(case_id, cur, self.selector)
                 sheet.next_row()
 
-    def generate_headers(self):
-        for sheet in self.sheets:
-            sheet.generate_header()
-
     def write_xls(self, fname):
         self.workbook.save(fname)
 
-def exportAsXLS(cur, fname, ids=None, case_parts=None, anonymize=False):
+def exportAsXLS(cur, ids=None, case_parts=None, anonymize=False):
     if ids is None:
         ids = []
         cur.execute(FETCH_ALL_IDS)
@@ -175,7 +178,12 @@
 
     book = Book(selector)
     book.add_cases(ids, cur)
-    book.generate_headers()
-    book.write_xls(fname)
 
+    try:
+        out = MyStringIO()
+        book.write_xls(FakeStr(out))
+        return out.getvalue()
+    finally:
+        out.real_close()
+
 # vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

Modified: wasko/trunk/waskaweb/lib/exportselection.py
===================================================================
--- wasko/trunk/waskaweb/lib/exportselection.py	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/lib/exportselection.py	2009-03-26 17:09:19 UTC (rev 435)
@@ -132,11 +132,12 @@
 
     def __init__(self, anonymize=False, master_where="id = %(id)s", rg_where="master_id = %(id)s"):
         self.views = {}
-        self.exportDocuments = False
-        self.exportLogbook   = False
-        self.anonymize       = anonymize
-        self.master_where    = master_where
-        self.rg_where        = rg_where
+        self.exportDocuments   = False
+        self.exportLogbook     = False
+        self.anonymize         = anonymize
+        self.master_where      = master_where
+        self.rg_where          = rg_where
+        self.master_projection = None
 
     def getSelectStatementByView(self, view):
         return self.views.get(view)
@@ -152,6 +153,7 @@
             ", ".join(projection),
             relname,
             self.master_where)
+        self.master_projection = projection
 
 class SelectorFactory:
 

Modified: wasko/trunk/waskaweb/lib/renderer.py
===================================================================
--- wasko/trunk/waskaweb/lib/renderer.py	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/lib/renderer.py	2009-03-26 17:09:19 UTC (rev 435)
@@ -388,13 +388,13 @@
                 old_ro = self.ro_mode
                 self.ro_mode = True
                 for child in conditional.children:
-                    out = self._renderChild(child)
+                    self._renderChild(child)
                 self.ro_mode = old_ro
             else:
                 self.toTarget(Text(""), conditional.getTarget())
         else:
             for child in conditional.children:
-                out = self._renderChild(child)
+                self._renderChild(child)
 
     def _renderMatrix(self, node):
         description = node.getDescription()

Modified: wasko/trunk/waskaweb/model/case.py
===================================================================
--- wasko/trunk/waskaweb/model/case.py	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/model/case.py	2009-03-26 17:09:19 UTC (rev 435)
@@ -313,23 +313,10 @@
 
     def exportAsXLS(self, case_parts = None, anonymize=False):
         con, cur = None, None
-        fname = None
         try:
             con = db.getConnection()
-            cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
-            f = None
-            try:
-                fname = tmpnam() # security risk: symlink attacks
-                exportAsXLS(cur, fname, self.listDatasetIds(), case_parts, anonymize)
-                f = open(fname, "rb")
-                return f.read()
-            finally:
-                if f:
-                    try: f.close()
-                    except: pass
-                if fname:
-                    try: unlink(fname)
-                    except: pass
+            cur = con.cursor()
+            return exportAsXLS(cur, self.listDatasetIds(), case_parts, anonymize)
         finally:
             db.recycleConnection(con, cur)
 
@@ -1261,4 +1248,4 @@
             return int(maxage) - age.days
         return None
 
-# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
+# vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

Modified: wasko/trunk/waskaweb/templates/casemanagement/overview.mako
===================================================================
--- wasko/trunk/waskaweb/templates/casemanagement/overview.mako	2009-03-25 15:16:04 UTC (rev 434)
+++ wasko/trunk/waskaweb/templates/casemanagement/overview.mako	2009-03-26 17:09:19 UTC (rev 435)
@@ -37,7 +37,7 @@
       % endif
       % if h.hasRole(['admin_ka', 'cm_ka']):
         <option value="stand-in">Vertretung zuweisen</option>
-      ##<option value="exportXLS">Als Excel-Tabellen exportieren</option>
+      <option value="exportXLS">Als Excel-Tabellen exportieren</option>
       <option value="exportXML">Als XML-Datei exportieren</option>
       ##<option value="exportCSV">Als CSV-Datei exportieren</option>
       ##% if not c.hide_evaluation:



More information about the Mpuls-commits mailing list