Changeset 15113 for main/waeup.aaue/trunk/src/waeup/aaue/applicants
- Timestamp:
- 23 Aug 2018, 06:43:06 (6 years ago)
- Location:
- main/waeup.aaue/trunk/src/waeup/aaue/applicants
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.aaue/trunk/src/waeup/aaue/applicants/applicant.py
r14829 r15113 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 … … 25 27 ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit, 26 28 IPUTMEApplicantEdit, ITranscriptApplicant, ICertificateRequest) 29 30 @grok.subscribe(ICustomApplicant, grok.IObjectRemovedEvent) 31 def custom_handle_applicant_removed(applicant, event): 32 """If an applicant is removed also pdf files of this applicant are removed. 33 """ 34 file_store = getUtility(IExtFileStore) 35 file_store.deleteFileByContext(applicant, attr='stateresult.pdf') 36 return 27 37 28 38 class CustomApplicant(NigeriaApplicant): -
main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser.py
r15100 r15113 224 224 ) 225 225 226 MAX_FILE_UPLOAD_SIZE = 1024 * 500 227 228 def handle_file_upload(upload, context, view, attr=None): 229 """Handle upload of applicant files. 230 231 Returns `True` in case of success or `False`. 232 233 Please note that file pointer passed in (`upload`) most probably 234 points to end of file when leaving this function. 235 """ 236 size = file_size(upload) 237 if size > MAX_FILE_UPLOAD_SIZE: 238 view.flash(_('Uploaded file is too big!')) 239 return False 240 dummy, ext = os.path.splitext(upload.filename) 241 ext.lower() 242 if ext != '.pdf': 243 view.flash(_('pdf file extension expected.')) 244 return False 245 upload.seek(0) # file pointer moved when determining size 246 store = getUtility(IExtFileStore) 247 file_id = IFileStoreNameChooser(context).chooseName(attr=attr) 248 store.createFile(file_id, upload) 249 return True 250 226 251 class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage): 227 252 """A display view for applicant data. 228 253 """ 254 255 @property 256 def file_links(self): 257 html = '' 258 pdf = getUtility(IExtFileStore).getFileByContext( 259 self.context, attr='stateresult.pdf') 260 if pdf: 261 html += '<a href="stateresult.pdf">Statement of Result</a>' 262 return html 229 263 230 264 @property … … 284 318 return '' 285 319 320 def update(self): 321 super(CustomApplicantDisplayFormPage, self).update() 322 self.extraform_url = self.url(self.context, 'stateresult.pdf') 323 return 324 286 325 class CustomPDFActionButton(PDFActionButton): 287 326 … … 386 425 return form_fields 387 426 427 def update(self): 428 super(CustomApplicantManageFormPage, self).update() 429 upload_stateresult = self.request.form.get('form.stateresult', None) 430 if upload_stateresult: 431 # We got a fresh stateresult upload 432 success = handle_file_upload( 433 upload_stateresult, self.context, self, attr='stateresult.pdf') 434 if success: 435 self.context.writeLogMessage(self, 'saved: stateresult') 436 else: 437 self.upload_success = False 438 self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE) 439 return 440 388 441 class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage): 389 442 """An applicant-centered edit view for applicant data. … … 400 453 if not self.request.form.get('confirm_passport', False): 401 454 return _('Passport picture confirmation box not ticked.') 455 if self.view.target in ('trans',) and \ 456 not store.getFileByContext(self.context, attr=u'stateresult.pdf'): 457 return _('No statement of result pdf file uploaded.') 458 402 459 return False 403 460 … … 460 517 form_fields['reg_number'].for_display = True 461 518 return form_fields 519 520 def update(self): 521 if self.context.locked or ( 522 self.context.__parent__.expired and 523 self.context.__parent__.strict_deadline): 524 self.emit_lock_message() 525 return 526 super(CustomApplicantEditFormPage, self).update() 527 upload_stateresult = self.request.form.get('form.stateresult', None) 528 if upload_stateresult: 529 # We got a fresh stateresult upload 530 success = handle_file_upload( 531 upload_stateresult, self.context, self, attr='stateresult.pdf') 532 if not success: 533 self.upload_success = False 534 self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE) 535 return 462 536 463 537 class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage): … … 587 661 return students_utils.renderPDF(self,'screening_data.pdf', 588 662 self.context, applicantview, note=self.note) 663 664 class StateResult(grok.View): 665 """Renders the pdf form extension for applicants. 666 """ 667 grok.name('stateresult.pdf') 668 grok.context(ICustomApplicant) 669 grok.require('waeup.viewApplication') 670 671 def render(self): 672 pdf = getUtility(IExtFileStore).getFileByContext( 673 self.context, attr='stateresult.pdf') 674 self.response.setHeader('Content-Type', 'application/pdf') 675 return pdf -
main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser_templates/applicantdisplaypage.pt
r14304 r15113 37 37 </td> 38 38 <tr> 39 <tr tal:condition="python: view.target in ('trans',)"> 40 <td class="fieldname" i18n:translate=""> 41 Files: 42 </td> 43 <td> 44 <span tal:replace="structure view/file_links" /> 45 </td> 46 </tr> 39 47 </tbody> 40 48 </table> -
main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser_templates/applicanteditpage.pt
r14555 r15113 42 42 </span> 43 43 <span tal:replace="view/max_upload_size">10 KB</span> 44 </tr> 45 <tr tal:condition="python: view.target in ('trans',)"> 46 <td class="fieldname" i18n:translate=""> 47 Statement of Result: 48 </td> 49 <td> 50 <p tal:condition="python: view.file_exists('stateresult.pdf')"> 51 <a href="stateresult.pdf" 52 i18n:translate=""> 53 Download pdf file 54 </a> 55 </p> 56 <div class="input-group half"> 57 <div class="input-group-btn"> 58 <div class="btn btn-default btn-file"> 59 Select… 60 <input type="file" name="form.stateresult" /> 61 </div> 62 </div> 63 <input type="text" class="form-control" readonly> 64 </div> 65 <span i18n:translate=""> 66 Max. file size: 67 </span> 68 <span tal:replace="view/max_file_upload_size">10 KB</span> 44 69 </tr> 45 70 <tr tal:condition="view/manage_applications"> -
main/waeup.aaue/trunk/src/waeup/aaue/applicants/tests/test_browser.py
r15099 r15113 20 20 import pytz 21 21 import os 22 from StringIO import StringIO 22 23 from zope.event import notify 23 24 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState 24 25 from zope.component import createObject, getUtility 25 26 from waeup.kofa.configuration import SessionConfiguration 26 from waeup.kofa.interfaces import IUserAccount 27 from waeup.kofa.interfaces import ( 28 IUserAccount, IExtFileStore, IFileStoreNameChooser) 27 29 from waeup.kofa.applicants.container import ApplicantsContainer 28 30 from waeup.kofa.browser.tests.test_pdf import samples_dir … … 285 287 self.assertFalse('Admitted Course of Study' in self.browser.contents) 286 288 return 289 290 def test_upload_stateresult_by_manager(self): 291 # Add trans applicants container 292 self.transcontainer = ApplicantsContainer() 293 self.transcontainer.mode = 'create' 294 self.transcontainer.code = u'trans%s' % session_1 295 self.transcontainer.prefix = u'trans' 296 self.transcontainer.application_category = u'no' 297 self.transcontainer.year = session_1 298 self.transcontainer.application_fee = 300.0 299 self.transcontainer.title = u'This is the trans%s container' % session_1 300 self.app['applicants'][self.transcontainer.code] = self.transcontainer 301 delta = datetime.timedelta(days=10) 302 self.transcontainer.startdate = datetime.datetime.now(pytz.utc) - delta 303 self.transcontainer.enddate = datetime.datetime.now(pytz.utc) + delta 304 # Add applicant 305 transapplicant = createObject(u'waeup.Applicant') 306 transapplicant.firstname = u'Anna' 307 transapplicant.lastname = u'Post' 308 self.app['applicants'][self.transcontainer.code].addApplicant(transapplicant) 309 self.transapplicant = self.app['applicants'][self.transcontainer.code][ 310 transapplicant.application_number] 311 self.transapplicant_view_path = ('http://localhost/app/applicants/trans%s/%s' 312 % (session_1, transapplicant.application_number)) 313 self.transapplicant_manage_path = ('http://localhost/app/applicants/trans%s/%s/manage' 314 % (session_1, transapplicant.application_number)) 315 # Login 316 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 317 self.browser.open(self.transapplicant_manage_path) 318 # Create a pseudo file with acceptable size 319 pdf_content = 'A' * 1024 * 300 # A string of 300 KB size 320 pseudo_pdf = StringIO(pdf_content) 321 ctrl = self.browser.getControl(name='form.stateresult') 322 file_ctrl = ctrl.mech_control 323 file_ctrl.add_file(pseudo_pdf, filename='myform.pdf') 324 self.browser.getControl("Save").click() # submit form 325 # Even though the form could not be saved ... 326 self.assertTrue('Required input is missing' in self.browser.contents) 327 # ... the file has been successfully uploaded 328 pdf_url = self.transapplicant_manage_path.replace('manage', 'stateresult.pdf') 329 self.browser.open(pdf_url) 330 self.assertEqual( 331 self.browser.headers['content-type'], 'application/pdf') 332 self.assertEqual(len(self.browser.contents), 307200) 333 # There is really a file stored for the applicant 334 storage = getUtility(IExtFileStore) 335 file_id = IFileStoreNameChooser(self.transapplicant).chooseName( 336 attr='stateresult.pdf') 337 # The stored file can be fetched 338 fd = storage.getFile(file_id) 339 file_len = len(fd.read()) 340 self.assertEqual(file_len, 307200) 341 # A file link is displayed on the edit view ... 342 self.browser.open(self.transapplicant_manage_path) 343 self.assertTrue('<a href="stateresult.pdf">' in self.browser.contents) 344 # ... and on the dislay view 345 self.browser.open(self.transapplicant_view_path) 346 self.assertTrue('<a href="stateresult.pdf">Statement of Result</a>' 347 in self.browser.contents) 348 # Adding file is properly logged 349 logfile = os.path.join( 350 self.app['datacenter'].storage, 'logs', 'applicants.log') 351 logcontent = open(logfile).read() 352 self.assertTrue( 353 'zope.mgr - waeup.aaue.applicants.browser.CustomApplicantManageFormPage' 354 ' - %s - saved: stateresult' 355 % (self.transapplicant.applicant_id) 356 in logcontent) 357 # When an applicant is removed, also the pdf files are gone. 358 del self.app['applicants'][self.transcontainer.code][self.transapplicant.application_number] 359 fd = storage.getFile(file_id) 360 self.assertTrue(fd is None)
Note: See TracChangeset for help on using the changeset viewer.