def latex_address(address1, address2, postal_code, city, country_code): address2_latex = '' if len(address2) > 0: address2_latex = '\\linebreak ' address2_latex += unicode(TexTools.escape(address2)).encode('utf-8') return LATEX_ADDRESS.format( address1_latex=unicode(TexTools.escape(address1)).encode('utf-8'), address2_latex=address2_latex, postal_code_latex=unicode( TexTools.escape(postal_code)).encode('utf-8'), city=unicode(TexTools.escape(city)).encode('utf-8'), country_code=unicode(TexTools.escape(country_code)).encode('utf-8'))
def latex_membership_loss(membership_loss_date, membership_loss_type): membership_loss = u'' if membership_loss_date is not None: membership_loss += membership_loss_date.strftime('%d.%m.%Y') if membership_loss_type is not None: membership_loss += '\\linebreak ' membership_loss += unicode(TexTools.escape( membership_loss_type)).encode('utf-8') return membership_loss
def test_escape(self): """ Test method TexTools.escape """ unescaped = u'&%$#_{}~^\\<>℅°ß' escaped = TexTools.escape(unescaped) expected = u'\\&\\%\\$\\#\\_\\{\}\\textasciitilde{}\\^{}' + \ u'\\textbackslash{}\\textless{}\\textgreater{}c/o\\degree{}\\ss{}' self.assertEqual(escaped, expected)
def create_pdf(tex_vars, tpl_tex, invoice): """ Create the invoice PDF """ receipt_pdf = tempfile.NamedTemporaryFile(suffix='.pdf') (path, filename) = os.path.split(receipt_pdf.name) filename = os.path.splitext(filename)[0] # generate tex command for pdflatex tex_cmd = u'' for key, val in tex_vars.iteritems(): tex_cmd += '\\newcommand{\\%s}{%s}' % (key, TexTools.escape(val)) tex_cmd += '\\input{%s}' % tpl_tex tex_cmd = u'"'+tex_cmd+'"' # make latex show ß correctly in pdf: tex_cmd = tex_cmd.replace(u'ß', u'\\ss{}') subprocess.call( [ 'pdflatex', '-jobname', filename, '-output-directory', path, '-interaction', 'nonstopmode', '-halt-on-error', tex_cmd.encode('latin_1') ], stdout=open(os.devnull, 'w'), # hide output stderr=subprocess.STDOUT, cwd=PDFLATEX_DIR ) # cleanup aux = os.path.join(path, filename + '.aux') if os.path.isfile(aux): os.unlink(aux) archive_dues19_invoice(receipt_pdf, invoice) return receipt_pdf
def member_list_date_pdf_view(request): """ The membership list *for a given date* for printout as PDF. The date is supplied in and parsed from the URL, e.g. http://0.0.0.0:6543/aml-2014-12-31.pdf The PDF is generated using pdflatex. If the date is not parseable, an error message is shown. """ try: _date_m = request.matchdict['date'] _date = datetime.strptime(_date_m, '%Y-%m-%d').date() except (KeyError, ValueError): request.session.flash( "Invalid date! '{}' does not compute! " "try again, please! (YYYY-MM-DD)".format( _date_m), 'message_to_user' ) return HTTPFound(request.route_url('error_page')) """ All member entries are loaded. """ # query the database _order_by = 'lastname' _num = C3sMember.get_number() _all_members = C3sMember.member_listing( _order_by, how_many=_num, offset=0, order=u'asc') # prepare variables _members = [] # the members, filtered _count_members = 0 # count those members _count_shares = 0 # count their shares _count_shares_printed = 0 # cross-check... """ ...and filtered for * active members (membership_accepted) * with membership numbers (cross-check) * who have become members before the given date. They are added to a list and counted. Their shares (those acquired before the date) are counted as well. """ # filter and count memberships and shares for item in _all_members: if ( (item.membership_number is not None) and item.is_member(_date)): # add this item to the filtered list of members _members.append(item) _count_members += 1 # also count their shares iff acquired in the timespan for share in item.shares: if (date( share.date_of_acquisition.year, share.date_of_acquisition.month, share.date_of_acquisition.day, ) <= _date): _count_shares += share.number """ The list of members is then sorted by * their given name * their last name, using locale.strcoll with german locale. This achieves a sort order like in phone books. """ # sort members alphabetically import locale locale.setlocale(locale.LC_ALL, "de_DE.UTF-8") # ...by fist name _members.sort(key=lambda x: x.firstname, cmp=locale.strcoll) # ...and then by their last name _members.sort(key=lambda x: x.lastname, cmp=locale.strcoll) """ Then a LaTeX file is constructed... """ here = os.path.dirname(__file__) latex_header_tex = os.path.abspath( os.path.join(here, '../membership_list_pdflatex/header')) latex_footer_tex = os.path.abspath( os.path.join(here, '../membership_list_pdflatex/footer')) # a temporary directory for the latex run _tempdir = tempfile.mkdtemp() # now we prepare a .tex file to be pdflatex'ed latex_file = tempfile.NamedTemporaryFile( suffix='.tex', dir=_tempdir, delete=False, # directory will be deleted anyways ) # and where to store the output pdf_file = tempfile.NamedTemporaryFile( dir=_tempdir, delete=False, # directory will be deleted anyways ) pdf_file.name = latex_file.name.replace('.tex', '.pdf') # construct latex data: header + variables latex_data = ''' \\input{%s} \\def\\numMembers{%s} \\def\\numShares{%s} \\def\\sumShares{%s} \\def\\today{%s} ''' % ( latex_header_tex, _count_members, _count_shares, _count_shares * 50, _date.strftime('%d.%m.%Y'), ) # add to the latex document latex_data += ''' \\input{%s}''' % latex_footer_tex # print '*' * 70 # print latex_data # print '*' * 70 latex_file.write(latex_data.encode('utf-8')) # make table rows per member for member in _members: _address = '''\\scriptsize{}''' _address += '''{}'''.format( unicode(TexTools.escape(member.address1)).encode('utf-8')) # check for contents of address2: if len(member.address2) > 0: _address += '''\\linebreak {}'''.format( unicode(TexTools.escape(member.address2)).encode('utf-8')) # add more... _address += ''' \\linebreak {} '''.format( unicode(TexTools.escape(member.postcode)).encode('utf-8')) _address += '''{}'''.format( unicode(TexTools.escape(member.city)).encode('utf-8')) _address += ''' ({})'''.format( unicode(TexTools.escape(member.country)).encode('utf-8')) # check shares acquired until $date _acquired_shares_until_date = 0 for share in member.shares: if date( share.date_of_acquisition.year, share.date_of_acquisition.month, share.date_of_acquisition.day) <= _date: _acquired_shares_until_date += share.number _count_shares_printed += share.number membership_loss = u'' if member.membership_loss_date is not None: membership_loss += \ member.membership_loss_date.strftime('%d.%m.%Y') + \ '\\linebreak ' if member.membership_loss_type is not None: membership_loss += member.membership_loss_type latex_file.write( ''' {0} & {1} & {2} & {3} & {4} & {5} & {6} \\\\\\hline % '''.format( TexTools.escape(member.lastname).encode('utf-8'), # 0 ' \\footnotesize ' + TexTools.escape( member.firstname).encode('utf-8'), # 1 ' \\footnotesize ' + TexTools.escape( str(member.membership_number)), # 2 _address, # 3 ' \\footnotesize ' + member.membership_date.strftime( '%d.%m.%Y'), # 4 ' \\footnotesize ' + membership_loss + ' ', # 5 ' \\footnotesize ' + str(_acquired_shares_until_date) # 6 )) latex_file.write(''' %\\end{tabular}% \\end{longtable}% \\label{LastPage} \\end{document} ''') latex_file.seek(0) # rewind # pdflatex latex_file to pdf_file fnull = open(os.devnull, 'w') # hide output pdflatex_output = subprocess.call( [ 'pdflatex', '-output-directory=%s' % _tempdir, latex_file.name ], stdout=fnull, stderr=subprocess.STDOUT # hide output ) if DEBUG: # pragma: no cover print("the output of pdflatex run: %s" % pdflatex_output) # if run was a success, run X times more... if pdflatex_output == 0: for i in range(2): pdflatex_output = subprocess.call( [ 'pdflatex', '-output-directory=%s' % _tempdir, latex_file.name ], stdout=fnull, stderr=subprocess.STDOUT # hide output ) if DEBUG: # pragma: no cover print("run #{} finished.".format(i+1)) # sanity check: did we print exactly as many shares as calculated? assert(_count_shares == _count_shares_printed) # return a pdf file response = Response(content_type='application/pdf') response.app_iter = open(pdf_file.name, "r") shutil.rmtree(_tempdir, ignore_errors=True) # delete temporary directory return response
def generate_membership_list_pdf(effective_date, members): template_path = os.path.join( os.path.dirname(__file__), '../../../membership_list_pdflatex') latex_dir = tempfile.mkdtemp() latex_file = tempfile.NamedTemporaryFile( suffix='.tex', dir=latex_dir, delete=False, ) shares_count = sum([member['shares_count'] for member in members]) latex_file.write( LATEX_HEADER.format( header_file=os.path.abspath( os.path.join( template_path, 'header')), footer_file=os.path.abspath( os.path.join( template_path, 'footer')), members_count=len(members), shares_count=shares_count, shares_value=shares_count * 50, effective_date=effective_date.strftime('%d.%m.%Y'), ).encode('utf-8')) # make table rows per member for member in members: latex_file.write( LATEX_MEMBER_ROW.format( lastname=TexTools.escape(member['lastname']).encode('utf-8'), firstname=TexTools.escape(member['firstname']).encode('utf-8'), membership_number=TexTools.escape( str(member['membership_number'])), address=latex_address( member['address1'], member['address2'], member['postcode'], member['city'], member['country']), membership_approval=member['membership_date'].strftime( '%d.%m.%Y'), membership_loss=latex_membership_loss( member['membership_loss_date'], member['membership_loss_type']), shares=str(member['shares_count']))) latex_file.write(LATEX_FOOTER) latex_file.close() # generate file three times in order to make sure all back references like # the number of total pages are properly calculated for i in range(3): subprocess.call( [ 'pdflatex', '-output-directory={0}'.format(latex_dir), latex_file.name ], stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT, ) pdf_file = open(latex_file.name.replace('.tex', '.pdf'), "r") shutil.rmtree(latex_dir, ignore_errors=True) return pdf_file
def member_list_date_pdf_view(request): """ The membership list *for a given date* for printout as PDF. The date is supplied in and parsed from the URL, e.g. http://0.0.0.0:6543/aml-2014-12-31.pdf The PDF is generated using pdflatex. If the date is not parseable, an error message is shown. """ effective_date_string = '' try: effective_date_string = request.matchdict['date'] effective_date = datetime.strptime(effective_date_string, '%Y-%m-%d') \ .date() except (KeyError, ValueError): request.session.flash( "Invalid date! '{}' does not compute! " "try again, please! (YYYY-MM-DD)".format( effective_date_string), 'message_to_user' ) return HTTPFound(request.route_url('error_page')) shares_count_printed = 0 # TODO: repositories are data layer and must only be used by the business # layer. Introduce business layer logic which uses the repositories and can # be accessed by this view via the request. shares_count = request.registry.share_information.get_share_count( effective_date) member_information = request.registry.member_information members_count = member_information.get_accepted_members_count( effective_date) members = member_information.get_accepted_members_sorted( effective_date) """ Then a LaTeX file is constructed... """ here = os.path.dirname(__file__) latex_header_tex = os.path.abspath( os.path.join(here, '../membership_list_pdflatex/header')) latex_footer_tex = os.path.abspath( os.path.join(here, '../membership_list_pdflatex/footer')) # a temporary directory for the latex run tempdir = tempfile.mkdtemp() # now we prepare a .tex file to be pdflatex'ed latex_file = tempfile.NamedTemporaryFile( suffix='.tex', dir=tempdir, delete=False, # directory will be deleted anyways ) # and where to store the output pdf_file = tempfile.NamedTemporaryFile( dir=tempdir, delete=False, # directory will be deleted anyways ) pdf_file.name = latex_file.name.replace('.tex', '.pdf') # construct latex data: header + variables latex_data = ''' \\input{%s} \\def\\numMembers{%s} \\def\\numShares{%s} \\def\\sumShares{%s} \\def\\today{%s} ''' % ( latex_header_tex, members_count, shares_count, shares_count * 50, effective_date.strftime('%d.%m.%Y'), ) # add to the latex document latex_data += ''' \\input{%s}''' % latex_footer_tex # print '*' * 70 # print latex_data # print '*' * 70 latex_file.write(latex_data.encode('utf-8')) # make table rows per member for member in members: address = '''\\scriptsize{}''' address += '''{}'''.format( unicode(TexTools.escape(member.address1)).encode('utf-8')) # check for contents of address2: if len(member.address2) > 0: address += '''\\linebreak {}'''.format( unicode(TexTools.escape(member.address2)).encode('utf-8')) # add more... address += ''' \\linebreak {} '''.format( unicode(TexTools.escape(member.postcode)).encode('utf-8')) address += '''{}'''.format( unicode(TexTools.escape(member.city)).encode('utf-8')) address += ''' ({})'''.format( unicode(TexTools.escape(member.country)).encode('utf-8')) member_share_count = \ request.registry.share_information.get_member_share_count( member.membership_number, effective_date) shares_count_printed += member_share_count membership_loss = u'' if member.membership_loss_date is not None: membership_loss += \ member.membership_loss_date.strftime('%d.%m.%Y') + \ '\\linebreak ' if member.membership_loss_type is not None: membership_loss += unicode(TexTools.escape( member.membership_loss_type)).encode('utf-8') latex_file.write( ''' {0} & {1} & {2} & {3} & {4} & {5} & {6} \\\\\\hline % '''.format( TexTools.escape(member.lastname).encode('utf-8'), # 0 ' \\footnotesize ' + TexTools.escape( member.firstname).encode('utf-8'), # 1 ' \\footnotesize ' + TexTools.escape( str(member.membership_number)), # 2 address, # 3 ' \\footnotesize ' + member.membership_date.strftime( '%d.%m.%Y'), # 4 ' \\footnotesize ' + membership_loss + ' ', # 5 ' \\footnotesize ' + str(member_share_count) # 6 )) latex_file.write(''' %\\end{tabular}% \\end{longtable}% \\label{LastPage} \\end{document} ''') latex_file.seek(0) # rewind # pdflatex latex_file to pdf_file fnull = open(os.devnull, 'w') # hide output pdflatex_output = subprocess.call( [ 'pdflatex', '-output-directory=%s' % tempdir, latex_file.name ], stdout=fnull, stderr=subprocess.STDOUT # hide output ) if DEBUG: # pragma: no cover print("the output of pdflatex run: %s" % pdflatex_output) # if run was a success, run X times more... if pdflatex_output == 0: for i in range(2): pdflatex_output = subprocess.call( [ 'pdflatex', '-output-directory=%s' % tempdir, latex_file.name ], stdout=fnull, stderr=subprocess.STDOUT # hide output ) if DEBUG: # pragma: no cover print("run #{} finished.".format(i+1)) # sanity check: did we print exactly as many shares as calculated? assert(shares_count == shares_count_printed) # return a pdf file response = Response(content_type='application/pdf') response.app_iter = open(pdf_file.name, "r") shutil.rmtree(tempdir, ignore_errors=True) # delete temporary directory return response
def gen_cert(member): ''' Utility function: create a membership certificate PDF file using pdflatex ''' certificate_path = os.path.join( os.path.dirname(__file__), '../../../certificate') if 'de' in member.locale: latex_background_image = os.path.abspath( os.path.join(certificate_path, 'Urkunde_Hintergrund_blank.pdf')) # latex header and footer latex_header_tex = os.path.abspath( os.path.join(certificate_path, 'urkunde_header_de.tex')) latex_footer_tex = os.path.abspath( os.path.join(certificate_path, 'urkunde_footer_de.tex')) else: latex_background_image = os.path.abspath( os.path.join(certificate_path, 'Urkunde_Hintergrund_blank.pdf')) # latex header and footer latex_header_tex = os.path.abspath( os.path.join(certificate_path, 'urkunde_header_en.tex')) latex_footer_tex = os.path.abspath( os.path.join(certificate_path, 'urkunde_footer_en.tex')) sign_meik = os.path.abspath( os.path.join(certificate_path, 'sign_meik.png')) sign_julian = os.path.abspath( os.path.join(certificate_path, 'sign_julian.png')) # a temporary directory for the latex run tempdir = tempfile.mkdtemp() latex_file = tempfile.NamedTemporaryFile( suffix='.tex', dir=tempdir, delete=False, # directory will be deleted anyways ) # using tempfile pdf_file = tempfile.NamedTemporaryFile( dir=tempdir, delete=False, # directory will be deleted anyways ) pdf_file.name = latex_file.name.replace('.tex', '.pdf') is_founder = True if 'dungHH_' in member.email_confirm_code else False # prepare the certificate text if member.locale == 'de': # german hereby_confirmed = u'Hiermit wird bestätigt, dass' is_member = u'Mitglied der Cultural Commons Collecting Society SCE ' \ u'mit beschränkter Haftung (C3S SCE) ist' one_more_share = u' und einen weiteren Geschäftsanteil übernommen hat' several_shares = u' weitere Geschäftsanteile übernommen hat' and_block = u' und ' if is_founder: confirm_date = ( u'Der Beitritt erfolgte im Rahmen der Gründung am 25.09.2013') else: confirm_date = u'Der Beitritt wurde am {} zugelassen'.format( datetime.strftime(member.membership_date, '%d.%m.%Y')) mship_num = u'Die Mitgliedsnummer lautet {}.'.format( member.membership_number ) mship_num_text = u'Mitgliedsnummer {}'.format( member.membership_number ) exec_dir = u'Geschäftsführender Direktor' else: # default fallback is english hereby_confirmed = u'This is to certify that' is_member = u'is a member of the >>Cultural Commons Collecting ' \ u'Society SCE mit beschränkter Haftung (C3S SCE)<<' one_more_share = u' and has subscribed to one additional share' several_shares = u'additional shares' and_block = u' and has subscribed to' if is_founder: confirm_date = ( u'Membership was acquired as a founding member ' 'on the 25th of September 2013') else: confirm_date = u'Registered on the {}'.format( datetime.strftime(member.membership_date, '%Y-%m-%d')) mship_num = u'The membership number is {}.'.format( member.membership_number ) mship_num_text = u'membership number {}'.format( member.membership_number ) exec_dir = u'Executive Director' # construct latex_file latex_data = ''' \\input{%s} \\def\\backgroundImage{%s} \\def\\txtBlkHerebyConfirmed{%s} \\def\\firstName{%s} \\def\\lastName{%s} \\def\\addressOne{%s} \\def\\postCode{%s} \\def\\city{%s} \\def\\numShares{%s} \\def\\numAddShares{%s} \\def\\txtBlkIsMember{%s} \\def\\txtBlkMembershipNumber{%s} \\def\\txtBlkConfirmDate{%s} \\def\\signDate{%s} \\def\\signMeik{%s} \\def\\signJulian{%s} \\def\\txtBlkCEO{%s} \\def\\txtBlkMembershipNum{%s} ''' % ( latex_header_tex, latex_background_image, hereby_confirmed, TexTools.escape(member.firstname), TexTools.escape(member.lastname), TexTools.escape(member.address1), TexTools.escape(member.postcode), TexTools.escape(member.city), member.num_shares, member.num_shares-1, is_member, TexTools.escape(mship_num), confirm_date, ( datetime.strftime(date.today(), "%d.%m.%Y") if member.locale == 'de' else date.today()), sign_meik, sign_julian, exec_dir, mship_num_text ) if member.is_legalentity: latex_data += '\n\\def\\company{%s}' % TexTools.escape(member.lastname) if member.address2 is not u'': # add address part 2 iff exists latex_data += '\n\\def\\addressTwo{%s}' % TexTools.escape( member.address2) if member.num_shares > 1: # how many shares? if member.num_shares == 2: # iff member has exactely two shares... latex_data += '\n\\def\\txtBlkAddShares{%s.}' % one_more_share if member.num_shares > 2: # iff more than two latex_data += '\n\\def\\txtBlkAddShares{%s %s %s.}' % ( and_block, member.num_shares-1, several_shares ) else: # iff member has exactely one share.. latex_data += '\n\\def\\txtBlkAddShares{.}' # finish the latex document latex_data += '\n\\input{%s}' % latex_footer_tex latex_file.write(latex_data.encode('utf-8')) latex_file.seek(0) # rewind # pdflatex latex_file to pdf_file # pdflatex_output = subprocess.call( [ 'pdflatex', '-output-directory=%s' % tempdir, latex_file.name ], stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT # hide output ) # return a pdf file response = Response(content_type='application/pdf') response.app_iter = open(pdf_file.name, "r") shutil.rmtree(tempdir, ignore_errors=True) # delete temporary directory return response
def gen_cert(member): ''' Utility function: create a membership certificate PDF file using pdflatex ''' here = os.path.dirname(__file__) if 'de' in member.locale: latex_background_image = os.path.abspath( os.path.join(here, '../certificate/Urkunde_Hintergrund_blank.pdf')) # latex header and footer latex_header_tex = os.path.abspath( os.path.join(here, '../certificate/urkunde_header_de.tex')) latex_footer_tex = os.path.abspath( os.path.join(here, '../certificate/urkunde_footer_de.tex')) else: latex_background_image = os.path.abspath( os.path.join(here, '../certificate/Urkunde_Hintergrund_blank.pdf')) # latex header and footer latex_header_tex = os.path.abspath( os.path.join(here, '../certificate/urkunde_header_en.tex')) latex_footer_tex = os.path.abspath( os.path.join(here, '../certificate/urkunde_footer_en.tex')) sign_meik = os.path.abspath( os.path.join(here, '../certificate/sign_meik.png')) sign_julian = os.path.abspath( os.path.join(here, '../certificate/sign_julian.png')) # a temporary directory for the latex run tempdir = tempfile.mkdtemp() latex_file = tempfile.NamedTemporaryFile( suffix='.tex', dir=tempdir, delete=False, # directory will be deleted anyways ) # using tempfile pdf_file = tempfile.NamedTemporaryFile( dir=tempdir, delete=False, # directory will be deleted anyways ) pdf_file.name = latex_file.name.replace('.tex', '.pdf') is_founder = True if 'dungHH_' in member.email_confirm_code else False # prepare the certificate text if member.locale == 'de': # german hereby_confirmed = u'Hiermit wird bestätigt, dass' is_member = u'Mitglied der Cultural Commons Collecting Society SCE ' \ u'mit beschränkter Haftung (C3S SCE) ist' one_more_share = u' und einen weiteren Geschäftsanteil übernommen hat' several_shares = u' weitere Geschäftsanteile übernommen hat' and_block = u' und ' if is_founder: confirm_date = ( u'Der Beitritt erfolgte im Rahmen der Gründung am 25.09.2013') else: confirm_date = u'Der Beitritt wurde am {} zugelassen'.format( datetime.strftime(member.membership_date, '%d.%m.%Y')) mship_num = u'Die Mitgliedsnummer lautet {}.'.format( member.membership_number) mship_num_text = u'Mitgliedsnummer {}'.format(member.membership_number) exec_dir = u'Geschäftsführender Direktor' else: # default fallback is english hereby_confirmed = u'This is to certify that' is_member = u'is a member of the >>Cultural Commons Collecting ' \ u'Society SCE mit beschränkter Haftung (C3S SCE)<<' one_more_share = u' and has subscribed to one additional share' several_shares = u'additional shares' and_block = u' and has subscribed to' if is_founder: confirm_date = (u'Membership was acquired as a founding member ' 'on the 25th of September 2013') else: confirm_date = u'Registered on the {}'.format( datetime.strftime(member.membership_date, '%Y-%m-%d')) mship_num = u'The membership number is {}.'.format( member.membership_number) mship_num_text = u'membership number {}'.format( member.membership_number) exec_dir = 'Executive Director' # construct latex_file latex_data = ''' \\input{%s} \\def\\backgroundImage{%s} \\def\\txtBlkHerebyConfirmed{%s} \\def\\firstName{%s} \\def\\lastName{%s} \\def\\addressOne{%s} \\def\\postCode{%s} \\def\\city{%s} \\def\\numShares{%s} \\def\\numAddShares{%s} \\def\\txtBlkIsMember{%s} \\def\\txtBlkMembershipNumber{%s} \\def\\txtBlkConfirmDate{%s} \\def\\signDate{%s} \\def\\signMeik{%s} \\def\\signJulian{%s} \\def\\txtBlkCEO{%s} \\def\\txtBlkMembershipNum{%s} ''' % (latex_header_tex, latex_background_image, hereby_confirmed, TexTools.escape(member.firstname), TexTools.escape(member.lastname), TexTools.escape(member.address1), TexTools.escape(member.postcode), TexTools.escape(member.city), member.num_shares, member.num_shares - 1, is_member, TexTools.escape(mship_num), confirm_date, (datetime.strftime(date.today(), "%d.%m.%Y") if member.locale == 'de' else date.today()), sign_meik, sign_julian, exec_dir, mship_num_text) if DEBUG: # pragma: no cover print('#' * 60) print(member.is_legalentity) print(member.lastname) print('#' * 60) if member.is_legalentity: latex_data += '\n\\def\\company{%s}' % TexTools.escape(member.lastname) if member.address2 is not u'': # add address part 2 iff exists latex_data += '\n\\def\\addressTwo{%s}' % TexTools.escape( member.address2) if member.num_shares > 1: # how many shares? if member.num_shares == 2: # iff member has exactely two shares... latex_data += '\n\\def\\txtBlkAddShares{%s.}' % one_more_share if member.num_shares > 2: # iff more than two latex_data += '\n\\def\\txtBlkAddShares{%s %s %s.}' % ( and_block, member.num_shares - 1, several_shares) else: # iff member has exactely one share.. latex_data += '\n\\def\\txtBlkAddShares{.}' # finish the latex document latex_data += '\n\\input{%s}' % latex_footer_tex if DEBUG: # pragma: no cover print '*' * 70 print('*' * 30, 'latex data: ', '*' * 30) print '*' * 70 print latex_data print '*' * 70 latex_file.write(latex_data.encode('utf-8')) latex_file.seek(0) # rewind # pdflatex latex_file to pdf_file # pdflatex_output = subprocess.call( ['pdflatex', '-output-directory=%s' % tempdir, latex_file.name], stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT # hide output ) # return a pdf file response = Response(content_type='application/pdf') response.app_iter = open(pdf_file.name, "r") shutil.rmtree(tempdir, ignore_errors=True) # delete temporary directory return response
def gen_cert(member): """ Utility function: create a membership certificate PDF file using pdflatex """ here = os.path.dirname(__file__) if "de" in member.locale: latex_background_image = os.path.abspath(os.path.join(here, "../certificate/Urkunde_Hintergrund_blank.pdf")) # latex header and footer latex_header_tex = os.path.abspath(os.path.join(here, "../certificate/urkunde_header_de.tex")) latex_footer_tex = os.path.abspath(os.path.join(here, "../certificate/urkunde_footer_de.tex")) else: latex_background_image = os.path.abspath(os.path.join(here, "../certificate/Urkunde_Hintergrund_blank.pdf")) # latex header and footer latex_header_tex = os.path.abspath(os.path.join(here, "../certificate/urkunde_header_en.tex")) latex_footer_tex = os.path.abspath(os.path.join(here, "../certificate/urkunde_footer_en.tex")) sign_meik = os.path.abspath(os.path.join(here, "../certificate/sign_meik.png")) sign_max = os.path.abspath(os.path.join(here, "../certificate/sign_max.png")) # a temporary directory for the latex run tempdir = tempfile.mkdtemp() latex_file = tempfile.NamedTemporaryFile( suffix=".tex", dir=tempdir, delete=False # directory will be deleted anyways ) # using tempfile pdf_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False) # directory will be deleted anyways pdf_file.name = latex_file.name.replace(".tex", ".pdf") is_founder = True if "dungHH_" in member.email_confirm_code else False # prepare the certificate text if member.locale == "de": # german hereby_confirmed = u"Hiermit wird bestätigt, dass" is_member = u"Mitglied der Cultural Commons Collecting Society SCE " u"mit beschränkter Haftung (C3S SCE) ist" one_more_share = u" und einen weiteren Geschäftsanteil übernommen hat" several_shares = u" weitere Geschäftsanteile übernommen hat" and_block = u" und " if is_founder: confirm_date = u"Der Beitritt erfolgte im Rahmen der Gründung am 25.09.2013" else: confirm_date = u"Der Beitritt wurde am {} zugelassen".format( datetime.strftime(member.membership_date, "%d.%m.%Y") ) mship_num = u"Die Mitgliedsnummer lautet {}.".format(member.membership_number) mship_num_text = u"Mitgliedsnummer {}".format(member.membership_number) exec_dir = u"Geschäftsführender Direktor" else: # default fallback is english hereby_confirmed = u"This is to certify that" is_member = ( u"is a member of the >>Cultural Commons Collecting " u"Society SCE mit beschränkter Haftung (C3S SCE)<<" ) one_more_share = u" and has subscribed to one additional share" several_shares = u"additional shares" and_block = u" and has subscribed to" if is_founder: confirm_date = u"Membership was aquired as a founding member " "on the 25th of September 2013" else: confirm_date = u"Registered on the {}".format(datetime.strftime(member.membership_date, "%Y-%m-%d")) mship_num = u"The membership number is {}.".format(member.membership_number) mship_num_text = u"membership number {}".format(member.membership_number) exec_dir = "Executive Director" # construct latex_file latex_data = """ \\input{%s} \\def\\backgroundImage{%s} \\def\\txtBlkHerebyConfirmed{%s} \\def\\firstName{%s} \\def\\lastName{%s} \\def\\addressOne{%s} \\def\\postCode{%s} \\def\\city{%s} \\def\\numShares{%s} \\def\\numAddShares{%s} \\def\\txtBlkIsMember{%s} \\def\\txtBlkMembershipNumber{%s} \\def\\txtBlkConfirmDate{%s} \\def\\signDate{%s} \\def\\signMeik{%s} \\def\\signMax{%s} \\def\\txtBlkCEO{%s} \\def\\txtBlkMembershipNum{%s} """ % ( latex_header_tex, latex_background_image, hereby_confirmed, TexTools.escape(member.firstname), TexTools.escape(member.lastname), TexTools.escape(member.address1), TexTools.escape(member.postcode), TexTools.escape(member.city), member.num_shares, member.num_shares - 1, is_member, TexTools.escape(mship_num), confirm_date, (datetime.strftime(date.today(), "%d.%m.%Y") if member.locale == "de" else date.today()), sign_meik, sign_max, exec_dir, mship_num_text, ) if DEBUG: # pragma: no cover print ("#" * 60) print (member.is_legalentity) print (member.lastname) print ("#" * 60) if member.is_legalentity: latex_data += "\n\\def\\company{%s}" % TexTools.escape(member.lastname) if member.address2 is not u"": # add address part 2 iff exists latex_data += "\n\\def\\addressTwo{%s}" % TexTools.escape(member.address2) if member.num_shares > 1: # how many shares? if member.num_shares == 2: # iff member has exactely two shares... latex_data += "\n\\def\\txtBlkAddShares{%s.}" % one_more_share if member.num_shares > 2: # iff more than two latex_data += "\n\\def\\txtBlkAddShares{%s %s %s.}" % (and_block, member.num_shares - 1, several_shares) else: # iff member has exactely one share.. latex_data += "\n\\def\\txtBlkAddShares{.}" # finish the latex document latex_data += "\n\\input{%s}" % latex_footer_tex if DEBUG: # pragma: no cover print "*" * 70 print ("*" * 30, "latex data: ", "*" * 30) print "*" * 70 print latex_data print "*" * 70 latex_file.write(latex_data.encode("utf-8")) latex_file.seek(0) # rewind # pdflatex latex_file to pdf_file # pdflatex_output = subprocess.call( ["pdflatex", "-output-directory=%s" % tempdir, latex_file.name], stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT, # hide output ) # return a pdf file response = Response(content_type="application/pdf") response.app_iter = open(pdf_file.name, "r") shutil.rmtree(tempdir, ignore_errors=True) # delete temporary directory return response
def make_reversal_pdf_pdflatex(member, invoice=None): """ This function uses pdflatex to create a PDF as reversal invoice: cancel and balance out a former invoice. """ dues17_archive_invoice = get_dues17_archive_invoice(invoice) if dues17_archive_invoice is not None: return dues17_archive_invoice pdflatex_dir = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../certificate/')) # pdf backgrounds pdf_backgrounds = { 'blank': pdflatex_dir + '/' + 'Urkunde_Hintergrund_blank.pdf', } # latex templates latex_templates = { 'generic': pdflatex_dir + '/' + 'dues17_storno_de.tex', 'generic_en': pdflatex_dir + '/' + 'dues17_storno_en.tex', } # choose background and template background = 'blank' template_name = 'generic' if 'de' in member.locale else 'generic_en' # pick background and template bg_pdf = pdf_backgrounds[background] tpl_tex = latex_templates[template_name] # pick temporary file for pdf receipt_pdf = tempfile.NamedTemporaryFile(prefix='storno_', suffix='.pdf') (path, filename) = os.path.split(receipt_pdf.name) filename = os.path.splitext(filename)[0] invoice_no = str(invoice.invoice_no).zfill(4) + '-S' invoice_date = invoice.invoice_date.strftime('%d. %m. %Y') # set variables for tex command tex_vars = { 'personalFirstname': member.firstname, 'personalLastname': member.lastname, 'personalAddressOne': member.address1, 'personalAddressTwo': member.address2, 'personalPostCode': member.postcode, 'personalCity': member.city, 'personalMShipNo': unicode(member.membership_number), 'invoiceNo': invoice_no, 'invoiceDate': invoice_date, 'duesAmount': unicode(invoice.invoice_amount), 'origInvoiceRef': ('C3S-dues2017-' + str(invoice.preceding_invoice_no).zfill(4)), 'lang': 'de', 'pdfBackground': bg_pdf, } # generate tex command for pdflatex tex_cmd = u'' for key, val in tex_vars.iteritems(): tex_cmd += '\\newcommand{\\%s}{%s}' % (key, TexTools.escape(val)) tex_cmd += '\\input{%s}' % tpl_tex tex_cmd = u'"' + tex_cmd + '"' # XXX: try to find out, why utf-8 doesn't work on debian subprocess.call( [ 'pdflatex', '-jobname', filename, '-output-directory', path, '-interaction', 'nonstopmode', '-halt-on-error', tex_cmd.encode('latin_1') ], stdout=open(os.devnull, 'w'), # hide output stderr=subprocess.STDOUT, cwd=pdflatex_dir) # cleanup aux = os.path.join(path, filename + '.aux') if os.path.isfile(aux): os.unlink(aux) archive_dues17_invoice(receipt_pdf, invoice) return receipt_pdf
def make_invoice_pdf_pdflatex(member, invoice=None): """ This function uses pdflatex to create a PDF as receipt for the members membership dues. default output is the current invoice. if i_no is suplied, the relevant invoice number is produced """ dues17_archive_invoice = get_dues17_archive_invoice(invoice) if dues17_archive_invoice is not None: return dues17_archive_invoice # directory of pdf and tex files pdflatex_dir = os.path.abspath( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../certificate/')) # pdf backgrounds pdf_backgrounds = { 'blank': pdflatex_dir + '/' + 'Urkunde_Hintergrund_blank.pdf', } # latex templates latex_templates = { # 'generic': pdflatex_dir + '/' + 'membership_dues_receipt.tex', 'generic': pdflatex_dir + '/' + 'dues17_invoice_de.tex', 'generic_en': pdflatex_dir + '/' + 'dues17_invoice_en.tex', } # choose background and template background = 'blank' template_name = 'generic' if 'de' in member.locale else 'generic_en' # pick background and template bg_pdf = pdf_backgrounds[background] tpl_tex = latex_templates[template_name] # pick temporary file for pdf receipt_pdf = tempfile.NamedTemporaryFile(prefix='invoice_', suffix='.pdf') (path, filename) = os.path.split(receipt_pdf.name) filename = os.path.splitext(filename)[0] # on invoice, print start quarter or "reduced". prepare string: if (not invoice.is_reversal and invoice.is_altered and invoice.preceding_invoice_no is not None): is_altered_str = u'angepasst' if ('de' in member.locale) else u'altered' if invoice is not None: # use invoice no from URL invoice_no = str(invoice.invoice_no).zfill(4) invoice_date = invoice.invoice_date.strftime('%d. %m. %Y') else: # pragma: no cover # this branch is deprecated, because we always supply an invoice number # use invoice no from member record invoice_no = str(member.dues17_invoice_no).zfill(4) invoice_date = member.dues17_invoice_date # set variables for tex command tex_vars = { 'personalFirstname': member.firstname, 'personalLastname': member.lastname, 'personalAddressOne': member.address1, 'personalAddressTwo': member.address2, 'personalPostCode': member.postcode, 'personalCity': member.city, 'personalMShipNo': unicode(member.membership_number), 'invoiceNo': str(invoice_no).zfill(4), # leading zeroes! 'invoiceDate': invoice_date, 'account': unicode(-member.dues15_balance - member.dues16_balance \ - member.dues17_balance), 'duesStart': is_altered_str if ( invoice.is_altered) else string_start_quarter_dues17(member), 'duesAmount': unicode(invoice.invoice_amount), 'lang': 'de', 'pdfBackground': bg_pdf, } # generate tex command for pdflatex tex_cmd = u'' for key, val in tex_vars.iteritems(): tex_cmd += '\\newcommand{\\%s}{%s}' % (key, TexTools.escape(val)) tex_cmd += '\\input{%s}' % tpl_tex tex_cmd = u'"' + tex_cmd + '"' # make latex show ß correctly in pdf: tex_cmd = tex_cmd.replace(u'ß', u'\\ss{}') # XXX: try to find out, why utf-8 doesn't work on debian subprocess.call( [ 'pdflatex', '-jobname', filename, '-output-directory', path, '-interaction', 'nonstopmode', '-halt-on-error', tex_cmd.encode('latin_1') ], stdout=open(os.devnull, 'w'), # hide output stderr=subprocess.STDOUT, cwd=pdflatex_dir) # cleanup aux = os.path.join(path, filename + '.aux') if os.path.isfile(aux): os.unlink(aux) archive_dues17_invoice(receipt_pdf, invoice) return receipt_pdf
def make_reversal_pdf_pdflatex(member, invoice=None): """ This function uses pdflatex to create a PDF as reversal invoice: cancel and balance out a former invoice. """ dues16_archive_invoice = get_dues16_archive_invoice(invoice) if dues16_archive_invoice is not None: return dues16_archive_invoice pdflatex_dir = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../../../certificate/' )) # pdf backgrounds pdf_backgrounds = { 'blank': pdflatex_dir + '/' + 'Urkunde_Hintergrund_blank.pdf', } # latex templates latex_templates = { 'generic': pdflatex_dir + '/' + 'dues16_storno_de.tex', 'generic_en': pdflatex_dir + '/' + 'dues16_storno_en.tex', } # choose background and template background = 'blank' template_name = 'generic' if 'de' in member.locale else 'generic_en' # pick background and template bg_pdf = pdf_backgrounds[background] tpl_tex = latex_templates[template_name] # pick temporary file for pdf receipt_pdf = tempfile.NamedTemporaryFile(prefix='storno_', suffix='.pdf') (path, filename) = os.path.split(receipt_pdf.name) filename = os.path.splitext(filename)[0] invoice_no = str(invoice.invoice_no).zfill(4) + '-S' invoice_date = invoice.invoice_date.strftime('%d. %m. %Y') # set variables for tex command tex_vars = { 'personalFirstname': member.firstname, 'personalLastname': member.lastname, 'personalAddressOne': member.address1, 'personalAddressTwo': member.address2, 'personalPostCode': member.postcode, 'personalCity': member.city, 'personalMShipNo': unicode(member.membership_number), 'invoiceNo': invoice_no, 'invoiceDate': invoice_date, 'duesAmount': unicode(invoice.invoice_amount), 'origInvoiceRef': ('C3S-dues2016-' + str(invoice.preceding_invoice_no).zfill(4)), 'lang': 'de', 'pdfBackground': bg_pdf, } # generate tex command for pdflatex tex_cmd = u'' for key, val in tex_vars.iteritems(): tex_cmd += '\\newcommand{\\%s}{%s}' % (key, TexTools.escape(val)) tex_cmd += '\\input{%s}' % tpl_tex tex_cmd = u'"'+tex_cmd+'"' # XXX: try to find out, why utf-8 doesn't work on debian subprocess.call( [ 'pdflatex', '-jobname', filename, '-output-directory', path, '-interaction', 'nonstopmode', '-halt-on-error', tex_cmd.encode('latin_1') ], stdout=open(os.devnull, 'w'), # hide output stderr=subprocess.STDOUT, cwd=pdflatex_dir ) # cleanup aux = os.path.join(path, filename + '.aux') if os.path.isfile(aux): os.unlink(aux) archive_dues16_invoice(receipt_pdf, invoice) return receipt_pdf
def make_invoice_pdf_pdflatex(member, invoice=None): """ This function uses pdflatex to create a PDF as receipt for the members membership dues. default output is the current invoice. if i_no is suplied, the relevant invoice number is produced """ dues16_archive_invoice = get_dues16_archive_invoice(invoice) if dues16_archive_invoice is not None: return dues16_archive_invoice # directory of pdf and tex files pdflatex_dir = os.path.abspath( os.path.join( os.path.dirname(os.path.abspath(__file__)), '../../../certificate/' )) # pdf backgrounds pdf_backgrounds = { 'blank': pdflatex_dir + '/' + 'Urkunde_Hintergrund_blank.pdf', } # latex templates latex_templates = { # 'generic': pdflatex_dir + '/' + 'membership_dues_receipt.tex', 'generic': pdflatex_dir + '/' + 'dues16_invoice_de.tex', 'generic_en': pdflatex_dir + '/' + 'dues16_invoice_en.tex', } # choose background and template background = 'blank' template_name = 'generic' if 'de' in member.locale else 'generic_en' # pick background and template bg_pdf = pdf_backgrounds[background] tpl_tex = latex_templates[template_name] # pick temporary file for pdf receipt_pdf = tempfile.NamedTemporaryFile(prefix='invoice_', suffix='.pdf') (path, filename) = os.path.split(receipt_pdf.name) filename = os.path.splitext(filename)[0] # on invoice, print start quarter or "reduced". prepare string: if ( not invoice.is_reversal and invoice.is_altered and invoice.preceding_invoice_no is not None): is_altered_str = u'angepasst' if ( 'de' in member.locale) else u'altered' if invoice is not None: # use invoice no from URL invoice_no = str(invoice.invoice_no).zfill(4) invoice_date = invoice.invoice_date.strftime('%d. %m. %Y') else: # pragma: no cover # this branch is deprecated, because we always supply an invoice number # use invoice no from member record invoice_no = str(invoice.invoice_no).zfill(4) invoice_date = invoice.invoice_date dues15_balance = D('0.0') dues16_balance = D('0.0') if not math.isnan(member.dues15_balance): dues15_balance = member.dues15_balance if not math.isnan(member.dues16_balance): dues16_balance = member.dues16_balance # set variables for tex command tex_vars = { 'personalFirstname': member.firstname, 'personalLastname': member.lastname, 'personalAddressOne': member.address1, 'personalAddressTwo': member.address2, 'personalPostCode': member.postcode, 'personalCity': member.city, 'personalMShipNo': unicode(member.membership_number), 'invoiceNo': str(invoice_no).zfill(4), # leading zeroes! 'invoiceDate': invoice_date, 'account': unicode(-dues15_balance - dues16_balance), 'duesStart': is_altered_str if ( invoice.is_altered) else string_start_quarter_dues16(member), 'duesAmount': unicode(invoice.invoice_amount), 'lang': 'de', 'pdfBackground': bg_pdf, } # generate tex command for pdflatex tex_cmd = u'' for key, val in tex_vars.iteritems(): tex_cmd += '\\newcommand{\\%s}{%s}' % (key, TexTools.escape(val)) tex_cmd += '\\input{%s}' % tpl_tex tex_cmd = u'"'+tex_cmd+'"' # make latex show ß correctly in pdf: tex_cmd = tex_cmd.replace(u'ß', u'\\ss{}') # XXX: try to find out, why utf-8 doesn't work on debian # TODO: Handle any return code not equal to zero subprocess.call( [ 'pdflatex', '-jobname', filename, '-output-directory', path, '-interaction', 'nonstopmode', '-halt-on-error', tex_cmd.encode('latin_1') ], stdout=open(os.devnull, 'w'), # hide output stderr=subprocess.STDOUT, cwd=pdflatex_dir ) # cleanup aux = os.path.join(path, filename + '.aux') if os.path.isfile(aux): os.unlink(aux) archive_dues16_invoice(receipt_pdf, invoice) return receipt_pdf