Index: WAeUP_SRP/base/ScratchCards.py
===================================================================
--- WAeUP_SRP/base/ScratchCards.py	(revision 3074)
+++ WAeUP_SRP/base/ScratchCards.py	(revision 3076)
@@ -128,6 +128,49 @@
     ###)
 
-
-    security.declareProtected(ModifyPortalContent,"getUnusedPins")
+    security.declareProtected(ModifyPortalContent,"archiveBatch") ###(
+    def archiveBatch(self,delete=False):
+        """archive a batch"""
+        #import pdb;pdb.set_trace()
+        batch = self.getContent()
+        member = self.portal_membership.getAuthenticatedMember()
+        logger = logging.getLogger('ScratchCards.archiveBatch')
+        nr = batch.no_of_pins
+        prefix = batch.prefix
+        sold = batch.sold_by
+        cost = batch.cost
+        batch_no = batch.batch_no
+        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
+        export_file = "%s/export/%s-%s_archive_%s.csv" % (i_home,prefix,batch_no,current)
+        lines = []
+        fields = ['prefix','cost','serial','pin','student']
+        headline = ','.join(fields)
+        out = open(export_file,"wb")
+        out.write(headline +'\n')
+        out.write('%(prefix)s,%(cost)8.2f,%(batch_no)d,%(nr)d,%(sold)s\n' % vars())
+        out.close()
+        out = open(export_file,"a")
+        csv_writer = csv.DictWriter(out,fields,)
+        pins = self.portal_pins(prefix_batch = "%(prefix)s%(batch_no)d" % vars())
+        logger.info('%s starts archiving %s_%s with %s records ' % (member,
+                                                                    prefix,
+                                                                    batch_no,
+                                                                    len(pins)))
+            
+        pin_list = []
+        for pin in pins:
+            pin_list += pin.pin,
+            lines.append(self.portal_pins.record2dict(fields,pin))
+        total = len(lines)
+        csv_writer.writerows(lines)
+        msg = "wrote %(total)d records to %(export_file)s" % vars()
+        logger.info(msg)
+        if delete:
+            for pin in pin_list:
+                self.deleteRecord(pin)
+            msg = "deleted %(total)d pin from pins_catalog" % len(pin_list)
+            logger.info(msg)
+    ###)
+
+    security.declareProtected(ModifyPortalContent,"getUnusedPins") ###(
     def getUnusedPins(self):
         """return a list of unused Pins"""
@@ -144,6 +187,7 @@
             return unused[-max_pins:]
         return unused
-
-    security.declareProtected(View,"getUsedPins")
+    ###)
+
+    security.declareProtected(View,"getUsedPins") ###(
     def getUsedPins(self):
         """return a list of used Pins"""
@@ -159,6 +203,7 @@
                                                ) if p.student]
         return used
-
-    security.declareProtected(View,"getNumberOfUsedPins")
+    ###)
+
+    security.declareProtected(View,"getNumberOfUsedPins") ###(
     def getNumberOfUsedPins(self):
         """return the number of used Pins"""
@@ -173,4 +218,5 @@
                                                ) if p.student]
         return len(used)
+    ###)
 
 InitializeClass(ScratchCardBatch)
Index: WAeUP_SRP/base/skins/waeup_pins/archive.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_pins/archive.py	(revision 3076)
+++ WAeUP_SRP/base/skins/waeup_pins/archive.py	(revision 3076)
@@ -0,0 +1,32 @@
+## Script (Python) "archive"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=ids=[], REQUEST=None
+##title=
+##
+# $Id$
+"""
+FIXME: add docstring.
+"""
+try:
+    from Products.zdb import set_trace
+except:
+    def set_trace():
+        pass
+
+import logging
+logger = logging.getLogger('Skins.archive')
+member_id = str(context.portal_membership.getAuthenticatedMember())
+if ids:
+    for id in ids:
+        ob = getattr(context, id)
+        ob['archiveBatch']()
+    message = 'portal_status_message=%s archived' % ' '.join(ids)
+else:
+    message = 'portal_status_message=psm_select_at_least_one_document'
+
+if REQUEST is not None:
+    return REQUEST.RESPONSE.redirect("%s?%s" % (context.absolute_url(), message))
Index: WAeUP_SRP/base/skins/waeup_pins/archive_delete.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_pins/archive_delete.py	(revision 3076)
+++ WAeUP_SRP/base/skins/waeup_pins/archive_delete.py	(revision 3076)
@@ -0,0 +1,30 @@
+## Script (Python) "archive_delete"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=ids=[], REQUEST=None
+##title=
+##
+# $Id$
+"""
+archive and delte PIN batches
+"""
+
+import logging
+logger = logging.getLogger('Skins.archive_delete')
+member_id = str(context.portal_membership.getAuthenticatedMember())
+
+if ids:
+    for id in ids:
+        ob = getattr(context, id)
+        ob['archiveBatch'](delete=True)
+    message = 'portal_status_message=%s archived and deleted' % ' '.join(ids)
+    context.manage_delObjects(ids)
+else:
+    message = 'portal_status_message=select at least one batch to archive and delete'
+
+if REQUEST is not None:
+    return REQUEST.RESPONSE.redirect("%s?%s" % (context.absolute_url(), message))
+    
Index: WAeUP_SRP/base/skins/waeup_pins/pins_view.pt
===================================================================
--- WAeUP_SRP/base/skins/waeup_pins/pins_view.pt	(revision 3074)
+++ WAeUP_SRP/base/skins/waeup_pins/pins_view.pt	(revision 3076)
@@ -56,6 +56,51 @@
       <br />
       <h3>PIN Batches</h3>
-      <br />
-      <form action="." method="get">
+      <form action="." method="post" class="group"
+            tal:define="rows info/batches;
+            choosen_ids info/choosen_ids|python:[]"
+            >
+        <table class="contentListing" width="100%">      
+          <tr tal:repeat="line rows"
+            tal:attributes="class python:test(repeat['line'].even(), 'even ajaxtd', 'odd ajaxtd')">
+            <span tal:repeat="row line">
+              <td align="left" valign="middle" style="width: 5px;">
+                <input type="checkbox" name="ids:list" value="" id="" class="noborder"
+                       tal:define="id row"
+                       tal:attributes="value id;
+                       id python:'cb_' + id;
+                       checked python:id in choosen_ids;" 
+                       />
+              </td>
+              <td><a href="view" tal:attributes="href string:${context/absolute_url}/${row}">
+                  <strong tal:content="row" /></a> </td>
+            </span>
+          </tr>
+        </table>
+        <table width="100%" cellspacing="0" cellpadding="2"
+               class="folderButtons">
+          <tr>
+            <td align="left" valign="top" rowspan="3"></td>
+            <td align="left" valign="top">
+                <input tal:condition="nothing" type="button" value="button_select_all" class="context"
+                       onclick="someJavaScriptFunctionThatWillBeReplaced"
+                       i18n:attributes="value"
+                       tal:attributes="onclick python:'toggleSelect(this, \'%s\', \'%s\')'
+                       % (cpsmcat('button_select_all'), cpsmcat('button_deselect_all'))"
+                       />
+                <input type="submit" name="archive:method" value="archive"
+                       class="destructive" i18n:attributes="value"
+                       tal:attributes="onclick python:'return window.confirm(\'%s\')' %
+                       ('confirm archive', )" 
+                       />
+                <input type="submit" name="archive_delete:method" value="archive + delete"
+                       class="destructive" i18n:attributes="value"
+                       tal:attributes="onclick python:'return window.confirm(\'%s\')' %
+                       ('confirm archive and delete', )" 
+                       />
+            </td>
+          </tr>
+        </table>
+      </form>
+      <form action="." method="get" tal:condition="nothing">
         <select class="form-element" name=":action" 
                 tal:attributes="onChange string:location.href='${context/absolute_url}/'+this.options[this.selectedIndex].value"
Index: WAeUP_SRP/base/skins/waeup_pins/search_pins.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_pins/search_pins.py	(revision 3074)
+++ WAeUP_SRP/base/skins/waeup_pins/search_pins.py	(revision 3076)
@@ -12,4 +12,9 @@
 list Students for ClearanceOfficers
 """
+try:
+    from Products.zdb import set_trace
+except:
+    def set_trace():
+        pass
 
 request = REQUEST
@@ -111,5 +116,14 @@
     batches = context.objectIds()
     batches.sort()
-    info['batches'] = batches
+    l = []
+    cols = 6
+    rows,rest = divmod(len(batches),cols)
+    for r in range(rows):
+        von = r*cols
+        l += batches[von:von+cols],
+    if rest:
+        von = r*cols + cols
+        l += batches[von:von+rest],
+    info['batches'] = l
     view = context.pins_view
 if psm == '':
