Changeset 8932 for main/waeup.futminna/trunk/src/waeup/futminna/applicants
- Timestamp:
- 7 Jul 2012, 10:48:31 (12 years ago)
- Location:
- main/waeup.futminna/trunk/src/waeup/futminna
- Files:
-
- 1 deleted
- 6 edited
- 4 copied
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.futminna/trunk/src/waeup/futminna
- Property svn:mergeinfo changed
/main/waeup.aaue/trunk/src/waeup/aaue merged: 8931 /main/waeup.uniben/trunk/src/waeup/uniben merged: 8928
- Property svn:mergeinfo changed
-
main/waeup.futminna/trunk/src/waeup/futminna/applicants/applicant.py
r8670 r8932 22 22 from waeup.kofa.utils.helpers import attrs_to_fields 23 23 from waeup.futminna.applicants.interfaces import( 24 ICustomApplicant, I UGApplicantEdit, IPGApplicantEdit, IPUTMEApplicantEdit)24 ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit, IPUTMEApplicantEdit) 25 25 26 26 class CustomApplicant(Applicant): 27 27 28 grok.implements(ICustomApplicant, I UGApplicantEdit,29 I PGApplicantEdit, IPUTMEApplicantEdit)28 grok.implements(ICustomApplicant, ICustomUGApplicantEdit, 29 ICustomPGApplicantEdit, IPUTMEApplicantEdit) 30 30 grok.provides(ICustomApplicant) 31 31 -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/browser.py
r8841 r8932 19 19 """ 20 20 import grok 21 from zope.component import getUtility 22 from zope.i18n import translate 23 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget 24 from waeup.kofa.students.interfaces import IStudentsUtils 25 from waeup.kofa.applicants.interfaces import ( 26 IApplicantRegisterUpdate, IApplicant, IApplicantEdit) 27 from waeup.kofa.applicants.browser import (ApplicantDisplayFormPage, 28 ExportPDFPage, 29 ApplicantManageFormPage, ApplicantEditFormPage, 30 ApplicantRegistrationPage, ApplicantAddFormPage, 31 OnlinePaymentDisplayFormPage, ApplicationFeePaymentAddPage, 32 OnlinePaymentBreadcrumb, ExportPDFPaymentSlipPage, 33 ApplicantBaseDisplayFormPage) 34 from waeup.kofa.applicants.viewlets import ( 35 PaymentReceiptActionButton, PDFActionButton) 36 from waeup.kofa.applicants.pdf import PDFApplicationSlip 21 from kofacustom.nigeria.applicants.browser import NigeriaApplicantEditFormPage 37 22 from waeup.futminna.applicants.interfaces import ( 38 IPGApplicant, IUGApplicant, IPGApplicantEdit, IUGApplicantEdit, 39 ICustomApplicantOnlinePayment, IPUTMEApplicantEdit, 40 UG_OMIT_DISPLAY_FIELDS, PG_OMIT_DISPLAY_FIELDS, 41 UG_OMIT_PDF_FIELDS, PG_OMIT_PDF_FIELDS, 42 UG_OMIT_MANAGE_FIELDS, PG_OMIT_MANAGE_FIELDS, 23 ICustomPGApplicantEdit, ICustomUGApplicantEdit, 24 IPUTMEApplicantEdit, 43 25 UG_OMIT_EDIT_FIELDS, PG_OMIT_EDIT_FIELDS, PUTME_OMIT_EDIT_FIELDS, 44 UG_OMIT_RESULT_SLIP_FIELDS) 45 from waeup.futminna.interfaces import MessageFactory as _ 46 47 class CustomOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb): 48 """A breadcrumb for payments. 49 """ 50 grok.context(ICustomApplicantOnlinePayment) 51 52 class PaymentReceiptActionButton(PaymentReceiptActionButton): 53 grok.order(4) 54 grok.context(ICustomApplicantOnlinePayment) 55 56 class PDFActionButton(PDFActionButton): 57 58 @property 59 def text(self): 60 if getattr(self.context, 'result_uploaded', False): 61 return _('Download result slip') 62 return _('Download application slip') 26 ) 63 27 64 28 65 class CustomPDFApplicationSlip(PDFApplicationSlip): 66 67 def _reduced_slip(self): 68 return getattr(self.context, 'result_uploaded', False) 69 70 @property 71 def note(self): 72 target = getattr(self.context.__parent__, 'prefix', None) 73 if target is not None and not target.startswith('pg') \ 74 and not self._reduced_slip(): 75 return _(u'<br /><br /><br />' 76 'Comfirm your exam venue 72 hours to the exam.') 77 return 78 79 @property 80 def form_fields(self): 81 target = getattr(self.context.__parent__, 'prefix', None) 82 if target is not None and target.startswith('pg'): 83 form_fields = grok.AutoFields(IPGApplicant) 84 for field in PG_OMIT_PDF_FIELDS: 85 form_fields = form_fields.omit(field) 86 else: 87 form_fields = grok.AutoFields(IUGApplicant) 88 if self._reduced_slip(): 89 for field in UG_OMIT_RESULT_SLIP_FIELDS: 90 form_fields = form_fields.omit(field) 91 else: 92 for field in UG_OMIT_PDF_FIELDS: 93 form_fields = form_fields.omit(field) 94 if not getattr(self.context, 'student_id'): 95 form_fields = form_fields.omit('student_id') 96 return form_fields 97 98 class CustomApplicantDisplayFormPage(ApplicantDisplayFormPage): 99 """A display view for applicant data. 100 """ 101 102 @property 103 def form_fields(self): 104 target = getattr(self.context.__parent__, 'prefix', None) 105 if target is not None and target.startswith('pg'): 106 form_fields = grok.AutoFields(IPGApplicant) 107 for field in PG_OMIT_DISPLAY_FIELDS: 108 form_fields = form_fields.omit(field) 109 else: 110 form_fields = grok.AutoFields(IUGApplicant) 111 for field in UG_OMIT_DISPLAY_FIELDS: 112 form_fields = form_fields.omit(field) 113 return form_fields 114 115 class CustomApplicantManageFormPage(ApplicantManageFormPage): 116 """A full edit view for applicant data. 117 """ 118 119 @property 120 def form_fields(self): 121 target = getattr(self.context.__parent__, 'prefix', None) 122 if target is not None and target.startswith('pg'): 123 form_fields = grok.AutoFields(IPGApplicant) 124 for field in PG_OMIT_MANAGE_FIELDS: 125 form_fields = form_fields.omit(field) 126 else: 127 form_fields = grok.AutoFields(IUGApplicant) 128 for field in UG_OMIT_MANAGE_FIELDS: 129 form_fields = form_fields.omit(field) 130 form_fields['student_id'].for_display = True 131 form_fields['applicant_id'].for_display = True 132 return form_fields 133 134 class CustomApplicantEditFormPage(ApplicantEditFormPage): 29 class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage): 135 30 """An applicant-centered edit view for applicant data. 136 31 """ … … 140 35 target = getattr(self.context.__parent__, 'prefix', None) 141 36 if target is not None and target.startswith('pg'): 142 form_fields = grok.AutoFields(I PGApplicantEdit)37 form_fields = grok.AutoFields(ICustomPGApplicantEdit) 143 38 for field in PG_OMIT_EDIT_FIELDS: 144 39 form_fields = form_fields.omit(field) … … 148 43 form_fields = form_fields.omit(field) 149 44 else: 150 form_fields = grok.AutoFields(I UGApplicantEdit)45 form_fields = grok.AutoFields(ICustomUGApplicantEdit) 151 46 for field in UG_OMIT_EDIT_FIELDS: 152 47 form_fields = form_fields.omit(field) … … 154 49 form_fields['reg_number'].for_display = True 155 50 return form_fields 156 157 class CustomOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):158 """ Page to view an online payment ticket159 """160 grok.context(ICustomApplicantOnlinePayment)161 form_fields = grok.AutoFields(ICustomApplicantOnlinePayment).omit('ac')162 form_fields[163 'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')164 form_fields[165 'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')166 167 class CustomApplicationFeePaymentAddPage(ApplicationFeePaymentAddPage):168 """ Page to add an online payment ticket169 """170 factory = u'waeup.CustomApplicantOnlinePayment'171 172 class CustomExportPDFPaymentSlipPage(ExportPDFPaymentSlipPage):173 """Deliver a PDF slip of the context.174 """175 grok.context(ICustomApplicantOnlinePayment)176 form_fields = grok.AutoFields(ICustomApplicantOnlinePayment).omit('ac')177 form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')178 form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le') -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/export.py
r8619 r8932 21 21 from waeup.kofa.applicants.interfaces import IApplicantBaseData 22 22 from waeup.kofa.applicants.export import ApplicantsExporter 23 from waeup.futminna.applicants.interfaces import IUGApplicant, IPGApplicant 23 from kofacustom.nigeria.applicants.interfaces import ( 24 INigeriaUGApplicant, INigeriaPGApplicant) 25 from waeup.futminna.applicants.interfaces import ( 26 ICustomUGApplicant, ICustomPGApplicant) 24 27 25 28 class CustomApplicantsExporter(ApplicantsExporter): … … 28 31 29 32 fields = tuple(sorted(set( 30 IUGApplicant.names() + 31 IPGApplicant.names() + 33 ICustomUGApplicant.names() + 34 ICustomPGApplicant.names() + 35 INigeriaUGApplicant.names() + 36 INigeriaPGApplicant.names() + 32 37 IApplicantBaseData.names() 33 38 ))) + ('container_code',) -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/interfaces.py
r8833 r8932 29 29 from waeup.kofa.students.vocabularies import nats_vocab, GenderSource 30 30 from waeup.kofa.applicants.interfaces import contextual_reg_num_source 31 from kofacustom.nigeria.interfaces import ( 32 LGASource, high_qual, high_grade, exam_types) 31 from kofacustom.nigeria.applicants.interfaces import ( 32 LGASource, high_qual, high_grade, exam_types, 33 INigeriaUGApplicant, INigeriaPGApplicant, 34 INigeriaApplicantOnlinePayment, 35 UG_OMIT_DISPLAY_FIELDS, 36 UG_OMIT_PDF_FIELDS, 37 UG_OMIT_MANAGE_FIELDS, 38 UG_OMIT_EDIT_FIELDS, 39 PUTME_OMIT_EDIT_FIELDS, 40 UG_OMIT_RESULT_SLIP_FIELDS, 41 PG_OMIT_DISPLAY_FIELDS, 42 PG_OMIT_PDF_FIELDS, 43 PG_OMIT_MANAGE_FIELDS, 44 PG_OMIT_EDIT_FIELDS, 45 ) 33 46 from waeup.futminna.interfaces import MessageFactory as _ 34 47 from waeup.futminna.payments.interfaces import ICustomOnlinePayment 35 48 36 UG_OMIT_DISPLAY_FIELDS = ('locked', 'course_admitted', 37 'password', 'result_uploaded') 38 UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('email', 'phone') 39 UG_OMIT_MANAGE_FIELDS = () 40 UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + ('locked', 'course_admitted', 41 'student_id', 'screening_score', 'screening_venue', 'notice', 42 'screening_date', 'result_uploaded') 43 PUTME_OMIT_EDIT_FIELDS = UG_OMIT_EDIT_FIELDS + ( 44 'firstname', 'middlename', 'lastname', 'sex', 45 'course1', 'lga', 'jamb_score', 'jamb_subjects') 46 UG_OMIT_RESULT_SLIP_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('email', 'phone', 47 'date_of_birth', 'sex', 48 'nationality', 'lga', 'perm_address', 'course2', 'screening_venue', 49 'screening_date') 50 51 PG_OMIT_DISPLAY_FIELDS = ('locked', 'course_admitted', 'password') 52 PG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('email', 'phone') 53 PG_OMIT_MANAGE_FIELDS = () 54 PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + ( 55 'locked', 'course_admitted', 56 'student_id', 'screening_score', 'screening_venue', 'notice', 57 'screening_date') 58 59 class IUGApplicant(IApplicantBaseData): 49 class ICustomUGApplicant(INigeriaUGApplicant): 60 50 """An undergraduate applicant. 61 51 … … 65 55 """ 66 56 67 nationality = schema.Choice( 68 source = nats_vocab, 69 title = _(u'Nationality'), 70 required = False, 71 ) 72 lga = schema.Choice( 73 source = LGASource(), 74 title = _(u'State/LGA (Nigerians only)'), 75 required = False, 76 ) 77 perm_address = schema.Text( 78 title = _(u'Permanent Address'), 79 required = False, 80 ) 81 course1 = schema.Choice( 82 title = _(u'1st Choice Course of Study'), 83 source = AppCatCertificateSource(), 84 required = True, 85 ) 86 course2 = schema.Choice( 87 title = _(u'2nd Choice Course of Study'), 88 source = AppCatCertificateSource(), 89 required = False, 90 ) 91 jamb_subjects = schema.Text( 92 title = _(u'Subjects and Scores'), 93 required = False, 94 ) 95 jamb_score = schema.Int( 96 title = _(u'Total Score'), 97 required = False, 98 ) 99 notice = schema.Text( 100 title = _(u'Notice'), 101 required = False, 102 ) 103 screening_venue = schema.TextLine( 104 title = _(u'Screening Venue'), 105 required = False, 106 ) 107 screening_date = schema.TextLine( 108 title = _(u'Screening Date'), 109 required = False, 110 ) 111 screening_score = schema.Int( 112 title = _(u'Screening Score (%)'), 113 required = False, 114 ) 115 aggregate = schema.Int( 116 title = _(u'Aggregate Score (%)'), 117 description = _(u'(average of relative JAMB and PUTME scores)'), 118 required = False, 119 ) 120 result_uploaded = schema.Bool( 121 title = _(u'Result uploaded'), 122 default = False, 123 ) 124 student_id = schema.TextLine( 125 title = _(u'Student Id'), 126 required = False, 127 readonly = False, 128 ) 129 course_admitted = schema.Choice( 130 title = _(u'Admitted Course of Study'), 131 source = CertificateSource(), 132 required = False, 133 ) 134 locked = schema.Bool( 135 title = _(u'Form locked'), 136 default = False, 137 ) 138 139 class IPGApplicant(IApplicantBaseData): 57 class ICustomPGApplicant(INigeriaPGApplicant): 140 58 """A postgraduate applicant. 141 59 … … 145 63 """ 146 64 147 nationality = schema.Choice( 148 source = nats_vocab, 149 title = _(u'Nationality'), 150 required = False, 151 ) 152 lga = schema.Choice( 153 source = LGASource(), 154 title = _(u'State/LGA (Nigerians only)'), 155 required = False, 156 ) 157 perm_address = schema.Text( 158 title = _(u'Permanent Address'), 159 required = False, 160 ) 161 course1 = schema.Choice( 162 title = _(u'1st Choice Course of Study'), 163 source = AppCatCertificateSource(), 164 required = True, 165 ) 166 course2 = schema.Choice( 167 title = _(u'2nd Choice Course of Study'), 168 source = AppCatCertificateSource(), 169 required = False, 170 ) 171 hq_type = schema.Choice( 172 title = _(u'Qualification Obtained'), 173 required = False, 174 readonly = False, 175 vocabulary = high_qual, 176 ) 177 hq_matric_no = schema.TextLine( 178 title = _(u'Former Matric Number'), 179 required = False, 180 readonly = False, 181 ) 182 hq_degree = schema.Choice( 183 title = _(u'Class of Degree'), 184 required = False, 185 readonly = False, 186 vocabulary = high_grade, 187 ) 188 hq_school = schema.TextLine( 189 title = _(u'Institution Attended'), 190 required = False, 191 readonly = False, 192 ) 193 hq_session = schema.TextLine( 194 title = _(u'Years Attended'), 195 required = False, 196 readonly = False, 197 ) 198 hq_disc = schema.TextLine( 199 title = _(u'Discipline'), 200 required = False, 201 readonly = False, 202 ) 203 pp_school = schema.Choice( 204 title = _(u'Qualification Obtained'), 205 required = False, 206 readonly = False, 207 vocabulary = exam_types, 208 ) 209 #presently = schema.Bool( 210 # title = _(u'Attending'), 211 # required = False, 212 # readonly = False, 213 # ) 214 presently_inst = schema.TextLine( 215 title = _(u'If yes, name of institution'), 216 required = False, 217 readonly = False, 218 ) 219 nysc_year = schema.Int( 220 title = _(u'Nysc Year'), 221 required = False, 222 readonly = False, 223 ) 224 nysc_lga = schema.Choice( 225 source = LGASource(), 226 title = _(u'Nysc Location'), 227 required = False, 228 ) 229 employer = schema.TextLine( 230 title = _(u'Employer'), 231 required = False, 232 readonly = False, 233 ) 234 emp_position = schema.TextLine( 235 title = _(u'Employer Position'), 236 required = False, 237 readonly = False, 238 ) 239 emp_start = FormattedDate( 240 title = _(u'Start Date'), 241 required = False, 242 readonly = False, 243 show_year = True, 244 ) 245 emp_end = FormattedDate( 246 title = _(u'End Date'), 247 required = False, 248 readonly = False, 249 show_year = True, 250 ) 251 emp_reason = schema.TextLine( 252 title = _(u'Reason for Leaving'), 253 required = False, 254 readonly = False, 255 ) 256 employer2 = schema.TextLine( 257 title = _(u'2nd Employer'), 258 required = False, 259 readonly = False, 260 ) 261 emp2_position = schema.TextLine( 262 title = _(u'2nd Employer Position'), 263 required = False, 264 readonly = False, 265 ) 266 emp2_start = FormattedDate( 267 title = _(u'Start Date'), 268 required = False, 269 readonly = False, 270 show_year = True, 271 ) 272 emp2_end = FormattedDate( 273 title = _(u'End Date'), 274 required = False, 275 readonly = False, 276 show_year = True, 277 ) 278 emp2_reason = schema.TextLine( 279 title = _(u'Reason for Leaving'), 280 required = False, 281 readonly = False, 282 ) 283 notice = schema.Text( 284 title = _(u'Notice'), 285 required = False, 286 readonly = False, 287 ) 288 screening_venue = schema.TextLine( 289 title = _(u'Screening Venue'), 290 required = False, 291 readonly = False, 292 ) 293 screening_date = schema.TextLine( 294 title = _(u'Screening Date'), 295 required = False, 296 ) 297 screening_score = schema.Int( 298 title = _(u'Screening Score'), 299 required = False, 300 readonly = False, 301 ) 302 student_id = schema.TextLine( 303 title = _(u'Student Id'), 304 required = False, 305 readonly = False, 306 ) 307 course_admitted = schema.Choice( 308 title = _(u'Admitted Course of Study'), 309 source = CertificateSource(), 310 required = False, 311 readonly = False, 312 ) 313 locked = schema.Bool( 314 title = _(u'Form locked'), 315 default = False, 316 ) 317 318 class ICustomApplicant(IUGApplicant, IPGApplicant): 65 class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant): 319 66 """An interface for both types of applicants. 320 67 321 Attention: The I PGApplicant field seetings will be overwritten322 by I PGApplicant field settings. If a field is defined68 Attention: The ICustomPGApplicant field seetings will be overwritten 69 by ICustomPGApplicant field settings. If a field is defined 323 70 in both interfaces zope.schema validates only against the 324 constraints in I UGApplicant. This does not affect the forms325 since they are build on either I UGApplicant or IPGApplicant.71 constraints in ICustomUGApplicant. This does not affect the forms 72 since they are build on either ICustomUGApplicant or ICustomPGApplicant. 326 73 """ 327 74 … … 335 82 """ 336 83 337 class I UGApplicantEdit(IUGApplicant):84 class ICustomUGApplicantEdit(ICustomUGApplicant): 338 85 """An undergraduate applicant interface for edit forms. 339 86 … … 358 105 ) 359 106 360 I UGApplicantEdit[361 'date_of_birth'].order = I UGApplicant['date_of_birth'].order362 I UGApplicantEdit[363 'email'].order = I UGApplicant['email'].order107 ICustomUGApplicantEdit[ 108 'date_of_birth'].order = ICustomUGApplicant['date_of_birth'].order 109 ICustomUGApplicantEdit[ 110 'email'].order = ICustomUGApplicant['email'].order 364 111 365 class I PGApplicantEdit(IPGApplicant):112 class ICustomPGApplicantEdit(ICustomPGApplicant): 366 113 """A postgraduate applicant interface for editing. 367 114 … … 386 133 ) 387 134 388 I PGApplicantEdit[389 'date_of_birth'].order = I PGApplicant['date_of_birth'].order390 I PGApplicantEdit[391 'email'].order = I PGApplicant['email'].order135 ICustomPGApplicantEdit[ 136 'date_of_birth'].order = ICustomPGApplicant['date_of_birth'].order 137 ICustomPGApplicantEdit[ 138 'email'].order = ICustomPGApplicant['email'].order 392 139 393 class ICustomApplicantOnlinePayment(I CustomOnlinePayment):140 class ICustomApplicantOnlinePayment(INigeriaApplicantOnlinePayment): 394 141 """An applicant payment via payment gateways. 395 142 396 143 """ 397 144 398 class IPUTMEApplicantEdit(I UGApplicant):145 class IPUTMEApplicantEdit(ICustomUGApplicant): 399 146 """An undergraduate applicant interface for editing. 400 147 … … 419 166 420 167 IPUTMEApplicantEdit[ 421 'date_of_birth'].order = I UGApplicant['date_of_birth'].order168 'date_of_birth'].order = ICustomUGApplicant['date_of_birth'].order 422 169 IPUTMEApplicantEdit[ 423 'email'].order = I UGApplicant['email'].order170 'email'].order = ICustomUGApplicant['email'].order 424 171 425 172 class ICustomApplicantUpdateByRegNo(ICustomApplicant): -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/payment.py
r8619 r8932 48 48 """ 49 49 grok.implements(IFactory) 50 grok.name(u'waeup. CustomApplicantOnlinePayment')50 grok.name(u'waeup.ApplicantOnlinePayment') 51 51 title = u"Create a new online payment.", 52 52 description = u"This factory instantiates new online payment instances." -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/tests/test_applicant.py
r8931 r8932 30 30 from waeup.kofa.interfaces import IFileStoreHandler, IFileStoreNameChooser 31 31 from waeup.kofa.testing import FunctionalTestCase 32 from waeup. aaue.applicants.applicant import (32 from waeup.futminna.applicants.applicant import ( 33 33 CustomApplicant, CustomApplicantFactory, 34 34 ) 35 from waeup. aaue.applicants.interfaces import ICustomApplicant36 from waeup. aaue.testing import FunctionalLayer35 from waeup.futminna.applicants.interfaces import ICustomApplicant 36 from waeup.futminna.testing import FunctionalLayer 37 37 38 38 class CustomApplicantTest(FunctionalTestCase): -
main/waeup.futminna/trunk/src/waeup/futminna/applicants/tests/test_browser.py
r8931 r8932 39 39 from waeup.kofa.applicants.tests.test_batching import ApplicantImportExportSetup 40 40 from waeup.kofa.interfaces import IBatchProcessor 41 from waeup. aaue.testing import FunctionalLayer42 from waeup. aaue.applicants.export import CustomApplicantsExporter43 from waeup. aaue.applicants.batching import CustomApplicantProcessor41 from waeup.futminna.testing import FunctionalLayer 42 from waeup.futminna.applicants.export import CustomApplicantsExporter 43 from waeup.futminna.applicants.batching import CustomApplicantProcessor 44 44 45 45
Note: See TracChangeset for help on using the changeset viewer.