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.
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
"""Add warranties.proofurl / prooffilename (proof-of-cover document).
|
|
|
|
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 lived in somebody's mailbox until they
|
|
left. Two columns: the served URL of the stored file, and the name the vendor
|
|
sent it under, which is what a person recognises months later.
|
|
|
|
Idempotent; downgrade drops both.
|
|
|
|
Revision ID: warranty0002proof
|
|
Revises: warranty0001anchor
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision = 'warranty0002proof'
|
|
down_revision = 'warranty0001anchor'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
_TABLE = 'warranties'
|
|
_COLUMNS = (('proofurl', sa.String(500)), ('prooffilename', sa.String(255)))
|
|
|
|
|
|
def _column_names(insp, table):
|
|
return {c['name'] for c in insp.get_columns(table)}
|
|
|
|
|
|
def upgrade():
|
|
bind = op.get_bind()
|
|
insp = sa.inspect(bind)
|
|
if _TABLE not in insp.get_table_names():
|
|
return
|
|
existing = _column_names(insp, _TABLE)
|
|
for name, coltype in _COLUMNS:
|
|
if name not in existing:
|
|
op.add_column(_TABLE, sa.Column(name, coltype, nullable=True))
|
|
|
|
|
|
def downgrade():
|
|
bind = op.get_bind()
|
|
insp = sa.inspect(bind)
|
|
if _TABLE not in insp.get_table_names():
|
|
return
|
|
existing = _column_names(insp, _TABLE)
|
|
for name, _ in _COLUMNS:
|
|
if name in existing:
|
|
op.drop_column(_TABLE, name)
|