def handle(self, *args, **kwargs): try: out_dir = args[0] except IndexError: print "Requires arg: <output directory>" return data = [] qs = Profile.objects.enrolled().select_related('user') for profile in qs: docs = profile.user.documents_authored.filter(status='published') try: latest = docs.order_by('-date_written')[0] except IndexError: continue data.append((latest.date_written.strftime("%y-%m-%d"), profile)) data.sort() data.reverse() rows = [] for i, (date, profile) in enumerate(data[:250]): rows.append([str(i), str(profile.pk), profile.display_name]) env = build_envelope( profile.user.organization_set.all()[0].mailing_address, profile.full_address()) fn = os.path.join(out_dir, "%03d-%s.jpg" % (i, profile.get_blog_slug())) with open(fn, 'w') as fh: fh.write(env.getvalue()) write_csv(rows, os.path.join(out_dir, "manifest.csv"))
def get_mailing_file(request, mailing_id): mailing = utils.mail_filter_or_404(request.user, Mailing, pk=mailing_id) if mailing.has_file(): response = HttpResponse(mimetype='application/zip') filename = mailing.get_file() # Compile special instructions special_instructions = [] for letter in mailing.letters.all(): if letter.recipient and letter.recipient.profile.special_mail_handling: special_instructions.append(letter.recipient.profile) if special_instructions: # Add/replace special instructions manifest. tmpdir = tempfile.mkdtemp() subdir = os.path.join( tmpdir, os.path.splitext(os.path.basename(filename))[0]) os.makedirs(subdir) instructions_path = os.path.join( tmpdir, os.path.splitext(os.path.basename(filename))[0], "special_instructions.csv") rows = [["Name", "Address", "Special instructions"]] for profile in special_instructions: rows.append([ profile.display_name, profile.mailing_address, profile.special_mail_handling, ]) utils.write_csv(rows, instructions_path) proc = subprocess.Popen([ "zip", os.path.splitext(filename)[0], os.path.relpath(instructions_path, tmpdir), ], cwd=tmpdir) proc.communicate() shutil.rmtree(tmpdir) else: # No special instructions: remove them. proc = subprocess.Popen([ "zip", "-d", filename, os.path.splitext(os.path.basename(filename))[0] + "/special_instructions.csv" ]) proc.communicate() if settings.X_SENDFILE_ENABLED: response['X-Sendfile'] = filename else: with open(mailing.get_file()) as fh: response.write(fh.read()) response['Content-Disposition'] = 'attachment; filename={0}'.format( os.path.basename(mailing.get_file())) return response task_id = tasks.generate_collation_task.delay(mailing.pk, request.path) return redirect("moderation.wait_for_processing", task_id)
def get_mailing_file(request, mailing_id): mailing = utils.mail_filter_or_404(request.user, Mailing, pk=mailing_id) if mailing.has_file(): response = HttpResponse(mimetype='application/zip') filename = mailing.get_file() # Compile special instructions special_instructions = [] for letter in mailing.letters.all(): if letter.recipient and letter.recipient.profile.special_mail_handling: special_instructions.append(letter.recipient.profile) if special_instructions: # Add/replace special instructions manifest. tmpdir = tempfile.mkdtemp() subdir = os.path.join(tmpdir, os.path.splitext(os.path.basename(filename))[0]) os.makedirs(subdir) instructions_path = os.path.join(tmpdir, os.path.splitext(os.path.basename(filename))[0], "special_instructions.csv") rows = [["Name", "Address", "Special instructions"]] for profile in special_instructions: rows.append([ profile.display_name, profile.mailing_address, profile.special_mail_handling, ]) utils.write_csv(rows, instructions_path) proc = subprocess.Popen(["zip", os.path.splitext(filename)[0], os.path.relpath(instructions_path, tmpdir), ], cwd=tmpdir) proc.communicate() shutil.rmtree(tmpdir) else: # No special instructions: remove them. proc = subprocess.Popen(["zip", "-d", filename, os.path.splitext(os.path.basename(filename))[0] + "/special_instructions.csv" ]) proc.communicate() if settings.X_SENDFILE_ENABLED: response['X-Sendfile'] = filename else: with open(mailing.get_file()) as fh: response.write(fh.read()) response['Content-Disposition'] = 'attachment; filename={0}'.format( os.path.basename(mailing.get_file()) ) return response task_id = tasks.generate_collation_task.delay(mailing.pk, request.path) return redirect("moderation.wait_for_processing", task_id)
def handle(self, *args, **kwargs): try: out_dir = args[0] except IndexError: print "Requires arg: <output directory>" return data = [] qs = Profile.objects.enrolled().select_related('user') for profile in qs: docs = profile.user.documents_authored.filter(status='published') try: latest = docs.order_by('-date_written')[0] except IndexError: continue data.append(( latest.date_written.strftime("%y-%m-%d"), profile )) data.sort() data.reverse() rows = [] for i,(date,profile) in enumerate(data[:250]): rows.append([ str(i), str(profile.pk), profile.display_name ]) env = build_envelope( profile.user.organization_set.all()[0].mailing_address, profile.full_address() ) fn = os.path.join(out_dir, "%03d-%s.jpg" % (i, profile.get_blog_slug())) with open(fn, 'w') as fh: fh.write(env.getvalue()) write_csv(rows, os.path.join(out_dir, "manifest.csv"))
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)