function createOpportunitiesController({ STAGE_OPTIONS, STATUS_OPTIONS, authSessionState, consumptionPlansState, consumptionTrendState, getFiscalPeriodRange, opportunitiesDashboardState, opportunitiesFilterState, opportunitiesQueryState, opportunitiesTableState, preferencesState, productsContentState, renderProductsProgress, requestOpportunitiesPage, resetCrmServiceRequests, resetWorkloadActions, resetWorkloads, requestOpptyProductsInBackground, requestTokenRelayOnce, ensureCurrentUser, setOpportunitiesTableState }) { async function requestOpportunitiesForPeriod(period) { const dateRange = getFiscalPeriodRange(period, new Date()); opportunitiesQueryState.dateRange = dateRange; const requestVersion = ++opportunitiesQueryState.periodRequestVersion; resetWorkloadActions(); resetWorkloads(); await ensureCurrentUser(); if (!isCurrentPeriodRequest(requestVersion)) return; if (preferencesState.selectedOpportunityTypeValues.size === 0) { setOpportunitiesTableState({ items: [], status: "empty", message: "Select at least one Opportunity Type View in Preferences." }); return; } if (!dateRange) { setOpportunitiesTableState({ items: [], status: "empty", message: "No opportunities to display for this period." }); return; } try { const token = authSessionState.accessToken || await requestTokenRelayOnce(); if (requestVersion !== opportunitiesQueryState.periodRequestVersion) { return; } await requestOpportunities(token, period, dateRange, requestVersion); } catch (error) { // Authentication and request errors are recorded by their respective request handlers. } } async function requestOpportunities(token, period, dateRange, requestVersion) { if (isCurrentPeriodRequest(requestVersion)) { productsContentState.currentProductsRequestId = ""; productsContentState.opptyProductsByNumber = new Map(); productsContentState.expandedProductOptyNumbers = new Set(); productsContentState.productsProgress = { state: "idle", completed: 0, total: 0, failed: 0, cacheHits: 0 }; consumptionPlansState.accountPlansRequestState = new Map(); consumptionTrendState.consumptionTrendCache = new Map(); consumptionTrendState.consumptionTrendWindowOffsets = new Map(); consumptionTrendState.consumptionTrendSeriesFilters = new Map(); renderProductsProgress(); setOpportunitiesTableState({ items: [], status: "loading", message: "Loading opportunities..." }); } try { if (!isCurrentPeriodRequest(requestVersion)) return; const allItems = await requestOpportunitiesPage(token, period, dateRange, 0, [], requestVersion, 1); if (allItems && isCurrentPeriodRequest(requestVersion)) { setOpportunitiesTableState({ items: allItems, status: "ready", message: "" }); requestOpptyProductsInBackground(allItems, token); } } catch (error) { if (isCurrentPeriodRequest(requestVersion)) { setOpportunitiesTableState({ items: [], status: "error", message: "Unable to load opportunities." }); } throw error; } } function resetOpportunitiesTable() { resetWorkloadActions(); resetWorkloads(); resetCrmServiceRequests(); opportunitiesFilterState.selectedStages = new Set(STAGE_OPTIONS); opportunitiesFilterState.selectedStatuses = new Set(STATUS_OPTIONS); opportunitiesFilterState.selectedCustomerKeys = new Set(); opportunitiesFilterState.customerSearch = ""; opportunitiesFilterState.selectedOwnerKeys = new Set(); opportunitiesFilterState.ownerSearch = ""; opportunitiesFilterState.tableSearch = ""; opportunitiesFilterState.hasSavedCustomerFilter = false; opportunitiesFilterState.hasSavedOwnerFilter = false; opportunitiesFilterState.customerFilterInitialized = false; opportunitiesFilterState.ownerFilterInitialized = false; productsContentState.currentProductsRequestId = ""; productsContentState.opptyProductsByNumber = new Map(); productsContentState.expandedProductOptyNumbers = new Set(); productsContentState.productsProgress = { state: "idle", completed: 0, total: 0, failed: 0, cacheHits: 0 }; productsContentState.productsLastCachedAt = 0; consumptionPlansState.accountPlansRequestState = new Map(); consumptionTrendState.consumptionTrendCache = new Map(); consumptionTrendState.consumptionTrendWindowOffsets = new Map(); consumptionTrendState.consumptionTrendSeriesFilters = new Map(); opportunitiesDashboardState.stageDashboardAmounts = new Map([["TOTAL", 0], ...STAGE_OPTIONS.map((stage) => [stage, 0])]); opportunitiesTableState.opportunitiesTableState = { items: [], status: "idle", message: "", sortKey: "", sortDirection: "ascending" }; } function isCurrentPeriodRequest(requestVersion) { return requestVersion === opportunitiesQueryState.periodRequestVersion; } return { requestOpportunitiesForPeriod, requestOpportunities, resetOpportunitiesTable, isCurrentPeriodRequest }; }