Attach proof of cover to a warranty

A provider lookup answers whether a unit is covered. It does not produce the
invoice or the extended-warranty certificate, and a manually entered warranty
had nowhere to keep one - so the proof stayed in somebody's mailbox until they
left.

Two columns rather than one: the served URL of the stored document, and the
name the vendor sent it under, because "Dell invoice 4471.pdf" is what a person
recognises a year later and "warranty-12.pdf" is not. The download route sends
the original name back.

Authenticated in both directions, unlike an asset photo: an invoice carries
pricing and a service tag. One document per warranty, replacing any prior
extension so a re-upload as .pdf does not leave the old .png behind claiming to
be current. Capped at 25MB - a certificate is a document, not a disk image.

Office formats are allowed because purchase records genuinely arrive as .msg
and .xlsx, not only as PDFs.
This commit is contained in:
cproudlock
2026-08-12 11:45:40 -04:00
parent c28b02e45b
commit 2fce81f33f
5 changed files with 369 additions and 4 deletions

View File

@@ -48,6 +48,14 @@ class Warranty(db.Model):
# When a provider lookup last refreshed this record.
lastcheckeddate = db.Column(db.DateTime)
notes = db.Column(db.Text)
# Proof of cover: the purchase invoice, the extended-warranty certificate,
# whatever the vendor sent. A provider lookup answers "is it covered"; this
# answers "prove it" months later, when the email it arrived in is gone.
# Stores the served URL, not the original filename - see the upload route.
proofurl = db.Column(db.String(500))
prooffilename = db.Column(db.String(255))
isactive = db.Column(db.Boolean, nullable=False, server_default='1')
links = db.relationship('WarrantyAsset', back_populates='warranty',
@@ -68,6 +76,8 @@ class Warranty(db.Model):
'enddate': self.enddate.isoformat() if self.enddate else None,
'lastcheckeddate': self.lastcheckeddate.isoformat() + 'Z' if self.lastcheckeddate else None,
'notes': self.notes,
'proofurl': self.proofurl,
'prooffilename': self.prooffilename,
'isactive': bool(self.isactive),
'status': status,
'statuscolor': STATUS_COLORS.get(status, STATUS_COLORS['unknown']),