feat: an unpaid cart's files are kept 2 days, a paid order's 30

Files are uploaded before payment so the price and the security check use
the file itself, but an abandoned cart kept them for 30 days. Now a finished
upload is held 2 days, a quote waiting for review 7, an approved quote 2 more
to be paid, and the paid order keeps its originals for 30 days from upload.
A payment never starts for files that are gone; one under way holds them a
day. Files attached to an order take the order's window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cauê Faleiros
2026-09-30 12:09:02 -03:00
parent eb254da501
commit 933bd30cbd
7 changed files with 71 additions and 2 deletions

View File

@@ -49,6 +49,26 @@ def is_test(order):
return (order.get('payment') or {}).get('provider') == TEST_PROVIDER
# How long a file is kept while nothing has been paid for it. A cart's files
# are uploaded before payment, so the price and the security check are done on
# the file itself; a cart that is never paid must not keep them for 30 days.
UNPAID_HOLD = '2 days'
# A quote waiting for an operator's review keeps its files this long.
REVIEW_HOLD = '7 days'
# Once paid, the order keeps its originals for this long from the upload.
ORDER_RETENTION = '30 days'
def quote_uploads(quote_or_draft):
return [uid for item in quote_or_draft['items'] for uid in item['uploads']]
def hold_uploads(c, upload_ids, interval):
"""Keep these files at least `interval` from now; never shortens a hold."""
c.execute('''UPDATE dtf_local.uploads SET expires_at=GREATEST(expires_at, now()+%s::interval)
WHERE id=ANY(%s) AND purged_at IS NULL''', (interval, [str(u) for u in upload_ids]))
def create_order(c, quote, payment):
"""Create the order for a reviewed quote, or return the one already there.
@@ -68,6 +88,9 @@ def create_order(c, quote, payment):
order = c.execute(
'INSERT INTO dtf_local.orders(id,quote_id,owner,snapshot,payment) VALUES(%s,%s,%s,%s,%s) RETURNING *',
(uuid4(), quote['id'], quote['owner'], Jsonb(approved), Jsonb(payment))).fetchone()
# Paid: the files are kept for the order's retention, counted from upload.
c.execute('''UPDATE dtf_local.uploads SET expires_at=GREATEST(expires_at, created_at+%s::interval)
WHERE id=ANY(%s) AND purged_at IS NULL''', (ORDER_RETENTION, quote_uploads(approved)))
queue_print_files(c, order['id'], len(approved['items']))
if is_test(order):
return order, True