Changeset 15530


Ignore:
Timestamp:
31 Jul 2019, 10:49:59 (5 years ago)
Author:
Henrik Bettermann
Message:

Implement Verification of Result/Transcript? and Certificate application form.

Location:
main/waeup.aaue/trunk/src/waeup/aaue/applicants
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/applicant.py

    r15113 r15530  
    3434    file_store = getUtility(IExtFileStore)
    3535    file_store.deleteFileByContext(applicant, attr='stateresult.pdf')
     36    file_store.deleteFileByContext(applicant, attr='verificationdoc.pdf')
    3637    return
    3738
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser.py

    r15521 r15530  
    5151    ITranscriptApplicant,
    5252    ICertificateRequest,
    53     ICustomApplicant
     53    ICustomApplicant,
     54    IVerificationRequest
    5455    )
    5556
     
    260261        if pdf:
    261262            html += '<a href="stateresult.pdf">Statement of Result</a>'
     263        pdf = getUtility(IExtFileStore).getFileByContext(
     264            self.context, attr='verificationdoc.pdf')
     265        if pdf:
     266            html += '<a href="verificationdoc.pdf">Result/Certificate Document</a>'
    262267        return html
    263268
     
    269274            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
    270275            form_fields['perm_address'].custom_widget = BytesDisplayWidget
     276            return form_fields
     277        if self.target is not None and self.target == 'ver':
     278            form_fields = grok.AutoFields(IVerificationRequest).omit(
     279                'locked', 'suspended')
     280            form_fields['body_address'].custom_widget = BytesDisplayWidget
    271281            return form_fields
    272282        if self.target is not None and self.target == 'cert':
     
    318328        return ''
    319329
    320     def update(self):
    321         super(CustomApplicantDisplayFormPage, self).update()
    322         self.extraform_url = self.url(self.context, 'stateresult.pdf')
    323         return
     330    #def update(self):
     331    #    super(CustomApplicantDisplayFormPage, self).update()
     332    #    #self.extraform_url = self.url(self.context, 'stateresult.pdf')
     333    #    return
    324334
    325335class CustomPDFActionButton(PDFActionButton):
     
    407417            form_fields['applicant_id'].for_display = True
    408418            return form_fields
     419        if self.target is not None and self.target == 'ver':
     420            form_fields = grok.AutoFields(IVerificationRequest)
     421            form_fields['applicant_id'].for_display = True
     422            return form_fields
    409423        # AAUE is using the same interface for all regular applications.
    410424        form_fields = grok.AutoFields(ICustomUGApplicant)
     
    428442        super(CustomApplicantManageFormPage, self).update()
    429443        upload_stateresult = self.request.form.get('form.stateresult', None)
     444        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
    430445        if upload_stateresult:
    431446            # We got a fresh stateresult upload
     
    434449            if success:
    435450                self.context.writeLogMessage(self, 'saved: stateresult')
     451            else:
     452                self.upload_success = False
     453        if upload_verificationdoc:
     454            # We got a fresh verificationdoc upload
     455            success = handle_file_upload(
     456                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
     457            if success:
     458                self.context.writeLogMessage(self, 'saved: verificationdoc')
    436459            else:
    437460                self.upload_success = False
     
    518541                for field in ('firstname', 'middlename', 'lastname'):
    519542                    form_fields[field].for_display = True
     543            return form_fields
     544        if self.target is not None and self.target == 'ver':
     545            form_fields = grok.AutoFields(IVerificationRequest).omit(
     546                'locked', 'suspended')
     547            form_fields['applicant_id'].for_display = True
    520548            return form_fields
    521549        # AAUE is using the same interface for all regular applications.
     
    563591        super(CustomApplicantEditFormPage, self).update()
    564592        upload_stateresult = self.request.form.get('form.stateresult', None)
     593        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
    565594        if upload_stateresult:
    566595            # We got a fresh stateresult upload
    567596            success = handle_file_upload(
    568597                upload_stateresult, self.context, self, attr='stateresult.pdf')
     598            if not success:
     599                self.upload_success = False
     600        if upload_verificationdoc:
     601            # We got a fresh verificationdoc upload
     602            success = handle_file_upload(
     603                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
    569604            if not success:
    570605                self.upload_success = False
     
    711746        self.response.setHeader('Content-Type', 'application/pdf')
    712747        return pdf
     748
     749class VerificationDoc(grok.View):
     750    """Renders the pdf form extension for applicants.
     751    """
     752    grok.name('verificationdoc.pdf')
     753    grok.context(ICustomApplicant)
     754    grok.require('waeup.viewApplication')
     755
     756    def render(self):
     757        pdf = getUtility(IExtFileStore).getFileByContext(
     758            self.context, attr='verificationdoc.pdf')
     759        self.response.setHeader('Content-Type', 'application/pdf')
     760        return pdf
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser_templates/applicantdisplaypage.pt

    r15503 r15530  
    3737      </td>
    3838    <tr>
    39     <tr tal:condition="python: view.target in ('trans', 'cert')">
     39    <tr tal:condition="python: view.target in ('trans', 'cert', 'ver')">
    4040      <td class="fieldname" i18n:translate="">
    4141        Files:
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser_templates/applicanteditpage.pt

    r15503 r15530  
    2222    <tbody>
    2323      <tal:widgets content="structure provider:widgets" />
    24       <tr>
     24      <tr tal:condition="python: context.__parent__.with_picture">
    2525        <td class="fieldname" i18n:translate="">
    2626          Passport Photo:
     
    6868          <span tal:replace="view/max_file_upload_size">10 KB</span>
    6969      </tr>
     70      <tr tal:condition="python: view.target in ('ver',)">
     71        <td class="fieldname" i18n:translate="">
     72          Scanned Document:
     73        </td>
     74        <td>
     75          <p tal:condition="python: view.file_exists('verificationdoc.pdf')">
     76            <a href="verificationdoc.pdf"
     77               i18n:translate="">
     78              Download pdf file
     79            </a>
     80          </p>
     81          <div class="input-group half">
     82            <div class="input-group-btn">
     83              <div class="btn btn-default btn-file">
     84                Select&hellip;
     85              <input type="file" name="form.verificationdoc" />
     86              </div>
     87            </div>
     88            <input type="text" class="form-control" readonly>
     89          </div>
     90          <span i18n:translate="">
     91            PDF files only. Max. file size:
     92          </span>
     93          <span tal:replace="view/max_file_upload_size">10 KB</span>
     94      </tr>
    7095      <tr tal:condition="view/manage_applications">
    7196        <td class="fieldname" i18n:translate="">Password:</td>
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/interfaces.py

    r15462 r15530  
    6060    )
    6161
     62document_types_vocab = SimpleKofaVocabulary(
     63    (_('Certificate'), 'certificate'),
     64    (_('Result'), 'result'),
     65    (_('Transcript'), 'transcript'),
     66    (_('Studentship'), 'studship'),
     67    )
     68
    6269class ICustomUGApplicant(IApplicantBaseData):
    6370    """An undergraduate applicant.
     
    793800
    794801
     802class IVerificationRequest(IKofaObject):
     803    """A applicant asking for verification.
     804    """
     805
     806    suspended = schema.Bool(
     807        title = _(u'Account suspended'),
     808        default = False,
     809        required = False,
     810        )
     811
     812    locked = schema.Bool(
     813        title = _(u'Form locked'),
     814        default = False,
     815        required = False,
     816        )
     817
     818    applicant_id = schema.TextLine(
     819        title = _(u'Applicant Id'),
     820        required = False,
     821        readonly = False,
     822        )
     823
     824    #reg_number = TextLineChoice(
     825    #    title = _(u'Kofa Registration Number'),
     826    #    readonly = False,
     827    #    required = True,
     828    #    source = contextual_reg_num_source,
     829    #    )
     830
     831    firstname = schema.TextLine(
     832        title = _(u'First Name'),
     833        required = True,
     834        )
     835
     836    middlename = schema.TextLine(
     837        title = _(u'Middle Name'),
     838        required = False,
     839        )
     840
     841    lastname = schema.TextLine(
     842        title = _(u'Last Name (Surname)'),
     843        required = True,
     844        )
     845
     846    email = schema.ASCIILine(
     847        title = _(u'Email Address'),
     848        required = True,
     849        constraint=validate_email,
     850        )
     851
     852    matric_number = schema.TextLine(
     853        title = _(u'Verification Body Reference Number'),
     854        readonly = False,
     855        required = True,
     856        )
     857
     858    body_address = schema.Text(
     859        title = _(u'Verification Body Address'),
     860        required = True,
     861        )
     862
     863    document_type = schema.Choice(
     864        title = _(u'Document Type'),
     865        vocabulary = document_types_vocab,
     866        required = True,
     867        )
     868
     869
    795870class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
    796                        ITranscriptApplicant, ICertificateRequest):
     871                       ITranscriptApplicant, ICertificateRequest,
     872                       IVerificationRequest):
    797873    """An interface for all types of applicants.
    798874
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/tests/test_browser.py

    r15462 r15530  
    381381        fd = storage.getFile(file_id)
    382382        self.assertTrue(fd is None)
     383
     384    def test_upload_verificationdoc_by_manager(self):
     385        # Add ver applicants container
     386        self.vercontainer = ApplicantsContainer()
     387        self.vercontainer.mode = 'create'
     388        self.vercontainer.code = u'ver%s' % session_1
     389        self.vercontainer.prefix = u'ver'
     390        self.vercontainer.application_category = u'no'
     391        self.vercontainer.year = session_1
     392        self.vercontainer.application_fee = 300.0
     393        self.vercontainer.title = u'This is the ver%s container' % session_1
     394        self.app['applicants'][self.vercontainer.code] = self.vercontainer
     395        delta = datetime.timedelta(days=10)
     396        self.vercontainer.startdate = datetime.datetime.now(pytz.utc) - delta
     397        self.vercontainer.enddate = datetime.datetime.now(pytz.utc) + delta
     398        # Add applicant
     399        verapplicant = createObject(u'waeup.Applicant')
     400        verapplicant.firstname = u'Anna'
     401        verapplicant.lastname = u'Post'
     402        self.app['applicants'][self.vercontainer.code].addApplicant(verapplicant)
     403        self.verapplicant = self.app['applicants'][self.vercontainer.code][
     404            verapplicant.application_number]
     405        self.verapplicant_view_path = ('http://localhost/app/applicants/ver%s/%s'
     406            % (session_1, verapplicant.application_number))
     407        self.verapplicant_manage_path = ('http://localhost/app/applicants/ver%s/%s/manage'
     408            % (session_1, verapplicant.application_number))
     409        # Login
     410        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     411        self.browser.open(self.verapplicant_manage_path)
     412        # Create a pseudo file with acceptable size
     413        pdf_content = 'A' * 1024 * 300  # A string of 300 KB size
     414        pseudo_pdf = StringIO(pdf_content)
     415        ctrl = self.browser.getControl(name='form.verificationdoc')
     416        file_ctrl = ctrl.mech_control
     417        file_ctrl.add_file(pseudo_pdf, filename='myform.pdf')
     418        self.browser.getControl("Save").click() # submit form
     419        # Even though the form could not be saved ...
     420        self.assertTrue('Required input is missing' in self.browser.contents)
     421        # ... the file has been successfully uploaded
     422        pdf_url = self.verapplicant_manage_path.replace('manage', 'verificationdoc.pdf')
     423        self.browser.open(pdf_url)
     424        self.assertEqual(
     425            self.browser.headers['content-type'], 'application/pdf')
     426        self.assertEqual(len(self.browser.contents), 307200)
     427        # There is really a file stored for the applicant
     428        storage = getUtility(IExtFileStore)
     429        file_id = IFileStoreNameChooser(self.verapplicant).chooseName(
     430            attr='verificationdoc.pdf')
     431        # The stored file can be fetched
     432        fd = storage.getFile(file_id)
     433        file_len = len(fd.read())
     434        self.assertEqual(file_len, 307200)
     435        # A file link is displayed on the edit view ...
     436        self.browser.open(self.verapplicant_manage_path)
     437        self.assertTrue('<a href="verificationdoc.pdf">' in self.browser.contents)
     438        # ... and on the dislay view
     439        self.browser.open(self.verapplicant_view_path)
     440        self.assertTrue('<a href="verificationdoc.pdf">Result/Certificate Document</a>'
     441            in self.browser.contents)
     442        # Adding file is properly logged
     443        logfile = os.path.join(
     444            self.app['datacenter'].storage, 'logs', 'applicants.log')
     445        logcontent = open(logfile).read()
     446        self.assertTrue(
     447            'zope.mgr - waeup.aaue.applicants.browser.CustomApplicantManageFormPage'
     448            ' - %s - saved: verificationdoc'
     449            % (self.verapplicant.applicant_id)
     450            in logcontent)
     451        # When an applicant is removed, also the pdf files are gone.
     452        del self.app['applicants'][self.vercontainer.code][self.verapplicant.application_number]
     453        fd = storage.getFile(file_id)
     454        self.assertTrue(fd is None)
  • main/waeup.aaue/trunk/src/waeup/aaue/applicants/utils.py

    r15385 r15530  
    4242        'bridge': ['Bridge Programme', 'BRI'],
    4343        'dsh': ['Science and Humanities Programme', 'DSH'],
     44        'ver': ['Verification Request', 'VR'],
    4445        }
    4546
Note: See TracChangeset for help on using the changeset viewer.