diff --git a/apps/api/src/modules/pricing/routes/admin-pricing-routes.js b/apps/api/src/modules/pricing/routes/admin-pricing-routes.js index 13642b0..1732e8a 100644 --- a/apps/api/src/modules/pricing/routes/admin-pricing-routes.js +++ b/apps/api/src/modules/pricing/routes/admin-pricing-routes.js @@ -74,6 +74,7 @@ export async function registerAdminPricingRoutes(app, options) { id: job.id, status: job.status, error: job.error ?? null, + valueMinor: job.valuation?.valuation?.valueMinor ?? null, createdAt: job.createdAt, updatedAt: job.updatedAt, }, diff --git a/apps/web/src/pages/AdminHomePage.vue b/apps/web/src/pages/AdminHomePage.vue index 24599a3..c76c141 100644 --- a/apps/web/src/pages/AdminHomePage.vue +++ b/apps/web/src/pages/AdminHomePage.vue @@ -9,7 +9,7 @@ import { createAdminListing, listAdminListings, markListingPending, publishAdmin import { createAdminSale, listAdminSales, voidAdminSale } from '@/services/admin-sale-service.js'; import { createAdminAcquisition, listAdminAcquisitions } from '@/services/admin-acquisition-service.js'; import { getAdminDashboard } from '@/services/admin-dashboard-service.js'; -import { addAdminPricingObservation, calculateAdminValuation, overrideAdminValuation } from '@/services/admin-pricing-service.js'; +import { addAdminPricingObservation, calculateAdminValuation, enqueueAdminPricingRefresh, getAdminPricingJob, overrideAdminValuation } from '@/services/admin-pricing-service.js'; import { createAdminProviderMapping, listAdminProviderMappings } from '@/services/admin-provider-mapping-service.js'; const { principal } = useAuth(); @@ -48,6 +48,7 @@ const pricingSource = ref(''); const pricingPrice = ref(''); const overridePrice = ref(''); const overrideReason = ref(''); +const refreshStatus = ref(''); const voidReasons = ref({}); const mappingProductId = ref(''); const mappingProviderId = ref(''); @@ -183,6 +184,29 @@ async function calculatePricing() { finally { isSaving.value = false; } } +async function refreshPricing() { + isSaving.value = true; + refreshStatus.value = 'Queued'; + try { + const item = inventory.value.find(({ id }) => id === pricingInventoryId.value); + const job = await enqueueAdminPricingRefresh(item.id, { productId: item.productId, conditionId: item.conditionId }, csrfToken()); + for (let attempt = 0; attempt < 15; attempt += 1) { + const status = await getAdminPricingJob(job.id); + refreshStatus.value = status.status; + if (status.status === 'COMPLETED') { + valuations.value = { ...valuations.value, [item.id]: { valueMinor: status.valueMinor, confidence: 'PROVIDER', sourceCount: null, stale: false } }; + return; + } + if (status.status === 'FAILED') throw new Error(status.error ?? 'Pricing refresh failed.'); + await new Promise((resolve) => setTimeout(resolve, 500)); + } + throw new Error('Pricing refresh is taking longer than expected.'); + } catch (requestError) { + error.value = requestError; + refreshStatus.value = 'FAILED'; + } finally { isSaving.value = false; } +} + async function overridePricing() { isSaving.value = true; try { @@ -337,6 +361,7 @@ onMounted(load); + diff --git a/apps/web/src/services/admin-pricing-service.js b/apps/web/src/services/admin-pricing-service.js index ca4c5af..3b21148 100644 --- a/apps/web/src/services/admin-pricing-service.js +++ b/apps/web/src/services/admin-pricing-service.js @@ -33,3 +33,15 @@ export function overrideAdminValuation(inventoryItemId, input, csrfToken) { body: JSON.stringify(input), }); } + +export function enqueueAdminPricingRefresh(inventoryItemId, input, csrfToken) { + return request(`/admin/inventory/${encodeURIComponent(inventoryItemId)}/pricing/refresh`, { + method: 'POST', + headers: { 'x-csrf-token': csrfToken }, + body: JSON.stringify(input), + }); +} + +export function getAdminPricingJob(jobId) { + return request(`/admin/jobs/${encodeURIComponent(jobId)}`); +}