Lock customer page after choice, archive files on revision, add file checkboxes for delivery

This commit is contained in:
Troll (Hermes Agent) 2026-08-01 21:10:57 +00:00
parent 51d1b4a4d9
commit 0f6b68cf5d
4 changed files with 144 additions and 48 deletions

83
app.py
View file

@ -234,11 +234,29 @@ def revise(token):
Customer asked for changes. Store the note and reset status to 'songs_uploaded'
so the operator sees it in the dashboard queue.
"""
req = get_request_by_token(token)
if not req:
abort(404)
note = request.form.get('revision_note', '').strip()
update_request(req['id'], revision_note=note, status='revisions_requested')
# Increment revision counter and archive current files before new versions are uploaded.
req = get_request_by_token(token)
if req:
new_count = (req.get('revision_count') or 0) + 1
upload_dir = Path(current_app.config['UPLOAD_FOLDER']) / str(req['id'])
if upload_dir.exists():
for field, version in (('song_a_path', 'A'), ('song_b_path', 'B')):
path = req.get(field)
if path and Path(path).exists():
old = Path(path)
archived = upload_dir / f"Rev{new_count}-{old.name}"
try:
old.rename(archived)
# Keep path pointing to the archived file; operator will upload new files.
req[field] = str(archived)
except OSError:
pass
update_request(req['id'], revision_note=note, status='revisions_requested',
song_a_path=req.get('song_a_path'), song_b_path=req.get('song_b_path'),
customer_approved='none', revision_count=new_count)
else:
abort(404)
# NOTE: No operator email is sent; the dashboard is the single queue.
flash('Your feedback has been saved. We will regenerate and update you.', 'success')
@ -323,6 +341,16 @@ def admin_request(rid):
def basename(path):
return Path(path).name if path else ''
# Collect any extra MP3 files in the request folder (archived revisions).
upload_dir = Path(current_app.config['UPLOAD_FOLDER']) / str(rid)
current_paths = {req['song_a_path'], req['song_b_path']}
extra_files = []
if upload_dir.exists():
for f in upload_dir.iterdir():
if f.is_file() and f.suffix.lower() == '.mp3' and str(f) not in current_paths:
extra_files.append(str(f))
extra_files.sort()
if request.method == 'POST':
action = request.form.get('action')
@ -366,34 +394,35 @@ def admin_request(rid):
elif action == 'mark_paid_deliver':
# Finalize: record Square payment ref, attach approved MP3s, email customer.
if req['customer_approved'] == 'none':
flash('Customer has not approved a version yet.', 'error')
else:
payment_ref = request.form.get('square_payment_ref', '').strip()
if not payment_ref:
flash('Square payment reference is required.', 'error')
return redirect(url_for('admin_request', rid=rid))
payment_ref = request.form.get('square_payment_ref', '').strip()
if not payment_ref:
flash('Square payment reference is required.', 'error')
return redirect(url_for('admin_request', rid=rid))
attachments = []
if req['customer_approved'] in ('a', 'both') and req['song_a_path']:
a_name = Path(req['song_a_path']).name
attachments.append((req['song_a_path'], a_name))
if req['customer_approved'] in ('b', 'both') and req['song_b_path']:
b_name = Path(req['song_b_path']).name
attachments.append((req['song_b_path'], b_name))
# Build list of selected files from checkboxes.
selected = request.form.getlist('deliver_file')
if not selected:
flash('Select at least one file to deliver.', 'error')
return redirect(url_for('admin_request', rid=rid))
player_link = f"{current_app.config['PUBLIC_BASE_URL']}/play/{req['player_token']}"
body = f"Hi {req['name']},\n\nThanks for your payment! Your approved song is attached to this email.\n\nIf you selected both versions, you'll find two MP3 files.\n\nYou can also keep streaming them here: {player_link}\n\nEnjoy!\n\n{current_app.config['BOOTH_NAME']}"
try:
send_email(req['email'], 'Your theme song files are here!', body, attachments=attachments)
update_request(rid, square_payment_ref=payment_ref, delivery_sent_at=now_utc(), status='delivered')
flash('Delivery email sent with MP3 attachments.', 'success')
except Exception as e:
flash(f'Failed to send delivery email: {e}', 'error')
attachments = []
for path in selected:
p = Path(path)
if p.exists():
attachments.append((str(p), p.name))
player_link = f"{current_app.config['PUBLIC_BASE_URL']}/play/{req['player_token']}"
body = f"Hi {req['name']},\n\nThanks for your payment! Your selected song(s) are attached to this email.\n\nYou can also keep streaming them here: {player_link}\n\nEnjoy!\n\n{current_app.config['BOOTH_NAME']}"
try:
send_email(req['email'], 'Your theme song files are here!', body, attachments=attachments)
update_request(rid, square_payment_ref=payment_ref, delivery_sent_at=now_utc(), status='delivered')
flash('Delivery email sent with MP3 attachments.', 'success')
except Exception as e:
flash(f'Failed to send delivery email: {e}', 'error')
return redirect(url_for('admin_request', rid=rid))
return render_template('admin/request.html', req=req, statuses=STATUS_LABELS, file_exists=file_exists, basename=basename)
return render_template('admin/request.html', req=req, statuses=STATUS_LABELS, file_exists=file_exists, basename=basename, extra_files=extra_files)
@app.route('/admin/request/<int:rid>/delete', methods=['POST'])