Changeset 15878 for main/kofacustom.iuokada/trunk/src/kofacustom/iuokada
- Timestamp:
- 9 Dec 2019, 21:39:51 (5 years ago)
- Location:
- main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants/applicant.py
r15563 r15878 19 19 import grok 20 20 from zope.interface import implementedBy 21 from zope.component import getUtility 22 from waeup.kofa.interfaces import IExtFileStore 21 23 from waeup.kofa.applicants.applicant import ApplicantFactory 22 24 from waeup.kofa.utils.helpers import attrs_to_fields … … 24 26 from kofacustom.iuokada.applicants.interfaces import( 25 27 ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit, IPUTMEApplicantEdit) 28 29 @grok.subscribe(ICustomApplicant, grok.IObjectRemovedEvent) 30 def custom_handle_applicant_removed(applicant, event): 31 """If an applicant is removed also pdf files of this applicant are removed. 32 """ 33 file_store = getUtility(IExtFileStore) 34 file_store.deleteFileByContext(applicant, attr='stateresult.pdf') 35 return 26 36 27 37 class CustomApplicant(NigeriaApplicant): -
main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants/browser.py
r15809 r15878 19 19 """ 20 20 import grok 21 import os 22 from zope.component import getUtility 21 23 from zope.formlib.textwidgets import BytesDisplayWidget 24 from waeup.kofa.interfaces import ( 25 IExtFileStore, IFileStoreNameChooser) 26 from waeup.kofa.utils.helpers import string_from_bytes, file_size, now 22 27 from waeup.kofa.applicants.browser import ( 23 28 ApplicantRegistrationPage, ApplicantsContainerPage) … … 43 48 ) 44 49 from kofacustom.iuokada.applicants.interfaces import ( 45 ICustomPGApplicant, ICustomUGApplicant, 50 ICustomPGApplicant, ICustomUGApplicant, ICustomApplicant, 46 51 ICustomPGApplicantEdit, ICustomUGApplicantEdit, 47 52 ICustomApplicantOnlinePayment 48 53 ) 49 54 from kofacustom.iuokada.interfaces import MessageFactory as _ 55 56 MAX_FILE_UPLOAD_SIZE = 1024 * 500 57 58 def handle_file_upload(upload, context, view, attr=None): 59 """Handle upload of applicant files. 60 61 Returns `True` in case of success or `False`. 62 63 Please note that file pointer passed in (`upload`) most probably 64 points to end of file when leaving this function. 65 """ 66 size = file_size(upload) 67 if size > MAX_FILE_UPLOAD_SIZE: 68 view.flash(_('Uploaded file is too big!')) 69 return False 70 dummy, ext = os.path.splitext(upload.filename) 71 ext.lower() 72 if ext != '.pdf': 73 view.flash(_('pdf file extension expected.')) 74 return False 75 upload.seek(0) # file pointer moved when determining size 76 store = getUtility(IExtFileStore) 77 file_id = IFileStoreNameChooser(context).chooseName(attr=attr) 78 store.createFile(file_id, upload) 79 return True 50 80 51 81 class CustomApplicantsContainerPage(ApplicantsContainerPage): … … 73 103 74 104 @property 105 def file_links(self): 106 html = '' 107 pdf = getUtility(IExtFileStore).getFileByContext( 108 self.context, attr='stateresult.pdf') 109 if pdf: 110 html += '<a href="%s">Statement of Result</a>' % self.url( 111 self.context, 'stateresult.pdf') 112 return html 113 114 @property 75 115 def form_fields(self): 76 116 if self.target is not None and self.target.startswith('pg'): … … 112 152 return form_fields 113 153 154 def update(self): 155 super(CustomApplicantManageFormPage, self).update() 156 upload_stateresult = self.request.form.get('form.stateresult', None) 157 if upload_stateresult: 158 # We got a fresh stateresult upload 159 success = handle_file_upload( 160 upload_stateresult, self.context, self, attr='stateresult.pdf') 161 if success: 162 self.context.writeLogMessage(self, 'saved: stateresult') 163 else: 164 self.upload_success = False 165 self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE) 166 return 167 114 168 class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage): 115 169 """An applicant-centered edit view for applicant data. 116 170 """ 117 171 172 def dataNotComplete(self, data): 173 store = getUtility(IExtFileStore) 174 if self.context.__parent__.with_picture: 175 store = getUtility(IExtFileStore) 176 if not store.getFileByContext(self.context, attr=u'passport.jpg'): 177 return _('No passport picture uploaded.') 178 if not self.request.form.get('confirm_passport', False): 179 return _('Passport picture confirmation box not ticked.') 180 if self.context.subtype == 'transfer' and \ 181 not store.getFileByContext(self.context, attr=u'stateresult.pdf'): 182 return _('No statement of result pdf file uploaded.') 183 return False 184 118 185 @property 119 186 def form_fields(self): … … 129 196 form_fields['reg_number'].for_display = True 130 197 return form_fields 198 199 def update(self): 200 if self.context.locked or ( 201 self.context.__parent__.expired and 202 self.context.__parent__.strict_deadline): 203 self.emit_lock_message() 204 return 205 super(CustomApplicantEditFormPage, self).update() 206 upload_stateresult = self.request.form.get('form.stateresult', None) 207 if upload_stateresult: 208 # We got a fresh stateresult upload 209 success = handle_file_upload( 210 upload_stateresult, self.context, self, attr='stateresult.pdf') 211 if not success: 212 self.upload_success = False 213 self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE) 214 return 131 215 132 216 class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip): … … 152 236 return form_fields 153 237 238 class StateResult(grok.View): 239 """Renders the pdf form extension for applicants. 240 """ 241 grok.name('stateresult.pdf') 242 grok.context(ICustomApplicant) 243 grok.require('waeup.viewApplication') 244 245 def render(self): 246 pdf = getUtility(IExtFileStore).getFileByContext( 247 self.context, attr='stateresult.pdf') 248 self.response.setHeader('Content-Type', 'application/pdf') 249 return pdf -
main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants/tests/test_browser.py
r15563 r15878 19 19 Test the applicant-related UI components. 20 20 """ 21 import grok 22 import datetime 23 import pytz 21 24 import os 22 import datetime 25 from StringIO import StringIO 26 from zope.event import notify 23 27 from zope.component import createObject, getUtility 24 28 from zope.catalog.interfaces import ICatalog 25 29 from zope.intid.interfaces import IIntIds 26 30 from hurry.workflow.interfaces import IWorkflowState 31 from zope.component import createObject, getUtility 32 from waeup.kofa.configuration import SessionConfiguration 33 from waeup.kofa.interfaces import ( 34 IUserAccount, IExtFileStore, IFileStoreNameChooser) 27 35 from kofacustom.iuokada.testing import FunctionalLayer 36 from waeup.kofa.applicants.container import ApplicantsContainer 28 37 from waeup.kofa.browser.tests.test_pdf import samples_dir 29 from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup 38 from waeup.kofa.applicants.tests.test_browser import (ApplicantsFullSetup, 39 ApplicantsFullSetup, container_name_1, session_1) 30 40 from waeup.kofa.applicants.tests.test_batching import ApplicantImportExportSetup 31 41 from kofacustom.iuokada.applicants.export import CustomApplicantExporter … … 91 101 open(path, 'wb').write(self.browser.contents) 92 102 print "Sample application_slip.pdf written to %s" % path 103 104 def test_upload_stateresult_by_manager(self): 105 # Add trans applicants container 106 self.transcontainer = ApplicantsContainer() 107 self.transcontainer.mode = 'create' 108 self.transcontainer.code = u'ug%s' % session_1 109 self.transcontainer.prefix = u'ug' 110 self.transcontainer.application_category = u'no' 111 self.transcontainer.year = session_1 112 self.transcontainer.application_fee = 300.0 113 self.transcontainer.title = u'This is the ug%s container' % session_1 114 self.app['applicants'][self.transcontainer.code] = self.transcontainer 115 delta = datetime.timedelta(days=10) 116 self.transcontainer.startdate = datetime.datetime.now(pytz.utc) - delta 117 self.transcontainer.enddate = datetime.datetime.now(pytz.utc) + delta 118 # Add applicant 119 transapplicant = createObject(u'waeup.Applicant') 120 transapplicant.firstname = u'Anna' 121 transapplicant.lastname = u'Post' 122 transapplicant.subtype = 'transfer' 123 self.app['applicants'][self.transcontainer.code].addApplicant(transapplicant) 124 self.transapplicant = self.app['applicants'][self.transcontainer.code][ 125 transapplicant.application_number] 126 self.transapplicant_view_path = ('http://localhost/app/applicants/ug%s/%s' 127 % (session_1, transapplicant.application_number)) 128 self.transapplicant_manage_path = ('http://localhost/app/applicants/ug%s/%s/manage' 129 % (session_1, transapplicant.application_number)) 130 # Login 131 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 132 self.browser.open(self.transapplicant_manage_path) 133 # Create a pseudo file with acceptable size 134 pdf_content = 'A' * 1024 * 300 # A string of 300 KB size 135 pseudo_pdf = StringIO(pdf_content) 136 ctrl = self.browser.getControl(name='form.stateresult') 137 file_ctrl = ctrl.mech_control 138 file_ctrl.add_file(pseudo_pdf, filename='myform.pdf') 139 self.browser.getControl("Save").click() # submit form 140 # Even though the form could not be saved ... 141 self.assertTrue('Required input is missing' in self.browser.contents) 142 # ... the file has been successfully uploaded 143 pdf_url = self.transapplicant_manage_path.replace('manage', 'stateresult.pdf') 144 self.browser.open(pdf_url) 145 self.assertEqual( 146 self.browser.headers['content-type'], 'application/pdf') 147 self.assertEqual(len(self.browser.contents), 307200) 148 # There is really a file stored for the applicant 149 storage = getUtility(IExtFileStore) 150 file_id = IFileStoreNameChooser(self.transapplicant).chooseName( 151 attr='stateresult.pdf') 152 # The stored file can be fetched 153 fd = storage.getFile(file_id) 154 file_len = len(fd.read()) 155 self.assertEqual(file_len, 307200) 156 # A file link is displayed on the edit view ... 157 self.browser.open(self.transapplicant_manage_path) 158 self.assertTrue('<a href="stateresult.pdf">' in self.browser.contents) 159 # ... and on the dislay view 160 self.browser.open(self.transapplicant_view_path) 161 self.assertTrue('stateresult.pdf">Statement of Result</a>' 162 in self.browser.contents) 163 # Adding file is properly logged 164 logfile = os.path.join( 165 self.app['datacenter'].storage, 'logs', 'applicants.log') 166 logcontent = open(logfile).read() 167 self.assertTrue( 168 'zope.mgr - kofacustom.iuokada.applicants.browser.CustomApplicantManageFormPage' 169 ' - %s - saved: stateresult' 170 % (self.transapplicant.applicant_id) 171 in logcontent) 172 # When an applicant is removed, also the pdf files are gone. 173 del self.app['applicants'][self.transcontainer.code][self.transapplicant.application_number] 174 fd = storage.getFile(file_id) 175 self.assertTrue(fd is None)
Note: See TracChangeset for help on using the changeset viewer.