- Timestamp:
- 21 Sep 2012, 08:19:35 (12 years ago)
- Location:
- main/waeup.kofa/branches/uli-zc-async
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/branches/uli-zc-async
- Property svn:mergeinfo changed
/main/waeup.kofa/branches/uli-async-update removed /main/waeup.kofa/branches/uli-autoinclude-less removed /main/waeup.kofa/trunk removed
- Property svn:mergeinfo changed
-
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/students/utils.py
r9209 r9211 19 19 """ 20 20 import grok 21 from random import SystemRandom as r 21 22 from time import time 23 from datetime import datetime 24 from zope.i18n import translate 25 from zope.component import getUtility, createObject 26 from reportlab.pdfgen import canvas 22 27 from reportlab.lib import colors 23 28 from reportlab.lib.units import cm 29 from reportlab.lib.enums import TA_RIGHT 24 30 from reportlab.lib.pagesizes import A4 25 from reportlab.lib.styles import getSampleStyleSheet 26 from reportlab.platypus import Paragraph, Image, Table, Spacer 27 from zope.component import getUtility, createObject 31 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle 32 from reportlab.platypus import (Frame, Paragraph, Image, PageBreak, Table, 33 Spacer) 34 from reportlab.platypus.tables import TableStyle 35 from reportlab.platypus.flowables import PageBreak 36 from zope.component import getUtility 28 37 from zope.formlib.form import setUpEditWidgets 29 from zope.i18n import translate 38 30 39 from waeup.kofa.interfaces import ( 31 40 IExtFileStore, IKofaUtils, RETURNING, PAID, CLEARED) 32 41 from waeup.kofa.interfaces import MessageFactory as _ 33 42 from waeup.kofa.students.interfaces import IStudentsUtils 43 from waeup.kofa.utils.helpers import now 34 44 35 45 SLIP_STYLE = [ … … 117 127 #data.append([Spacer(1, 12)]) 118 128 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 119 120 f_label = formatted_label(size=12) % _('Name')121 f_label = Paragraph(f_label, style["Normal"])122 f_text = formatted_text(studentview.context.display_fullname, size=12)123 f_text = Paragraph(f_text, style["Normal"])124 data_right.append([f_label,f_text])125 126 129 for widget in studentview.widgets: 127 if 'name' in widget.name:130 if widget.name == 'form.adm_code': 128 131 continue 129 132 f_label = formatted_label(size=12) % translate( … … 134 137 f_text = Paragraph(f_text, style["Normal"]) 135 138 data_right.append([f_label,f_text]) 136 137 if hasattr(studentview.context, 'certcode'):138 f_label = formatted_label(size=12) % _('Study Course')139 f_label = Paragraph(f_label, style["Normal"])140 f_text = formatted_text(141 studentview.context['studycourse'].certificate.longtitle(), size=12)142 f_text = Paragraph(f_text, style["Normal"])143 data_right.append([f_label,f_text])144 145 f_label = formatted_label(size=12) % _('Department')146 f_label = Paragraph(f_label, style["Normal"])147 f_text = formatted_text(148 studentview.context[149 'studycourse'].certificate.__parent__.__parent__.longtitle(),150 size=12)151 f_text = Paragraph(f_text, style["Normal"])152 data_right.append([f_label,f_text])153 154 f_label = formatted_label(size=12) % _('Faculty')155 f_label = Paragraph(f_label, style["Normal"])156 f_text = formatted_text(157 studentview.context[158 'studycourse'].certificate.__parent__.__parent__.__parent__.longtitle(),159 size=12)160 f_text = Paragraph(f_text, style["Normal"])161 data_right.append([f_label,f_text])162 163 139 table_left = Table(data_left,style=SLIP_STYLE) 164 140 table_right = Table(data_right,style=SLIP_STYLE, colWidths=[5*cm, 6*cm]) … … 189 165 return table 190 166 191 def get_signature_table(signatures, lang='en'):192 """Return a reportlab table containing signature fields (with date).193 """194 style = getSampleStyleSheet()195 space_width = 0.4 # width in cm of space between signatures196 table_width = 16.0 # supposed width of signature table in cms197 # width of signature cells in cm...198 sig_col_width = table_width - ((len(signatures) - 1) * space_width)199 sig_col_width = sig_col_width / len(signatures)200 data = []201 col_widths = [] # widths of columns202 203 sig_style = [204 ('VALIGN',(0,-1),(-1,-1),'TOP'),205 ('FONT', (0,0), (-1,-1), 'Helvetica-BoldOblique', 12),206 ('BOTTOMPADDING', (0,0), (-1,0), 36),207 ('TOPPADDING', (0,-1), (-1,-1), 0),208 ]209 for num, elem in enumerate(signatures):210 # draw a line above each signature cell (not: empty cells in between)211 sig_style.append(212 ('LINEABOVE', (num*2,-1), (num*2, -1), 1, colors.black))213 214 row = []215 for signature in signatures:216 row.append(trans(_('Date:'), lang))217 row.append('')218 if len(signatures) > 1:219 col_widths.extend([sig_col_width*cm, space_width*cm])220 else:221 col_widths.extend([sig_col_width/2*cm, sig_col_width/2*cm])222 row.append('') # empty spaceholder on right223 data.append(row[:-1])224 data.extend(([''],)*3) # insert 3 empty rows...225 row = []226 for signature in signatures:227 row.append(Paragraph(trans(signature, lang), style["Normal"]))228 row.append('')229 data.append(row[:-1])230 table = Table(data, style=sig_style, repeatRows=len(data),231 colWidths=col_widths)232 return table233 234 167 def docs_as_flowables(view, lang='en'): 235 168 """Create reportlab flowables out of scanned docs. … … 257 190 if img_path is None: 258 191 pass 259 elif not img_path [-4:] in ('.jpg', '.JPG'):192 elif not img_path.endswith('.jpg'): 260 193 # reportlab requires jpg images, I think. 261 f_text = Paragraph('%s ( not displayable)' % (194 f_text = Paragraph('%s (Not displayable)' % ( 262 195 viewlet.title,), ENTRY1_STYLE) 263 196 else: … … 269 202 return data 270 203 204 def insert_footer(pdf,width,style,text=None, number_of_pages=1): 205 """Render the whole footer frame. 206 """ 207 story = [] 208 frame_footer = Frame(1*cm,0,width-(2*cm),1*cm) 209 tz = getUtility(IKofaUtils).tzinfo 210 timestamp = now(tz).strftime("%d/%m/%Y %H:%M:%S %Z") 211 left_text = '<font size=10>%s</font>' % timestamp 212 story.append(Paragraph(left_text, style["Normal"])) 213 frame_footer.addFromList(story,pdf) 214 story = [] 215 frame_footer = Frame(1*cm,0,width-(2*cm),1*cm) 216 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 217 right_text = translate(_('<font size=10>${a} Page ${b} of ${c}</font>', 218 mapping = {'a':text, 'b':pdf.getPageNumber(), 'c':number_of_pages}), 219 'waeup.kofa', target_language=portal_language) 220 story.append(Paragraph(right_text, style["Right"])) 221 frame_footer.addFromList(story,pdf) 222 271 223 class StudentsUtils(grok.GlobalUtility): 272 224 """A collection of methods subject to customization. … … 275 227 276 228 def getReturningData(self, student): 277 """ Definewhat happens after school fee payment229 """ This method defines what happens after school fee payment 278 230 depending on the student's senate verdict. 279 231 … … 286 238 287 239 def setReturningData(self, student): 288 """ Define what happens after school fee payment 289 depending on the student's senate verdict. 290 291 This method folllows the same algorithm as getReturningData but 292 it also sets the new values. 240 """ This method defines what happens after school fee payment 241 depending on the student's senate verdict. It folllows 242 the same algorithm as getReturningData but it also sets the new 243 values 244 245 In the base configuration current level is always increased 246 by 100 no matter which verdict has been assigned. 293 247 """ 294 248 new_session, new_level = self.getReturningData(student) … … 296 250 student['studycourse'].current_session = new_session 297 251 verdict = student['studycourse'].current_verdict 298 student['studycourse'].current_verdict = ' 0'252 student['studycourse'].current_verdict = 'NY' 299 253 student['studycourse'].previous_verdict = verdict 300 254 return 301 255 302 def setPaymentDetails(self, category, student, 303 previous_session, previous_level): 256 def setPaymentDetails(self, category, student): 304 257 """Create Payment object and set the payment data of a student for 305 258 the payment category specified. 306 259 307 260 """ 261 details = {} 308 262 p_item = u'' 309 263 amount = 0.0 310 if previous_session: 311 p_session = previous_session 312 p_level = previous_level 313 p_current = False 314 else: 315 p_session = student['studycourse'].current_session 316 p_level = student['studycourse'].current_level 317 p_current = True 264 error = u'' 265 p_session = student['studycourse'].current_session 266 p_level = student['studycourse'].current_level 318 267 session = str(p_session) 319 268 try: … … 327 276 except (AttributeError, TypeError): 328 277 return _('Study course data are incomplete.'), None 329 if previous_session: 330 if previous_session < student['studycourse'].entry_session: 331 return _('The previous session must not fall below ' 332 'your entry session.'), None 333 if previous_session > student['studycourse'].current_session - 1: 334 return _('This is not a previous session.'), None 335 if previous_level == 100: 336 amount = getattr(certificate, 'school_fee_1', 0.0) 337 else: 338 amount = getattr(certificate, 'school_fee_2', 0.0) 339 else: 340 if student.state == CLEARED: 341 amount = getattr(certificate, 'school_fee_1', 0.0) 342 elif student.state == RETURNING: 343 # In case of returning school fee payment the payment session 344 # and level contain the values of the session the student 345 # has paid for. 346 p_session, p_level = self.getReturningData(student) 347 amount = getattr(certificate, 'school_fee_2', 0.0) 348 elif student.is_postgrad and student.state == PAID: 349 # Returning postgraduate students also pay for the next session 350 # but their level always remains the same. 351 p_session += 1 352 amount = getattr(certificate, 'school_fee_2', 0.0) 278 if student.state == CLEARED: 279 amount = getattr(certificate, 'school_fee_1', 0.0) 280 elif student.state == RETURNING: 281 # In case of returning school fee payment the payment session 282 # and level contain the values of the session the student 283 # has paid for. 284 p_session, p_level = self.getReturningData(student) 285 amount = getattr(certificate, 'school_fee_2', 0.0) 286 elif student.is_postgrad and student.state == PAID: 287 # Returning postgraduate students also pay for the next session 288 # but their level always remains the same. 289 p_session += 1 290 amount = getattr(certificate, 'school_fee_2', 0.0) 353 291 elif category == 'clearance': 354 try: 355 p_item = student['studycourse'].certificate.code 356 except (AttributeError, TypeError): 357 return _('Study course data are incomplete.'), None 292 p_item = student['studycourse'].certificate.code 358 293 amount = academic_session.clearance_fee 359 294 elif category == 'bed_allocation': … … 361 296 amount = academic_session.booking_fee 362 297 if amount in (0.0, None): 363 return _('Amount could not be determined.' + 364 ' Would you like to pay for a previous session?'), None 298 return _(u'Amount could not be determined.'), None 365 299 for key in student['payments'].keys(): 366 300 ticket = student['payments'][key] … … 369 303 ticket.p_item == p_item and \ 370 304 ticket.p_session == p_session: 371 return _('This type of payment has already been made.' + 372 ' Would you like to pay for a previous session?'), None 305 return _('This type of payment has already been made.'), None 373 306 payment = createObject(u'waeup.StudentOnlinePayment') 374 timestamp = ("%d" % int(time()*10000))[1:]307 timestamp = "%d" % int(time()*1000) 375 308 payment.p_id = "p%s" % timestamp 376 309 payment.p_category = category … … 378 311 payment.p_session = p_session 379 312 payment.p_level = p_level 380 payment.p_current = p_current381 313 payment.amount_auth = amount 382 314 return None, payment … … 398 330 entry_session = studycourse.entry_session 399 331 current_level = studycourse.current_level 400 if None in (entry_session, current_level,certificate):401 return d332 if not (entry_session and current_level and certificate): 333 return 402 334 end_level = certificate.end_level 403 if current_level == 10: 404 bt = 'pr' 405 elif entry_session == grok.getSite()['hostels'].accommodation_session: 335 if entry_session == grok.getSite()['hostels'].accommodation_session: 406 336 bt = 'fr' 407 337 elif current_level >= end_level: … … 425 355 return available_beds[0] 426 356 427 def renderPDFAdmissionLetter(self, view, student=None):428 """Render pdf admission letter.429 """430 # XXX: we have to fix the import problems here.431 from waeup.kofa.browser.interfaces import IPDFCreator432 from waeup.kofa.browser.pdf import format_html, NOTE_STYLE433 if student is None:434 return435 style = getSampleStyleSheet()436 creator = getUtility(IPDFCreator)437 data = []438 doc_title = view.label439 author = '%s (%s)' % (view.request.principal.title,440 view.request.principal.id)441 footer_text = view.label442 if getattr(student, 'student_id', None) is not None:443 footer_text = "%s - %s - " % (student.student_id, footer_text)444 445 # Admission text446 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE447 inst_name = grok.getSite()['configuration'].name448 text = trans(_(449 'This is to inform you that you have been provisionally'450 ' admitted into ${a} as follows:', mapping = {'a': inst_name}),451 portal_language)452 html = format_html(text)453 data.append(Paragraph(html, NOTE_STYLE))454 data.append(Spacer(1, 20))455 456 # Student data457 data.append(render_student_data(view))458 459 # Insert history460 data.append(Spacer(1, 20))461 datelist = student.history.messages[0].split()[0].split('-')462 creation_date = u'%s/%s/%s' % (datelist[2], datelist[1], datelist[0])463 text = trans(_(464 'Your Kofa student record was created on ${a}.',465 mapping = {'a': creation_date}),466 portal_language)467 html = format_html(text)468 data.append(Paragraph(html, NOTE_STYLE))469 470 # Create pdf stream471 view.response.setHeader(472 'Content-Type', 'application/pdf')473 pdf_stream = creator.create_pdf(474 data, None, doc_title, author=author, footer=footer_text,475 note=None)476 return pdf_stream477 478 357 def renderPDF(self, view, filename='slip.pdf', student=None, 479 358 studentview=None, tableheader=None, tabledata=None, 480 note=None , signatures=None):359 note=None): 481 360 """Render pdf slips for various pages. 482 361 """ … … 494 373 footer_text = "%s - %s - " % (student.student_id, footer_text) 495 374 496 # Insert history497 if not filename.startswith('payment'):498 data.extend(creator.fromStringList(student.history.messages))499 500 375 # Insert student data table 501 376 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE … … 506 381 507 382 # Insert widgets 508 if view.form_fields: 509 data.append(Paragraph(view.title, style["Heading3"])) 510 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 511 separators = getattr(self, 'SEPARATORS_DICT', {}) 512 table = creator.getWidgetsTable( 513 view.form_fields, view.context, None, lang=portal_language, 514 separators=separators) 515 data.append(table) 383 data.append(Paragraph(view.title, style["Heading3"])) 384 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 385 separators = getattr(self, 'SEPARATORS_DICT', {}) 386 table = creator.getWidgetsTable( 387 view.form_fields, view.context, None, lang=portal_language, 388 separators=separators) 389 data.append(table) 516 390 517 391 # Insert scanned docs … … 525 399 contenttable = render_table_data(tableheader,tabledata) 526 400 data.append(contenttable) 527 528 # Insert signatures529 if signatures:530 data.append(Spacer(1, 20))531 signaturetable = get_signature_table(signatures)532 data.append(signaturetable)533 401 534 402 view.response.setHeader( … … 544 412 545 413 VERDICTS_DICT = { 546 ' 0': _('(not yet)'),414 'NY': _('(not yet)'), 547 415 'A': 'Successful student', 548 416 'B': 'Student with carryover courses',
Note: See TracChangeset for help on using the changeset viewer.