Dashboard cards: rebuild deployable dists
This commit is contained in:
@@ -5,7 +5,7 @@ never stored. Warranties link to assets many-to-many via warrantyassets, though
|
||||
the common case is one warranty per asset.
|
||||
"""
|
||||
|
||||
from datetime import date, datetime, timezone
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
|
||||
from flask import Blueprint, request
|
||||
from flask_jwt_extended import jwt_required
|
||||
@@ -391,3 +391,54 @@ def warranty_report():
|
||||
'counts': {k: len(v) for k, v in buckets.items()},
|
||||
'buckets': buckets,
|
||||
})
|
||||
|
||||
|
||||
@warranty_bp.route('/dashboard/expiring', methods=['GET'])
|
||||
@jwt_required()
|
||||
@require_permission('warranty.view')
|
||||
def dashboard_expiring():
|
||||
"""Warranties running out, and ones that already have.
|
||||
|
||||
Already-expired first, then soonest. Expired stays on the list rather than
|
||||
dropping off: a machine out of warranty is a purchasing decision someone
|
||||
still has to make, and silently removing it the day it lapses is how it gets
|
||||
missed entirely.
|
||||
|
||||
Horizon is a setting because 90 days suits a site that budgets quarterly and
|
||||
nobody else (ADR-015).
|
||||
"""
|
||||
from shopdb.api import Setting
|
||||
|
||||
days = 90
|
||||
setting = Setting.query.filter_by(key='warranty_expiringdays').first()
|
||||
if setting and (setting.value or '').strip():
|
||||
try:
|
||||
days = int(setting.value)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
|
||||
today = date.today()
|
||||
horizon = today + timedelta(days=days)
|
||||
|
||||
rows = []
|
||||
query = (db.session.query(Warranty, WarrantyAsset, Asset)
|
||||
.join(WarrantyAsset, WarrantyAsset.warrantyid == Warranty.warrantyid)
|
||||
.join(Asset, Asset.assetid == WarrantyAsset.assetid)
|
||||
.filter(Warranty.isactive.is_(True),
|
||||
Warranty.enddate.isnot(None),
|
||||
Warranty.enddate <= horizon,
|
||||
Asset.isactive.is_(True)))
|
||||
|
||||
for warranty, _link, asset in query.all():
|
||||
remaining = (warranty.enddate - today).days
|
||||
rows.append({
|
||||
'assetid': asset.assetid,
|
||||
'assetnumber': asset.assetnumber or asset.name or str(asset.assetid),
|
||||
'enddate': warranty.enddate.isoformat(),
|
||||
'provider': warranty.provider,
|
||||
'daysleft': remaining,
|
||||
'state': 'expired' if remaining < 0 else 'expiring',
|
||||
})
|
||||
|
||||
rows.sort(key=lambda r: r['daysleft'])
|
||||
return success_response(rows[:50])
|
||||
|
||||
@@ -114,6 +114,49 @@ class WarrantyPlugin(BasePlugin):
|
||||
},
|
||||
]
|
||||
|
||||
def get_dashboard_widgets(self) -> List[Dict]:
|
||||
"""Dashboard card: warranties running out, and ones already expired.
|
||||
|
||||
Expired stays listed rather than dropping off. A machine out of
|
||||
warranty is a purchasing decision someone still has to make, and
|
||||
removing it the day it lapses is how it gets missed entirely.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
'id': 'warranty-expiring',
|
||||
'title': 'Warranties expiring',
|
||||
'endpoint': '/api/warranty/dashboard/expiring',
|
||||
'render': 'exceptions',
|
||||
'severity': 'info',
|
||||
'permission': 'warranty.view',
|
||||
'empty': 'hide',
|
||||
'position': 50,
|
||||
'map': {
|
||||
'title': 'assetnumber',
|
||||
'detail': 'state',
|
||||
'meta': [
|
||||
{'key': 'enddate', 'label': 'ends', 'format': 'date'},
|
||||
{'key': 'provider'},
|
||||
],
|
||||
'link': '/assets/{assetid}',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
def get_settings_defaults(self) -> List[Dict]:
|
||||
"""Settings this plugin owns."""
|
||||
return [
|
||||
{
|
||||
'key': 'warranty_expiringdays',
|
||||
'value': '90',
|
||||
'valuetype': 'integer',
|
||||
'category': 'warranty',
|
||||
'description': 'Days ahead to list an expiring warranty on the '
|
||||
'dashboard. Already-expired warranties are always '
|
||||
'listed.',
|
||||
},
|
||||
]
|
||||
|
||||
def get_permissions(self) -> List:
|
||||
"""Return the RBAC permissions this plugin owns."""
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user