def mass_mailing_spreadsheet(request, who=None): """ Return a spreadsheet with one line per address for all users of a given type. """ if not who: orgs = Organization.objects.mail_filter(request.user) return render(request, "correspondence/mass_mailing_spreadsheet.html", {"orgs": orgs}) if who == "bloggers": qs = Profile.objects.bloggers() elif who == "bloggers_with_published_content": qs = Profile.objects.bloggers_with_published_content() elif who == "enrolled": qs = Profile.objects.enrolled() elif who == "invitable": qs = Profile.objects.invitable() elif who == "invited": qs = Profile.objects.invited() elif who == "waitlistable": qs = Profile.objects.waitlistable() elif who == "waitlisted": qs = Profile.objects.waitlisted() elif who == "needs_signup_complete_letter": qs = Profile.objects.needs_signup_complete_letter() elif who == "needs_first_post_letter": qs = Profile.objects.needs_first_post_letter() elif who == "needs_comments_letter": qs = Profile.objects.needs_comments_letter() elif who == "lost_contact": qs = Profile.objects.filter(lost_contact=True) if who != "lost_contact": qs = qs.filter(lost_contact=False) qs = qs.mail_filter(request.user) with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as fh: fname = fh.name utils.write_address_csv([p.full_address() for p in qs], fname) response = HttpResponse(content_type="text/csv") with open(fname) as fh: response.write(fh.read()) os.remove(fname) response["Content-Disposition"] = "attachment; filename=%s-%s.csv" % ( who, datetime.datetime.now().strftime("%Y-%m-%d"), ) return response
def mass_mailing_spreadsheet(request, who=None): """ Return a spreadsheet with one line per address for all users of a given type. """ if not who: orgs = Organization.objects.mail_filter(request.user) return render(request, "correspondence/mass_mailing_spreadsheet.html", {'orgs': orgs}) if who == "bloggers": qs = Profile.objects.bloggers() elif who == "bloggers_with_published_content": qs = Profile.objects.bloggers_with_published_content() elif who == "enrolled": qs = Profile.objects.enrolled() elif who == "invitable": qs = Profile.objects.invitable() elif who == "invited": qs = Profile.objects.invited() elif who == "waitlistable": qs = Profile.objects.waitlistable() elif who == "waitlisted": qs = Profile.objects.waitlisted() elif who == "needs_signup_complete_letter": qs = Profile.objects.needs_signup_complete_letter() elif who == "needs_first_post_letter": qs = Profile.objects.needs_first_post_letter() elif who == "needs_comments_letter": qs = Profile.objects.needs_comments_letter() elif who == "lost_contact": qs = Profile.objects.filter(lost_contact=True) if who != "lost_contact": qs = qs.filter(lost_contact=False) qs = qs.mail_filter(request.user) with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as fh: fname = fh.name utils.write_address_csv([p.full_address() for p in qs], fname) response = HttpResponse(mimetype='text/csv') with open(fname) as fh: response.write(fh.read()) os.remove(fname) response['Content-Disposition'] = 'attachment; filename=%s-%s.csv' % ( who, datetime.datetime.now().strftime("%Y-%m-%d")) return response
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 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)