def first_post_letter(letter): pdfs = [] pdfs.append( utils.render_tex_to_pdf("correspondence/first-post-template.tex", {'letter': letter})) # First post, if any. First post uses a dynamic document rather than the # letter.document field, so that if a document is ever removed/unpublished, # we get the updated "first post" on printout. try: document = Document.objects.filter( status="published", type="post", author__pk=letter.recipient.pk).order_by('date_written')[0] pdfs.append(utils.url_to_pdf(document.get_absolute_url())) except IndexError: pass # Profile, if any if Document.objects.filter( status="published", type="profile", author__pk=letter.recipient.pk).order_by('-date_written').exists(): pdfs.append( utils.url_to_pdf(letter.recipient.profile.get_absolute_url())) if not pdfs: return None combined_pdf = utils.combine_pdfs(*pdfs) for pdf in pdfs: os.remove(pdf) return combined_pdf
def first_post_letter(letter): pdfs = [] pdfs.append( utils.render_tex_to_pdf("correspondence/first-post-template.tex", { 'letter': letter }) ) # First post, if any. First post uses a dynamic document rather than the # letter.document field, so that if a document is ever removed/unpublished, # we get the updated "first post" on printout. try: document = Document.objects.filter(status="published", type="post", author__pk=letter.recipient.pk).order_by('date_written')[0] pdfs.append(utils.url_to_pdf(document.get_absolute_url())) except IndexError: pass # Profile, if any if Document.objects.filter(status="published", type="profile", author__pk=letter.recipient.pk).order_by('-date_written').exists(): pdfs.append(utils.url_to_pdf(letter.recipient.profile.get_absolute_url())) if not pdfs: return None combined_pdf = utils.combine_pdfs(*pdfs) for pdf in pdfs: os.remove(pdf) return combined_pdf
def comments_letter(letter): pdfs = [ # cover letter utils.render_tex_to_pdf("correspondence/comment-mailing.tex", {"letter": letter}), utils.url_to_pdf(reverse("correspondence.recent_comments_letter", args=[letter.pk])), ] combined_pdf = utils.combine_pdfs(*pdfs) for pdf in pdfs: os.remove(pdf) return combined_pdf
def comments_letter(letter): pdfs = [ # cover letter utils.render_tex_to_pdf("correspondence/comment-mailing.tex", {'letter': letter}), utils.url_to_pdf( reverse("correspondence.recent_comments_letter", args=[letter.pk])) ] combined_pdf = utils.combine_pdfs(*pdfs) for pdf in pdfs: os.remove(pdf) return combined_pdf
def consent_form(letter): parts = [] delete_after = [] if letter.org.custom_intro_packet: parts.append(letter.org.custom_intro_packet.path) else: cover = utils.render_tex_to_pdf("correspondence/intro-packet-cover.tex", {"letter": letter}) parts.append(cover) delete_after.append(cover) packet = utils.render_tex_to_pdf( "correspondence/intro-packet-packet.tex", {"MEDIA_ROOT": settings.MEDIA_ROOT, "letter": letter} ) parts.append(packet) delete_after.append(packet) parts.append(os.path.join(settings.MEDIA_ROOT, "intro", "license.pdf")) combined = utils.combine_pdfs(*parts, add_blanks=True) for pdf in delete_after: os.remove(pdf) return combined
def consent_form(letter): parts = [] delete_after = [] if letter.org.custom_intro_packet: parts.append(letter.org.custom_intro_packet.path) else: cover = utils.render_tex_to_pdf( "correspondence/intro-packet-cover.tex", {'letter': letter}) parts.append(cover) delete_after.append(cover) packet = utils.render_tex_to_pdf( "correspondence/intro-packet-packet.tex", { 'MEDIA_ROOT': settings.MEDIA_ROOT, 'letter': letter }) parts.append(packet) delete_after.append(packet) parts.append(os.path.join(settings.MEDIA_ROOT, "intro", "license.pdf")) combined = utils.combine_pdfs(*parts, add_blanks=True) for pdf in delete_after: os.remove(pdf) return combined
def generate_colation(mailing): """ Generates a zip file containing all of the letters and envelopes for a particular mailing. The output has the following structure: mailings-YYYY-MM-DD/ letters/ (all letters, individually) envelopes/ (all envelopes) postcards/ (any other postcard type) all_letters.pdf -- all letters of all kinds (not postcards) combined for double-sided printing manifest.csv -- CSV file with sheet counts and names. addresses.csv -- CSV file with all addresses, one column per line, front-padded """ tmpdir = tempfile.mkdtemp(prefix="colation") outname = "mailings-%s_%s" % ( datetime.datetime.now().strftime("%Y-%m-%d"), mailing.pk, ) outdir = os.path.join(tmpdir, outname) os.makedirs(outdir) # also makes outdir manifest = {"letters": [], "postcards": []} for letter in mailing.letters.all(): if not letter.get_file(): continue details = { "recipient": letter.get_recipient_address(), "sender": letter.org.mailing_address, "type": letter.type, "file": letter.get_file(), "id": letter.id, } details["slug"] = slugify(details["recipient"].split("\n")[0]) if letter.is_postcard: manifest["postcards"].append(details) else: manifest["letters"].append(details) # Write envelopes if manifest["letters"]: envelope_dir = os.path.join(outdir, "envelopes") os.makedirs(envelope_dir) unique_envelopes = set((d["slug"], d["recipient"], d["sender"]) for d in manifest["letters"]) for slug, addr, from_address in unique_envelopes: env_fh = utils.build_envelope(from_address=from_address, to_address=addr) path = os.path.join(envelope_dir, "%s-envelope.jpg" % slug) with open(path, 'w') as fh: fh.write(env_fh.getvalue()) # Write postcards for key in ("postcards", "letters"): if not manifest[key]: continue file_dir = os.path.join(outdir, key) os.makedirs(file_dir) for details in manifest[key]: dest = os.path.join( file_dir, "{0}-{1}{2}.{3}".format( details["slug"], details["type"], details["id"], ("jpg" if key == "postcards" else "pdf"))) shutil.copy(details["file"], dest) # Replace 'file' in manifest with zipfile-relative path details["file"] = os.path.relpath(dest, outdir) # Make combined letters pdf. if manifest["letters"]: sorted_pdfs = sorted( glob.glob(os.path.join(outdir, "letters", "*.pdf"))) utils.combine_pdfs(*sorted_pdfs, add_blanks=True, filename=os.path.join(outdir, "all_letters.pdf")) # Write manifest file with open(os.path.join(outdir, "manifest.json"), 'w') as fh: json.dump(manifest, fh, indent=2) # Zip tmp_zip_path = "{0}.zip".format(outdir) zipbase = os.path.basename(outdir) proc = subprocess.Popen(["/usr/bin/zip", "-r", zipbase, zipbase], cwd=tmpdir) # zip adds ".zip" proc.communicate() # Clean up dest = os.path.join(settings.MEDIA_ROOT, "mailings", os.path.basename(outname) + ".zip") try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.move(tmp_zip_path, dest) proc = subprocess.Popen(["rm", "-r", tmpdir]) return os.path.relpath(dest, settings.MEDIA_ROOT)
def generate_colation(mailing): """ Generates a zip file containing all of the letters and envelopes for a particular mailing. The output has the following structure: mailings-YYYY-MM-DD/ letters/ (all letters, individually) envelopes/ (all envelopes) postcards/ (any other postcard type) all_letters.pdf -- all letters of all kinds (not postcards) combined for double-sided printing manifest.csv -- CSV file with sheet counts and names. addresses.csv -- CSV file with all addresses, one column per line, front-padded """ tmpdir = tempfile.mkdtemp(prefix="colation") outname = "mailings-%s_%s" % ( datetime.datetime.now().strftime("%Y-%m-%d"), mailing.pk, ) outdir = os.path.join(tmpdir, outname) os.makedirs(outdir) # also makes outdir envelopes = set() postcards = [] letters = [] manifest = defaultdict(int) for letter in mailing.letters.all(): if not letter.get_file(): continue address = letter.get_recipient_address() slug = slugify(address.split("\n")[0]) if letter.is_postcard: postcards.append((slug, letter)) continue letters.append((slug, letter)) envelopes.add((slug, address, letter.org.mailing_address)) count = get_pdf_page_count(letter.get_file()) if count: manifest[(slug, address)] += count # Write manifest file if manifest: items = manifest.items() items.sort() rows = [(a.split("\n")[0].strip(), str((c + c % 2) / 2)) for (s, a), c in items] utils.write_csv(rows, os.path.join(outdir, "manifest.csv")) # Write envelopes if envelopes: envelope_dir = os.path.join(outdir, "envelopes") os.makedirs(envelope_dir) for slug, addr, from_address in envelopes: env_fh = utils.build_envelope(from_address=from_address, to_address=addr) path = os.path.join(envelope_dir, "%s-envelope.jpg" % slug) with open(path, 'w') as fh: fh.write(env_fh.getvalue()) # Write addresses CSV sorted_addresses = [a for s, a, r in sorted(envelopes)] utils.write_address_csv(sorted_addresses, os.path.join(outdir, "addresses.csv")) # Write postcards if postcards: postcard_dir = os.path.join(outdir, "postcards") os.makedirs(postcard_dir) for slug, postcard in postcards: dest = os.path.join( postcard_dir, "{0}-{1}{2}.jpg".format(slug, postcard.type, postcard.pk)) shutil.copy(postcard.get_file(), dest) # Copy and combine letters if letters: letter_dir = os.path.join(outdir, "letters") os.makedirs(letter_dir) for slug, letter in letters: dest = os.path.join( letter_dir, "{0}-{1}{2}.pdf".format(slug, letter.type, letter.pk)) shutil.copy(letter.get_file(), dest) sorted_pdfs = sorted(glob.glob(os.path.join(letter_dir, "*.pdf"))) utils.combine_pdfs(*sorted_pdfs, add_blanks=True, filename=os.path.join(outdir, "all_letters.pdf")) # Zip tmp_zip_path = "{0}.zip".format(outdir) zipbase = os.path.basename(outdir) proc = subprocess.Popen(["/usr/bin/zip", "-r", zipbase, zipbase], cwd=tmpdir) # zip adds ".zip" proc.communicate() # Clean up dest = os.path.join(settings.MEDIA_ROOT, "mailings", os.path.basename(outname) + ".zip") try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.move(tmp_zip_path, dest) proc = subprocess.Popen(["rm", "-r", tmpdir]) return os.path.relpath(dest, settings.MEDIA_ROOT)
def combine_pdfs_task(pdf_files): from correspondence import utils combined = utils.combine_pdfs(*pdf_files) return combined
def generate_colation(mailing): """ Generates a zip file containing all of the letters and envelopes for a particular mailing. The output has the following structure: mailings-YYYY-MM-DD/ letters/ (all letters, individually) envelopes/ (all envelopes) postcards/ (any other postcard type) all_letters.pdf -- all letters of all kinds (not postcards) combined for double-sided printing manifest.csv -- CSV file with sheet counts and names. addresses.csv -- CSV file with all addresses, one column per line, front-padded """ tmpdir = tempfile.mkdtemp(prefix="colation") outname = "mailings-%s_%s" % ( datetime.datetime.now().strftime("%Y-%m-%d"), mailing.pk, ) outdir = os.path.join(tmpdir, outname) os.makedirs(outdir) # also makes outdir envelopes = set() postcards = [] letters = [] manifest = defaultdict(int) for letter in mailing.letters.all(): if not letter.get_file(): continue address = letter.get_recipient_address() slug = slugify(address.split("\n")[0]) if letter.is_postcard: postcards.append((slug, letter)) continue letters.append((slug, letter)) envelopes.add((slug, address, letter.org.mailing_address)) count = get_pdf_page_count(letter.get_file()) if count: manifest[(slug, address)] += count # Write manifest file if manifest: items = manifest.items() items.sort() rows = [(a.split("\n")[0].strip(), str((c + c%2)/2)) for (s, a),c in items] utils.write_csv(rows, os.path.join(outdir, "manifest.csv")) # Write envelopes if envelopes: envelope_dir = os.path.join(outdir, "envelopes") os.makedirs(envelope_dir) for slug, addr, from_address in envelopes: env_fh = utils.build_envelope( from_address=from_address, to_address=addr) path = os.path.join(envelope_dir, "%s-envelope.jpg" % slug) with open(path, 'w') as fh: fh.write(env_fh.getvalue()) # Write addresses CSV sorted_addresses = [a for s, a, r in sorted(envelopes)] utils.write_address_csv(sorted_addresses, os.path.join(outdir, "addresses.csv")) # Write postcards if postcards: postcard_dir = os.path.join(outdir, "postcards") os.makedirs(postcard_dir) for slug, postcard in postcards: dest = os.path.join(postcard_dir, "{0}-{1}{2}.jpg".format( slug, postcard.type, postcard.pk )) shutil.copy(postcard.get_file(), dest) # Copy and combine letters if letters: letter_dir = os.path.join(outdir, "letters") os.makedirs(letter_dir) for slug, letter in letters: dest = os.path.join(letter_dir, "{0}-{1}{2}.pdf".format(slug, letter.type, letter.pk)) shutil.copy(letter.get_file(), dest) sorted_pdfs = sorted(glob.glob(os.path.join(letter_dir, "*.pdf"))) utils.combine_pdfs(*sorted_pdfs, add_blanks=True, filename=os.path.join(outdir, "all_letters.pdf") ) # Zip tmp_zip_path = "{0}.zip".format(outdir) zipbase = os.path.basename(outdir) proc = subprocess.Popen(["/usr/bin/zip", "-r", zipbase, zipbase], cwd=tmpdir) # zip adds ".zip" proc.communicate() # Clean up dest = os.path.join(settings.MEDIA_ROOT, "mailings", os.path.basename(outname) + ".zip") try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.move(tmp_zip_path, dest) proc = subprocess.Popen(["rm", "-r", tmpdir]) return os.path.relpath(dest, settings.MEDIA_ROOT)
def generate_colation(mailing): """ Generates a zip file containing all of the letters and envelopes for a particular mailing. The output has the following structure: mailings-YYYY-MM-DD/ letters/ (all letters, individually) envelopes/ (all envelopes) postcards/ (any other postcard type) all_letters.pdf -- all letters of all kinds (not postcards) combined for double-sided printing manifest.csv -- CSV file with sheet counts and names. addresses.csv -- CSV file with all addresses, one column per line, front-padded """ tmpdir = tempfile.mkdtemp(prefix="colation") outname = "mailings-%s_%s" % ( datetime.datetime.now().strftime("%Y-%m-%d"), mailing.pk, ) outdir = os.path.join(tmpdir, outname) os.makedirs(outdir) # also makes outdir manifest = {"letters": [], "postcards": []} for letter in mailing.letters.all(): if not letter.get_file(): continue details = { "recipient": letter.get_recipient_address(), "sender": letter.org.mailing_address, "type": letter.type, "file": letter.get_file(), "id": letter.id, } details["slug"] = slugify(details["recipient"].split("\n")[0]) if letter.is_postcard: manifest["postcards"].append(details) else: manifest["letters"].append(details) # Write envelopes if manifest["letters"]: envelope_dir = os.path.join(outdir, "envelopes") os.makedirs(envelope_dir) unique_envelopes = set( (d["slug"], d["recipient"], d["sender"]) for d in manifest["letters"] ) for slug, addr, from_address in unique_envelopes: env_fh = utils.build_envelope(from_address=from_address, to_address=addr) path = os.path.join(envelope_dir, "%s-envelope.jpg" % slug) with open(path, 'w') as fh: fh.write(env_fh.getvalue()) # Write postcards for key in ("postcards", "letters"): if not manifest[key]: continue file_dir = os.path.join(outdir, key) os.makedirs(file_dir) for details in manifest[key]: dest = os.path.join(file_dir, "{0}-{1}{2}.{3}".format( details["slug"], details["type"], details["id"], ("jpg" if key == "postcards" else "pdf") )) shutil.copy(details["file"], dest) # Replace 'file' in manifest with zipfile-relative path details["file"] = os.path.relpath(dest, outdir) # Make combined letters pdf. if manifest["letters"]: sorted_pdfs = sorted(glob.glob(os.path.join(outdir, "letters", "*.pdf"))) utils.combine_pdfs(*sorted_pdfs, add_blanks=True, filename=os.path.join(outdir, "all_letters.pdf") ) # Write manifest file with open(os.path.join(outdir, "manifest.json"), 'w') as fh: json.dump(manifest, fh, indent=2) # Zip tmp_zip_path = "{0}.zip".format(outdir) zipbase = os.path.basename(outdir) proc = subprocess.Popen(["/usr/bin/zip", "-r", zipbase, zipbase], cwd=tmpdir) # zip adds ".zip" proc.communicate() # Clean up dest = os.path.join(settings.MEDIA_ROOT, "mailings", os.path.basename(outname) + ".zip") try: os.makedirs(os.path.dirname(dest)) except OSError: pass shutil.move(tmp_zip_path, dest) proc = subprocess.Popen(["rm", "-r", tmpdir]) return os.path.relpath(dest, settings.MEDIA_ROOT)