Skip to content

fix/630 missing criteria#868

Merged
guilbep merged 3 commits intodevfrom
fix/630-missing-criteria
Apr 16, 2026
Merged

fix/630 missing criteria#868
guilbep merged 3 commits intodevfrom
fix/630-missing-criteria

Conversation

@BenBotros
Copy link
Copy Markdown
Contributor

  • feat: split data management page
  • feat: refactor ModuleConfig UI and fix controls
  • feat: use module completeness composable and UI tweaks

What does this change?

Splits the monolithic DataManagementPage.vue (~1500-line script) into focused, self-contained components:

  • ModuleConfig.vue — module-level expansion item with activation toggle, uncertainty selector, common uploads, and submodule list; uses provide/inject to share callbacks with children
  • SubmoduleConfig.vue — per-submodule expansion item with enable toggle, threshold input, data/factor/reference upload cards, and computed-factor sync for Research Facilities
  • ReductionObjectivesSection.vue — standalone reduction-objectives card with file uploads and 3-slot goal editor
  • backoffice-module-config.ts — extracted MODULE_SUBMODULES and MODULE_COMMON_UPLOADS constants into a dedicated file

Completeness helpers (isModuleEnabled, isSubmoduleEnabled, isModuleIncomplete, isSubmoduleIncomplete, anyModuleIncomplete) moved from the page into the yearConfig Pinia store so they're reusable across components.

The Open year for users button is now disabled with a tooltip when any enabled module has missing or failed mandatory uploads.

Two backend fixes are also included:

  • equipment_electric_consumption/schemas.py: removed fallback that read active_hours/standby_hours from factor values when the user didn't supply them — if these are missing the formula now correctly returns None.
  • module_per_year.py: simplified factors_maps_by_type construction (removed incorrect key-prefix filtering that broke factor lookup); cleaned up unused factor_id_to_factor from base_csv_provider.py.

Why is this needed?

DataManagementPage.vue had grown to ~2500 lines of mixed concerns, making it hard to review, test, and extend. Extracting components and moving store logic into Pinia reduces coupling, enables independent testing, and fixes issue #630 where certain criteria were missing from the emission computation pipeline.

Type of change

  • ✨ New feature
  • 🧹 Code cleanup

Related issues

@BenBotros BenBotros requested a review from guilbep April 15, 2026 12:31
@BenBotros BenBotros self-assigned this Apr 15, 2026
Copilot AI review requested due to automatic review settings April 15, 2026 12:31
@github-actions
Copy link
Copy Markdown
Contributor

⚡ Lighthouse CI Results

📊 View full report

Performance scores will be available in the artifacts.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.43%. Comparing base (b2fe11e) to head (758de82).

Additional details and impacted files
@@           Coverage Diff           @@
##              dev     #868   +/-   ##
=======================================
  Coverage   60.43%   60.43%           
=======================================
  Files         137      137           
  Lines       11997    11997           
=======================================
  Hits         7250     7250           
  Misses       4747     4747           
Flag Coverage Δ
backend 60.43% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the Back Office “Data management” area by extracting the previous monolithic page into dedicated components, centralizing “module completeness” logic in the yearConfig Pinia store, and using that completeness state to disable the “Open year for users” action when mandatory uploads are missing/failed.

Changes:

  • Extracts module/submodule configuration UI and reduction objectives into separate components and shared constants.
  • Moves completeness helpers into yearConfig store and wires them into the UI (incl. disabling “Open year for users” with tooltip).
  • Adds i18n strings for loading/disabled tooltip messaging.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
frontend/src/stores/yearConfig.ts Adds completeness helpers (isModuleIncomplete, anyModuleIncomplete, etc.) using latest_jobs + module config constants.
frontend/src/pages/back-office/DataManagementPage.vue Replaces in-page logic with new components and disables “Open year for users” based on store completeness.
frontend/src/i18n/backoffice_data_management.ts Adds translations for loading and disabled tooltip.
frontend/src/constant/backoffice-module-config.ts Introduces shared module/submodule upload configuration constants.
frontend/src/components/organisms/data-management/ModuleConfig.vue Implements module-level UI (enable toggle, uncertainty, common uploads, recalculation dialog) and provides callbacks to submodules.
frontend/src/components/organisms/data-management/SubmoduleConfig.vue Implements per-submodule UI (enable toggle, threshold, uploads, computed factor sync).
frontend/src/components/organisms/data-management/ReductionObjectivesSection.vue Extracts reduction objectives uploads + 3-slot goal editor into its own component.

Comment thread frontend/src/components/organisms/data-management/ModuleConfig.vue Outdated
Comment thread frontend/src/components/organisms/data-management/SubmoduleConfig.vue Outdated
Comment thread frontend/src/stores/yearConfig.ts Outdated
Copilot AI review requested due to automatic review settings April 15, 2026 12:45
@github-actions
Copy link
Copy Markdown
Contributor

⚡ Lighthouse CI Results

📊 View full report

Performance scores will be available in the artifacts.

2 similar comments
@github-actions
Copy link
Copy Markdown
Contributor

⚡ Lighthouse CI Results

📊 View full report

Performance scores will be available in the artifacts.

@github-actions
Copy link
Copy Markdown
Contributor

⚡ Lighthouse CI Results

📊 View full report

Performance scores will be available in the artifacts.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

@BenBotros BenBotros force-pushed the fix/630-missing-criteria branch from 9028b15 to 758de82 Compare April 15, 2026 13:08
@BenBotros BenBotros marked this pull request as ready for review April 15, 2026 13:09
Copilot AI review requested due to automatic review settings April 15, 2026 13:09
@github-actions
Copy link
Copy Markdown
Contributor

⚡ Lighthouse CI Results

📊 View full report

Performance scores will be available in the artifacts.

@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
@EPFL-ENAC EPFL-ENAC deleted a comment from Copilot AI Apr 15, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Comment on lines +271 to +279
function isModuleEnabled(module: string): boolean {
const subs =
MODULE_SUBMODULES[module as keyof typeof MODULE_SUBMODULES] ?? [];
const moduleTypeId = subs.length > 0 ? subs[0].moduleTypeId : 0;
if (!moduleTypeId) return true;
return (
config.value?.config?.modules?.[String(moduleTypeId)]?.enabled ?? true
);
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isModuleEnabled derives moduleTypeId only from MODULE_SUBMODULES. If a module ever has only MODULE_COMMON_UPLOADS (or if a module is missing from MODULE_SUBMODULES due to config drift), moduleTypeId becomes 0 and the module is treated as enabled, which can cause anyModuleIncomplete to miss required checks. Consider resolving moduleTypeId from either (a) the first submodule, (b) the first common upload, or (c) a dedicated MODULE_TYPE_IDS mapping that is the single source of truth.

Copilot uses AI. Check for mistakes.
Comment on lines 190 to +200
<q-btn
icon="calendar_month"
color="accent"
:label="$t('open_year_for_users')"
class="text-weight-medium text-capitalize q-mt-md"
/>
:disable="yearConfigStore.anyModuleIncomplete"
>
<q-tooltip v-if="yearConfigStore.anyModuleIncomplete">
{{ $t('data_management_open_year_disabled_tooltip') }}
</q-tooltip>
</q-btn>
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The button is only disabled when anyModuleIncomplete is true, but anyModuleIncomplete is false when no config is loaded (config.value is falsy). This can leave “Open year for users” enabled while the year config is missing / still loading. Consider also disabling (or hiding) the button when !yearConfigStore.config (and possibly when yearConfigStore.loading), e.g., :disable="!yearConfigStore.config || yearConfigStore.anyModuleIncomplete".

Copilot uses AI. Check for mistakes.
Comment on lines +663 to +668
<q-card
v-if="getImportRow(common).hasData"
flat
class="col q-pa-lg"
:style="cardStyle(dataButtonColor(getImportRow(common)))"
>
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getImportRow(common) (and the derived dataButtonColor/factorButtonColor) is invoked multiple times per render, and each call filters latestJobs. This can create avoidable work on each reactive update. Consider computing the row once per common item (e.g., via a small wrapper component, a computed map keyed by moduleTypeId/dataEntryTypeId, or assigning const row = getImportRow(common) in a setup()-level helper for the loop) and then use row throughout the template.

Copilot uses AI. Check for mistakes.
Comment on lines +172 to +187
function downloadLastCsv(row: ImportRow, targetType: TargetType) {
const job =
targetType === TargetType.DATA_ENTRIES
? row.lastDataJob
: row.lastFactorJob;
if (!job?.meta) return;
const filePath = (job.meta as Record<string, unknown>)
.processed_file_path as string;
if (!filePath) return;
const a = document.createElement('a');
a.href = `/api/v1/files/${filePath}`;
a.download = filePath.split('/').pop() || filePath;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a.href interpolates filePath directly into the URL. If filePath can contain characters needing escaping (spaces, #, ?) the download link can break; and if the backend expects path-safe encoding, it can also cause unexpected routing. Prefer building the URL with encoding (e.g., encodeURIComponent for each path segment or a URL object) before assigning to a.href.

Copilot uses AI. Check for mistakes.
Comment on lines +189 to +194
function safeFileName(meta: unknown): string | undefined {
const fp = (meta as Record<string, unknown>)?.file_path as string | undefined;
if (!fp) return undefined;
const parts = fp.split('/');
return parts.length ? parts[parts.length - 1] : fp;
}
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safeFileName only reads meta.file_path, but downloadLastCsv uses meta.processed_file_path. If the API only provides processed_file_path (or uses it for the relevant job type), the UI can display an empty filename next to the success checkmark. Consider falling back to processed_file_path when file_path is missing, and suppressing the checkmark display if no filename can be resolved.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +75
function findJob(
jobs: SyncJobSummary[],
moduleTypeId: number,
targetType: number | null,
dataEntryTypeId?: number,
ingestionMethod?: IngestionMethod,
): SyncJobSummary | undefined {
const candidates = jobs.filter(
(j) => j.module_type_id === moduleTypeId && j.target_type === targetType,
);
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findJob/toSyncJobResponse/getImportRow/cardStyle/downloadLastCsv/safeFileName are duplicated between SubmoduleConfig.vue and ModuleConfig.vue. This duplication increases the risk of behavior drifting (e.g., filename meta key handling, ingestion-method selection, styling rules). Consider extracting these helpers into a shared composable/utility (e.g., useBackofficeImportRows() + formatJobMetaFilename()), then reusing it in both components.

Copilot uses AI. Check for mistakes.
@guilbep guilbep merged commit fe4fb85 into dev Apr 16, 2026
12 of 15 checks passed
@guilbep guilbep deleted the fix/630-missing-criteria branch April 16, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT](BackOffice Redesign & Merge)

4 participants