Changeset 17029 for main/kofacustom.edocons/trunk/src/kofacustom/edocons
- Timestamp:
- 23 Jul 2022, 08:08:45 (2 years ago)
- Location:
- main/kofacustom.edocons/trunk/src/kofacustom/edocons
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/applicant.py
r16639 r17029 23 23 from kofacustom.nigeria.applicants.applicant import NigeriaApplicant 24 24 from kofacustom.edocons.applicants.interfaces import( 25 ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit, IPUTMEApplicantEdit) 25 ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit, 26 IPUTMEApplicantEdit, ITranscriptApplicant) 26 27 27 28 class CustomApplicant(NigeriaApplicant): 28 29 29 30 grok.implements(ICustomApplicant, ICustomUGApplicantEdit, 30 ICustomPGApplicantEdit, IPUTMEApplicantEdit) 31 ICustomPGApplicantEdit, IPUTMEApplicantEdit, 32 ITranscriptApplicant) 31 33 grok.provides(ICustomApplicant) 32 34 -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/browser.py
r16853 r17029 54 54 ICustomPGApplicant, ICustomUGApplicant, ICustomApplicant, 55 55 ICustomPGApplicantEdit, ICustomUGApplicantEdit, 56 ICustomApplicantOnlinePayment, 56 ICustomApplicantOnlinePayment, ITranscriptApplicant, 57 57 ) 58 58 from kofacustom.nigeria.interfaces import MessageFactory as _ … … 94 94 'aggregate') 95 95 96 TSC_OMIT_FIELDS = ('locked', 'suspended', 97 ) 98 99 100 TSC_OMIT_EDIT_FIELDS = TSC_OMIT_FIELDS + ( 101 'applicant_id', 102 'proc_date', 103 ) 104 105 TSC_OMIT_MANAGE_FIELDS = TSC_OMIT_FIELDS + ( 106 'applicant_id',) 107 96 108 class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage): 97 109 """A display view for applicant data. … … 104 116 for field in PG_OMIT_DISPLAY_FIELDS: 105 117 form_fields = form_fields.omit(field) 118 elif self.target is not None and self.target.startswith('tsc'): 119 form_fields = grok.AutoFields(ITranscriptApplicant) 120 for field in TSC_OMIT_FIELDS: 121 form_fields = form_fields.omit(field) 122 return form_fields 106 123 else: 107 124 form_fields = grok.AutoFields(ICustomUGApplicant) 108 125 for field in UG_OMIT_DISPLAY_FIELDS: 109 126 form_fields = form_fields.omit(field) 127 form_fields['notice'].custom_widget = BytesDisplayWidget 110 128 #form_fields['perm_address'].custom_widget = BytesDisplayWidget 111 form_fields['notice'].custom_widget = BytesDisplayWidget112 129 if not getattr(self.context, 'student_id'): 113 130 form_fields = form_fields.omit('student_id') … … 134 151 for field in PG_OMIT_PDF_FIELDS: 135 152 form_fields = form_fields.omit(field) 153 elif self.target is not None and self.target.startswith('tsc'): 154 form_fields = grok.AutoFields(ITranscriptApplicant) 155 for field in TSC_OMIT_FIELDS: 156 form_fields = form_fields.omit(field) 157 return form_fields 136 158 else: 137 159 form_fields = grok.AutoFields(ICustomUGApplicant) … … 164 186 for field in PG_OMIT_MANAGE_FIELDS: 165 187 form_fields = form_fields.omit(field) 188 elif self.target is not None and self.target.startswith('tsc'): 189 form_fields = grok.AutoFields(ITranscriptApplicant) 190 for field in TSC_OMIT_MANAGE_FIELDS: 191 form_fields = form_fields.omit(field) 192 return form_fields 166 193 else: 167 194 form_fields = grok.AutoFields(ICustomUGApplicant) … … 185 212 for field in PG_OMIT_EDIT_FIELDS: 186 213 form_fields = form_fields.omit(field) 214 elif self.target is not None and self.target.startswith('tsc'): 215 form_fields = grok.AutoFields(ITranscriptApplicant) 216 for field in TSC_OMIT_EDIT_FIELDS: 217 form_fields = form_fields.omit(field) 218 return form_fields 187 219 else: 188 220 form_fields = grok.AutoFields(ICustomUGApplicantEdit) -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/interfaces.py
r16883 r17029 1 # -*- coding: utf-8 -*- 1 2 ## $Id$ 2 3 ## … … 20 21 21 22 from zope import schema 23 from zope.interface import invariant, Invalid 24 from zope.component import getUtility 25 from zope.catalog.interfaces import ICatalog 26 from zc.sourcefactory.basic import BasicSourceFactory 27 from waeup.kofa.university.vocabularies import StudyModeSource 22 28 from waeup.kofa.applicants.interfaces import ( 23 29 IApplicantBaseData, … … 25 31 from waeup.kofa.schoolgrades import ResultEntryField 26 32 from waeup.kofa.interfaces import ( 27 SimpleKofaVocabulary, academic_sessions_vocab, validate_email) 33 SimpleKofaVocabulary, academic_sessions_vocab, validate_email, 34 IKofaObject) 28 35 from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber 29 36 from waeup.kofa.students.vocabularies import nats_vocab, GenderSource … … 54 61 ) 55 62 63 DESTINATION_COST = { 64 #'none': ('To the moon', 1000000000.0, 1), 65 'nigeria': ('Within Nigeria', 20000.0, 1), 66 'africa': ('Within Africa ', 30000.0, 2), 67 'inter': ('International', 35000.0, 3), 68 'cert_nigeria': ('Certified Copy - Within Nigeria', 13000.0, 4), 69 'cert_africa': ('Certified Copy - Within Africa', 23000.0, 5), 70 'cert_inter': ('Certified Copy - International', 28000.0, 6), 71 } 72 73 class DestinationCostSource(BasicSourceFactory): 74 """A source that delivers continents and shipment costs. 75 """ 76 def getValues(self): 77 sorted_items = sorted(DESTINATION_COST.items(), 78 key=lambda element: element[1][2]) 79 return [item[0] for item in sorted_items] 80 81 def getToken(self, value): 82 return value 83 84 def getTitle(self, value): 85 return u"%s (₦ %s)" % ( 86 DESTINATION_COST[value][0], 87 DESTINATION_COST[value][1]) 88 89 class OrderSource(BasicSourceFactory): 90 """ 91 """ 92 def getValues(self): 93 return ['o', 'c'] 94 95 def getToken(self, value): 96 return value 97 98 def getTitle(self, value): 99 if value == 'o': 100 return _('Original') 101 if value == 'c': 102 return _('Certified True Copy') 103 104 class TranscriptCertificateSource(CertificateSource): 105 """Include Department and Faculty in Title. 106 """ 107 def getValues(self, context): 108 catalog = getUtility(ICatalog, name='certificates_catalog') 109 resultset = catalog.searchResults(code=(None, None)) 110 resultlist = sorted(resultset, key=lambda 111 value: value.__parent__.__parent__.__parent__.code + 112 value.__parent__.__parent__.code + 113 value.code) 114 return resultlist 115 116 def getTitle(self, context, value): 117 """ 118 """ 119 try: title = "%s / %s / %s (%s)" % ( 120 value.__parent__.__parent__.__parent__.title, 121 value.__parent__.__parent__.title, 122 value.title, value.code) 123 except AttributeError: 124 title = "NA / %s (%s)" % (value.title, value.code) 125 return title 126 56 127 class ICustomUGApplicant(INigeriaUGApplicant): 57 128 """An undergraduate applicant. … … 308 379 """ 309 380 310 311 class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant): 381 class ITranscriptApplicant(IKofaObject): 382 """A transcript applicant. 383 """ 384 385 suspended = schema.Bool( 386 title = _(u'Account suspended'), 387 default = False, 388 required = False, 389 ) 390 391 locked = schema.Bool( 392 title = _(u'Form locked'), 393 default = False, 394 required = False, 395 ) 396 397 applicant_id = schema.TextLine( 398 title = _(u'Transcript Application Id'), 399 required = False, 400 readonly = False, 401 ) 402 403 student_id = schema.TextLine( 404 title = _(u'Kofa Student Id'), 405 required = False, 406 readonly = False, 407 ) 408 409 matric_number = schema.TextLine( 410 title = _(u'Matriculation Number'), 411 readonly = False, 412 required = True, 413 ) 414 415 firstname = schema.TextLine( 416 title = _(u'First Name in School'), 417 required = True, 418 ) 419 420 middlename = schema.TextLine( 421 title = _(u'Middle Name in School'), 422 required = False, 423 ) 424 425 lastname = schema.TextLine( 426 title = _(u'Surname in School'), 427 required = True, 428 ) 429 430 date_of_birth = FormattedDate( 431 title = _(u'Date of Birth'), 432 required = False, 433 #date_format = u'%d/%m/%Y', # Use grok-instance-wide default 434 show_year = True, 435 ) 436 437 sex = schema.Choice( 438 title = _(u'Gender'), 439 source = GenderSource(), 440 required = True, 441 ) 442 443 #nationality = schema.Choice( 444 # vocabulary = nats_vocab, 445 # title = _(u'Nationality'), 446 # required = False, 447 # ) 448 449 email = schema.ASCIILine( 450 title = _(u'Email Address'), 451 required = True, 452 constraint=validate_email, 453 ) 454 455 phone = PhoneNumber( 456 title = _(u'Phone'), 457 description = u'', 458 required = False, 459 ) 460 461 #perm_address = schema.Text( 462 # title = _(u'Current Local Address'), 463 # required = False, 464 # readonly = False, 465 # ) 466 467 collected = schema.Bool( 468 title = _(u'Have you collected transcript before?'), 469 default = False, 470 required = False, 471 ) 472 473 entry_session = schema.Choice( 474 title = _(u'Academic Session of Entry'), 475 source = academic_sessions_vocab, 476 required = False, 477 readonly = False, 478 ) 479 480 end_session = schema.Choice( 481 title = _(u'Academic Session of Graduation'), 482 source = academic_sessions_vocab, 483 required = False, 484 readonly = False, 485 ) 486 487 entry_mode = schema.Choice( 488 title = _(u'Mode of Entry'), 489 source = StudyModeSource(), 490 required = False, 491 readonly = False, 492 ) 493 494 course_studied = schema.Choice( 495 title = _(u'Course of Study'), 496 source = TranscriptCertificateSource(), 497 description = u'Faculty / Department / Course', 498 required = True, 499 readonly = False, 500 ) 501 502 course_changed = schema.Choice( 503 title = _(u'Change of Study Course / Transfer'), 504 description = u'If yes, select previous course of study.', 505 source = TranscriptCertificateSource(), 506 readonly = False, 507 required = False, 508 ) 509 510 spillover_level = schema.Choice( 511 title = _(u'Spill-over'), 512 description = u'Any spill-over? If yes, select session of spill-over.', 513 source = academic_sessions_vocab, 514 required = False, 515 readonly = False, 516 ) 517 518 purpose = schema.TextLine( 519 title = _(u'Transcript Purpose'), 520 required = False, 521 ) 522 523 order = schema.Choice( 524 source = OrderSource(), 525 title = _(u'Type of Order'), 526 required = True, 527 ) 528 529 dispatch_address = schema.Text( 530 title = _(u'Recipient Body'), 531 description = u'Addresses (including email address and phone number) ' 532 'to which transcripts should be posted. ' 533 'All addresses must involve same courier charges.', 534 required = True, 535 readonly = False, 536 ) 537 538 charge = schema.Choice( 539 title = _(u'Transcript Charge'), 540 source = DestinationCostSource(), 541 required = True, 542 readonly = False, 543 ) 544 545 no_copies = schema.Choice( 546 title = _(u'Number of Copies'), 547 description = u'Must correspond with the number of dispatch addresses above.', 548 values=[1, 2, 3, 4], 549 required = False, 550 readonly = False, 551 default = 1, 552 ) 553 554 courier_tno = schema.TextLine( 555 title = _(u'Courier Tracking Number'), 556 required = False, 557 ) 558 559 proc_date = FormattedDate( 560 title = _(u'Processing Date'), 561 required = False, 562 #date_format = u'%d/%m/%Y', # Use grok-instance-wide default 563 show_year = True, 564 ) 565 566 @invariant 567 def type_of_order(applicant): 568 if not applicant.collected and applicant.order != 'o': 569 raise Invalid(_("If you haven't collected transcript before, type of order must be 'original'.")) 570 if applicant.order == 'o' and applicant.charge.startswith('cert_'): 571 raise Invalid(_("You've selected the wrong transcript charge.")) 572 if applicant.order == 'c' and not applicant.charge.startswith('cert_'): 573 raise Invalid(_("You've selected the wrong transcript charge.")) 574 575 576 class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant, 577 ITranscriptApplicant): 312 578 """An interface for both types of applicants. 313 579 -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/utils.py
r16767 r17029 47 47 'form.cbt_score': _(u'CBT Data'), 48 48 } 49 50 APP_TYPES_DICT = { 51 'app': ['General Studies', 'APP'], 52 'tsc': ['Transcript', 'TRF'], 53 } -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/interswitch/tests.py
r16845 r17029 59 59 self.student.nationality = u'NG' 60 60 self.browser.open(self.payments_path + '/addop') 61 self.browser.getControl(name="form.p_category").value = ['schoolfee ']61 self.browser.getControl(name="form.p_category").value = ['schoolfee_1'] 62 62 self.browser.getControl("Create ticket").click() 63 63 self.assertMatches('...ticket created...', … … 70 70 self.browser.contents) 71 71 self.assertTrue( 72 '<span> 40000.0</span>' in self.browser.contents)72 '<span>220000.0</span>' in self.browser.contents) 73 73 self.payment_url = self.browser.url 74 74 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() … … 77 77 self.assertEqual(self.student.current_mode, 'ug_ft') 78 78 self.assertTrue( 79 '<input type="hidden" name="amount" value="4030000" />' in 80 self.browser.contents) 81 self.assertTrue( 82 'item_name="School Fee (total amount)" item_amt="4000000" bank_id="31" acct_num="1489560452"' in 83 self.browser.contents) 84 self.browser.open(self.payments_path + '/addop') 85 self.browser.getControl(name="form.p_category").value = ['schoolfee_1'] 86 self.browser.getControl("Create ticket").click() 87 self.assertMatches('...ticket created...', 88 self.browser.contents) 89 self.browser.open(self.payments_path) 90 ctrl = self.browser.getControl(name='val_id') 91 self.value = ctrl.options[1] 92 self.browser.getLink(self.value).click() 93 self.assertMatches('...Amount Authorized...', 94 self.browser.contents) 95 self.assertTrue( 96 '<span>26400.0</span>' in self.browser.contents) 97 self.payment_url = self.browser.url 98 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 99 self.assertMatches('...<input type="hidden" name="pay_item_id" value="Default_Payable_MX26002" />...', 100 self.browser.contents) 101 self.assertEqual(self.student.current_mode, 'ug_ft') 102 self.assertTrue( 103 '<input type="hidden" name="amount" value="2670000" />' in 104 self.browser.contents) 105 self.assertTrue( 106 'item_name="School Fee (66% - 1st instalment)" item_amt="2640000" bank_id="31" acct_num="1489560452"' in 79 '<input type="hidden" name="amount" value="22030000" />' in 80 self.browser.contents) 81 self.assertTrue( 82 'item_name="School Fee - 1st instalment" item_amt="22000000" bank_id="31" acct_num="1489560452"' in 107 83 self.browser.contents) 108 84 … … 243 219 self.applicantscontainer.application_fee = 1000.0 244 220 self.browser.getControl(name="form.nationality").value = ['NG'] 221 self.browser.getControl(name="form.lga").value = ['zamfara_maru'] 245 222 self.browser.getControl(name="transition").value = ['start'] 246 223 self.browser.getControl("Save").click() -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/students/utils.py
r16709 r17029 60 60 return _(u'Session configuration object is not available.'), None 61 61 # Determine fee. 62 if category in ('schoolfee', 'schoolfee_1', 'secondinstal'): 63 try: 64 certificate = student['studycourse'].certificate 65 p_item = certificate.code 66 except (AttributeError, TypeError): 67 return _('Study course data are incomplete.'), None 68 if previous_session: 69 # Students can pay for previous sessions in all 70 # workflow states. Fresh students are excluded by the 71 # update method of the PreviousPaymentAddFormPage. 72 amount = getattr(certificate, 'school_fee_1', 0.0) 62 if category in ('schoolfee_1', 'secondinstal'): 63 if student.state == CLEARED: 64 pass 65 elif student.state == RETURNING: 66 # In case of returning school fee payment the 67 # payment session and level contain the values of 68 # the session the student has paid for. Payment 69 # session is always next session. 70 p_session, p_level = self.getReturningData(student) 71 academic_session = self._getSessionConfiguration(p_session) 72 if academic_session == None: 73 return _( 74 u'Session configuration object is not available.' 75 ), None 76 elif student.is_postgrad and student.state == PAID: 77 # Returning postgraduate students also pay for the 78 # next session but their level always remains the 79 # same. 80 p_session += 1 81 academic_session = self._getSessionConfiguration(p_session) 82 if academic_session == None: 83 return _( 84 u'Session configuration object is not available.' 85 ), None 73 86 else: 74 if category == 'secondinstal': 75 amount = 0.34 * getattr(certificate, 'school_fee_1', 0.0) 76 else: 77 if student.state == CLEARED: 78 amount = getattr(certificate, 'school_fee_1', 0.0) 79 elif student.state == RETURNING: 80 # In case of returning school fee payment the 81 # payment session and level contain the values of 82 # the session the student has paid for. Payment 83 # session is always next session. 84 p_session, p_level = self.getReturningData(student) 85 academic_session = self._getSessionConfiguration(p_session) 86 if academic_session == None: 87 return _( 88 u'Session configuration object is not available.' 89 ), None 90 amount = getattr(certificate, 'school_fee_1', 0.0) 91 elif student.is_postgrad and student.state == PAID: 92 # Returning postgraduate students also pay for the 93 # next session but their level always remains the 94 # same. 95 p_session += 1 96 academic_session = self._getSessionConfiguration(p_session) 97 if academic_session == None: 98 return _( 99 u'Session configuration object is not available.' 100 ), None 101 amount = getattr(certificate, 'school_fee_1', 0.0) 102 if category == 'schoolfee_1': 103 amount *= 0.66 87 return _('School fee payment not allowed. Wrong state.'), None 88 if category == 'schoolfee_1': 89 amount = 220000.0 90 elif category == 'secondinstal': 91 amount = 100000.0 104 92 elif category == 'clearance': 105 93 try: -
main/kofacustom.edocons/trunk/src/kofacustom/edocons/utils/utils.py
r16792 r17029 26 26 PAYMENT_CATEGORIES = { 27 27 'schoolfee': 'School Fee (total amount)', 28 'schoolfee_1': 'School Fee (66% - 1st instalment)',29 'secondinstal': 'School Fee (34% - 2nd instalment)',28 'schoolfee_1': 'School Fee - 1st instalment', 29 'secondinstal': 'School Fee - 2nd instalment', 30 30 'clearance': 'Acceptance Fee', 31 31 'hostel':'Hostel Fee', … … 42 42 43 43 SELECTABLE_PAYMENT_CATEGORIES = { 44 'schoolfee': 'School Fee (total amount)',45 'schoolfee_1': 'School Fee (66% - 1st instalment)',46 'secondinstal': 'School Fee (34% - 2nd instalment)',44 #'schoolfee': 'School Fee (total amount)', 45 'schoolfee_1': 'School Fee - 1st instalment', 46 'secondinstal': 'School Fee - 2nd instalment', 47 47 'hostel':'Hostel Fee', 48 48 }
Note: See TracChangeset for help on using the changeset viewer.