From 7e9650a62b1b8e8f9547b59eaf97eb25e9da14af Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 9 Jul 2026 16:05:26 -0400 Subject: [PATCH] Warranty phase 2: real Dell provider + settings UI + PC hero badge - DellProvider: real Dell TechDirect lookup. OAuth2 via HTTP Basic auth, asset-entitlements under /PROD/sbil/eapi/v5 (the device.warranty path 404s for this account), map latest dated entitlement to service level + dates. Cache the token process-wide; Dell rate-limits the token endpoint and a fresh request per refresh trips a 401 cooldown. Verified against live Dell. - Lenovo/HP stay config-shaped stubs. - Settings: warranty_dell_* keys (category integrations); Dell Warranty Lookup block in System Settings > Integrations (enable + client id/secret masked + optional token/API URL overrides). - WarrantyPanel takes optional pre-fetched items; PCDetail fetches once and feeds both the panel and a new hero warranty-status/end-date badge. - tools/mock_dell.py for offline testing of the provider flow. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/components/WarrantyPanel.vue | 6 + frontend/src/views/pcs/PCDetail.vue | 33 +++- .../src/views/settings/SystemSettings.vue | 99 +++++++++++ plugins/warranty/api/routes.py | 4 +- plugins/warranty/services/__init__.py | 3 +- plugins/warranty/services/providers.py | 162 +++++++++++++++--- shopdb/core/api/settings.py | 36 ++++ tools/mock_dell.py | 57 ++++++ 8 files changed, 370 insertions(+), 30 deletions(-) create mode 100644 tools/mock_dell.py diff --git a/frontend/src/components/WarrantyPanel.vue b/frontend/src/components/WarrantyPanel.vue index 9d83bdd..be152b7 100644 --- a/frontend/src/components/WarrantyPanel.vue +++ b/frontend/src/components/WarrantyPanel.vue @@ -33,6 +33,9 @@ const props = defineProps({ assetid: { type: [Number, String], default: null }, // When true, render the card even with no warranties (shows an "Add one" link). showEmpty: { type: Boolean, default: false }, + // Optional pre-fetched warranties. When provided, the panel uses them instead + // of fetching (lets a parent share one fetch with e.g. a hero badge). + items: { type: Array, default: null }, }) const warranties = ref([]) @@ -47,6 +50,8 @@ function formatDate(d) { } async function load() { + // Parent-supplied data wins - skip the fetch. + if (props.items !== null) { warranties.value = props.items; return } if (!props.assetid) { warranties.value = []; return } try { const response = await warrantyApi.forAsset(props.assetid) @@ -59,6 +64,7 @@ async function load() { onMounted(load) watch(() => props.assetid, load) +watch(() => props.items, load)