feat(reject-history): ship report page and archive openspec change
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
## Purpose
|
||||
Define stable requirements for field-name-consistency.
|
||||
|
||||
## Requirements
|
||||
|
||||
|
||||
### Requirement: UI and Export Fields SHALL Have a Consistent Contract
|
||||
The system SHALL define and apply a consistent contract among UI column labels, API keys, and export headers for report/query pages.
|
||||
|
||||
@@ -14,3 +11,25 @@ The system SHALL define and apply a consistent contract among UI column labels,
|
||||
#### Scenario: Resource history field alignment
|
||||
- **WHEN** resource history detail table shows KPI columns
|
||||
- **THEN** columns required by export semantics (including Availability%) SHALL be present or explicitly mapped
|
||||
|
||||
### Requirement: Reject and defect metric names SHALL remain semantically consistent across UI/API/export
|
||||
The system SHALL use explicit, stable names for charge-off reject and non-charge-off defect metrics across all output surfaces.
|
||||
|
||||
#### Scenario: UI and API key alignment
|
||||
- **WHEN** summary/trend/list payloads are rendered on reject-history page
|
||||
- **THEN** UI labels for reject metrics SHALL map to `REJECT_TOTAL_QTY` and related reject-rate fields
|
||||
- **THEN** UI labels for defect metrics SHALL map to `DEFECT_QTY` and defect-rate fields
|
||||
|
||||
#### Scenario: Export header alignment
|
||||
- **WHEN** reject-history CSV export is generated
|
||||
- **THEN** CSV headers SHALL include both `REJECT_TOTAL_QTY` and `DEFECT_QTY`
|
||||
- **THEN** header names SHALL preserve the same semantic meaning as API fields
|
||||
|
||||
### Requirement: Reject component columns SHALL be explicitly distinguished from defect columns
|
||||
The system SHALL prevent ambiguous naming that collapses reject components and defect into a single term.
|
||||
|
||||
#### Scenario: Component and aggregate coexistence
|
||||
- **WHEN** detailed records are presented
|
||||
- **THEN** reject component fields (`REJECTQTY`, `STANDBYQTY`, `QTYTOPROCESS`, `INPROCESSQTY`, `PROCESSEDQTY`) SHALL be distinguishable from `DEFECT_QTY`
|
||||
- **THEN** aggregate `REJECT_TOTAL_QTY` SHALL be clearly identified as component sum, not defect
|
||||
|
||||
|
||||
117
openspec/specs/reject-history-api/spec.md
Normal file
117
openspec/specs/reject-history-api/spec.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# reject-history-api Specification
|
||||
|
||||
## Purpose
|
||||
TBD - created by archiving change reject-history-query-page. Update Purpose after archive.
|
||||
## Requirements
|
||||
### Requirement: Reject History API SHALL validate required query parameters
|
||||
The API SHALL validate date parameters and basic paging bounds before executing database work.
|
||||
|
||||
#### Scenario: Missing required dates
|
||||
- **WHEN** a reject-history endpoint requiring date range is called without `start_date` or `end_date`
|
||||
- **THEN** the API SHALL return HTTP 400 with a descriptive validation error
|
||||
|
||||
#### Scenario: Invalid date order
|
||||
- **WHEN** `end_date` is earlier than `start_date`
|
||||
- **THEN** the API SHALL return HTTP 400 and SHALL NOT run SQL queries
|
||||
|
||||
### Requirement: Reject History API SHALL provide summary metrics endpoint
|
||||
The API SHALL provide aggregated summary metrics for the selected filter context.
|
||||
|
||||
#### Scenario: Summary response payload
|
||||
- **WHEN** `GET /api/reject-history/summary` is called with valid filters
|
||||
- **THEN** response SHALL be `{ success: true, data: { ... } }`
|
||||
- **THEN** data SHALL include `MOVEIN_QTY`, `REJECT_TOTAL_QTY`, `DEFECT_QTY`, `REJECT_RATE_PCT`, `DEFECT_RATE_PCT`, `REJECT_SHARE_PCT`, `AFFECTED_LOT_COUNT`, and `AFFECTED_WORKORDER_COUNT`
|
||||
|
||||
### Requirement: Reject History API SHALL support yield-exclusion policy toggle
|
||||
The API SHALL support excluding or including policy-marked scrap reasons through a shared query parameter.
|
||||
|
||||
#### Scenario: Default policy mode
|
||||
- **WHEN** reject-history endpoints are called without `include_excluded_scrap`
|
||||
- **THEN** `include_excluded_scrap` SHALL default to `false`
|
||||
- **THEN** rows mapped to `ERP_PJ_WIP_SCRAP_REASONS_EXCLUDE.ENABLE_FLAG='Y'` SHALL be excluded from yield-related calculations
|
||||
|
||||
#### Scenario: Explicitly include policy-marked scrap
|
||||
- **WHEN** `include_excluded_scrap=true` is provided
|
||||
- **THEN** policy-marked rows SHALL be included in summary/trend/pareto/list/export calculations
|
||||
- **THEN** API response `meta` SHALL include the effective `include_excluded_scrap` value
|
||||
|
||||
#### Scenario: Invalid toggle value
|
||||
- **WHEN** `include_excluded_scrap` is not parseable as boolean
|
||||
- **THEN** the API SHALL return HTTP 400 with a descriptive validation error
|
||||
|
||||
### Requirement: Reject History API SHALL provide trend endpoint
|
||||
The API SHALL return time-series trend data for quantity and rate metrics.
|
||||
|
||||
#### Scenario: Trend response structure
|
||||
- **WHEN** `GET /api/reject-history/trend` is called
|
||||
- **THEN** response SHALL be `{ success: true, data: { items: [...] } }`
|
||||
- **THEN** each trend item SHALL contain bucket date, `REJECT_TOTAL_QTY`, `DEFECT_QTY`, `REJECT_RATE_PCT`, and `DEFECT_RATE_PCT`
|
||||
|
||||
#### Scenario: Trend granularity
|
||||
- **WHEN** `granularity` is provided as `day`, `week`, or `month`
|
||||
- **THEN** the API SHALL aggregate by the requested granularity
|
||||
- **THEN** invalid granularity SHALL return HTTP 400
|
||||
|
||||
### Requirement: Reject History API SHALL provide reason Pareto endpoint
|
||||
The API SHALL return sorted reason distribution data with cumulative percentages.
|
||||
|
||||
#### Scenario: Pareto response payload
|
||||
- **WHEN** `GET /api/reject-history/reason-pareto` is called
|
||||
- **THEN** each item SHALL include `reason`, `category`, selected metric value, `pct`, and `cumPct`
|
||||
- **THEN** items SHALL be sorted descending by selected metric
|
||||
|
||||
#### Scenario: Metric mode validation
|
||||
- **WHEN** `metric_mode` is provided
|
||||
- **THEN** accepted values SHALL be `reject_total` or `defect`
|
||||
- **THEN** invalid `metric_mode` SHALL return HTTP 400
|
||||
|
||||
### Requirement: Reject History API SHALL provide paginated detail endpoint
|
||||
The API SHALL return paginated detailed rows for the selected filter context.
|
||||
|
||||
#### Scenario: List response payload
|
||||
- **WHEN** `GET /api/reject-history/list?page=1&per_page=50` is called
|
||||
- **THEN** response SHALL include `{ items: [...], pagination: { page, perPage, total, totalPages } }`
|
||||
- **THEN** each row SHALL include date, process dimensions, reason fields, `MOVEIN_QTY`, `REJECT_TOTAL_QTY`, `DEFECT_QTY`, and reject component columns
|
||||
|
||||
#### Scenario: Paging bounds
|
||||
- **WHEN** `page < 1`
|
||||
- **THEN** page SHALL be treated as 1
|
||||
- **WHEN** `per_page > 200`
|
||||
- **THEN** `per_page` SHALL be capped at 200
|
||||
|
||||
### Requirement: Reject History API SHALL provide CSV export endpoint
|
||||
The API SHALL provide CSV export using the same filter and metric semantics as list/query APIs.
|
||||
|
||||
#### Scenario: Export payload consistency
|
||||
- **WHEN** `GET /api/reject-history/export` is called with valid filters
|
||||
- **THEN** CSV headers SHALL include both `REJECT_TOTAL_QTY` and `DEFECT_QTY`
|
||||
- **THEN** export rows SHALL follow the same semantic definitions as summary/list endpoints
|
||||
|
||||
### Requirement: Reject History API SHALL centralize SQL in reject_history SQL directory
|
||||
The service SHALL load SQL from dedicated files under `src/mes_dashboard/sql/reject_history/`.
|
||||
|
||||
#### Scenario: SQL file loading
|
||||
- **WHEN** reject-history service executes queries
|
||||
- **THEN** SQL SHALL be loaded from files in `sql/reject_history`
|
||||
- **THEN** user-supplied filters SHALL be passed through bind parameters
|
||||
- **THEN** user input SHALL NOT be interpolated into SQL strings directly
|
||||
|
||||
### Requirement: Reject History API SHALL use cached exclusion-policy source
|
||||
The API SHALL read exclusion-policy reasons from cached `ERP_PJ_WIP_SCRAP_REASONS_EXCLUDE` data instead of querying Oracle on every request.
|
||||
|
||||
#### Scenario: Enabled exclusions only
|
||||
- **WHEN** exclusion-policy data is loaded
|
||||
- **THEN** only rows with `ENABLE_FLAG='Y'` SHALL be treated as active exclusions
|
||||
|
||||
#### Scenario: Daily full-table cache refresh
|
||||
- **WHEN** exclusion cache is initialized
|
||||
- **THEN** the full table SHALL be loaded and refreshed at least once per 24 hours
|
||||
- **THEN** Redis SHOULD be used as shared cache when available, with in-memory fallback when unavailable
|
||||
|
||||
### Requirement: Reject History API SHALL apply rate limiting on expensive endpoints
|
||||
The API SHALL rate-limit high-cost endpoints to protect Oracle and application resources.
|
||||
|
||||
#### Scenario: List and export rate limiting
|
||||
- **WHEN** `/api/reject-history/list` or `/api/reject-history/export` receives excessive requests
|
||||
- **THEN** configured rate limiting SHALL reject requests beyond the threshold within the time window
|
||||
|
||||
142
openspec/specs/reject-history-page/spec.md
Normal file
142
openspec/specs/reject-history-page/spec.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# reject-history-page Specification
|
||||
|
||||
## Purpose
|
||||
TBD - created by archiving change reject-history-query-page. Update Purpose after archive.
|
||||
## Requirements
|
||||
### Requirement: Reject History page SHALL provide filterable historical query controls
|
||||
The page SHALL provide a filter area for date range and major production dimensions to drive all report sections.
|
||||
|
||||
#### Scenario: Default filter values
|
||||
- **WHEN** the page is first loaded
|
||||
- **THEN** `start_date` and `end_date` SHALL default to a valid recent range
|
||||
- **THEN** all other dimension filters SHALL default to empty (no restriction)
|
||||
|
||||
#### Scenario: Apply and clear filters
|
||||
- **WHEN** user clicks "查詢"
|
||||
- **THEN** summary, trend, pareto, and list sections SHALL reload with the same filter set
|
||||
- **WHEN** user clicks "清除條件"
|
||||
- **THEN** all filters SHALL reset to defaults and all sections SHALL reload
|
||||
|
||||
#### Scenario: Required core filters are present
|
||||
- **WHEN** the filter panel is rendered
|
||||
- **THEN** it SHALL include `start_date/end_date` time filter controls
|
||||
- **THEN** it SHALL include reason filter control
|
||||
- **THEN** it SHALL include `WORKCENTER_GROUP` filter control
|
||||
|
||||
### Requirement: Reject History page SHALL expose yield-exclusion toggle control
|
||||
The page SHALL let users decide whether to include policy-marked scrap in yield calculations.
|
||||
|
||||
#### Scenario: Default toggle state
|
||||
- **WHEN** the page is first loaded
|
||||
- **THEN** "納入不計良率報廢" toggle SHALL default to OFF
|
||||
- **THEN** requests SHALL be sent with `include_excluded_scrap=false`
|
||||
|
||||
#### Scenario: Toggle affects all sections
|
||||
- **WHEN** user turns ON/OFF the toggle and clicks "查詢"
|
||||
- **THEN** summary, trend, pareto, and list sections SHALL reload under the selected policy mode
|
||||
- **THEN** export action SHALL use the same toggle state
|
||||
|
||||
#### Scenario: Policy status visibility
|
||||
- **WHEN** data is rendered
|
||||
- **THEN** the UI SHALL show a clear badge/text indicating whether policy-marked scrap is currently excluded or included
|
||||
|
||||
### Requirement: Reject History page SHALL present KPI cards with split reject/defect semantics
|
||||
The page SHALL display KPI cards that simultaneously show charge-off reject and non-charge-off defect metrics.
|
||||
|
||||
#### Scenario: KPI cards render core metrics
|
||||
- **WHEN** summary data is loaded
|
||||
- **THEN** cards SHALL include `MOVEIN_QTY`, `REJECT_TOTAL_QTY`, `DEFECT_QTY`, `REJECT_RATE_PCT`, `DEFECT_RATE_PCT`, `REJECT_SHARE_PCT`, `AFFECTED_LOT_COUNT`, and `AFFECTED_WORKORDER_COUNT`
|
||||
- **THEN** numbers SHALL use zh-TW formatting
|
||||
|
||||
#### Scenario: Visual distinction for semantic lanes
|
||||
- **WHEN** KPI cards are rendered
|
||||
- **THEN** reject-related cards SHALL use a warm-color visual lane
|
||||
- **THEN** defect-related cards SHALL use a cool-color visual lane
|
||||
- **THEN** page legend/badge text SHALL explicitly indicate charge-off vs non-charge-off meaning
|
||||
|
||||
### Requirement: Reject History page SHALL display quantity and rate trends in separate charts
|
||||
The page SHALL show both quantity trend and rate trend to avoid mixing unit scales.
|
||||
|
||||
#### Scenario: Quantity trend chart
|
||||
- **WHEN** trend data is loaded
|
||||
- **THEN** the quantity trend chart SHALL show `REJECT_TOTAL_QTY` and `DEFECT_QTY` over time
|
||||
- **THEN** the chart SHALL use a shared X-axis by date bucket
|
||||
|
||||
#### Scenario: Rate trend chart
|
||||
- **WHEN** trend data is loaded
|
||||
- **THEN** the rate trend chart SHALL show `REJECT_RATE_PCT` and `DEFECT_RATE_PCT` over time
|
||||
- **THEN** rate values SHALL be displayed as percentages
|
||||
|
||||
### Requirement: Reject History page SHALL provide reason Pareto analysis
|
||||
The page SHALL provide a Pareto view for loss reasons and support downstream filtering.
|
||||
|
||||
#### Scenario: Pareto rendering and ordering
|
||||
- **WHEN** reason Pareto data is loaded
|
||||
- **THEN** items SHALL be sorted by selected metric descending
|
||||
- **THEN** a cumulative percentage line SHALL be shown
|
||||
|
||||
#### Scenario: Default 80% cumulative display mode
|
||||
- **WHEN** the page first loads Pareto
|
||||
- **THEN** it SHALL default to "only cumulative top 80%" mode
|
||||
- **THEN** Pareto SHALL only render categories within the cumulative 80% threshold under current filters
|
||||
|
||||
#### Scenario: Full Pareto toggle mode
|
||||
- **WHEN** user turns OFF the 80% cumulative display mode
|
||||
- **THEN** Pareto SHALL render all categories after applying current filters
|
||||
- **THEN** switching mode SHALL NOT reset existing time/reason/workcenter-group filters
|
||||
|
||||
#### Scenario: Pareto click filtering
|
||||
- **WHEN** user clicks a Pareto bar or row
|
||||
- **THEN** the selected reason SHALL become an active filter chip
|
||||
- **THEN** detail list SHALL reload with that reason
|
||||
- **THEN** clicking the same reason again SHALL clear the reason filter
|
||||
|
||||
### Requirement: Reject History page SHALL show paginated detail rows
|
||||
The page SHALL provide a paginated detail table for investigation and traceability.
|
||||
|
||||
#### Scenario: Detail columns
|
||||
- **WHEN** list data is loaded
|
||||
- **THEN** each row SHALL include date, workcenter group, workcenter, product dimensions, reason/category, `MOVEIN_QTY`, `REJECT_TOTAL_QTY`, `DEFECT_QTY`, and component reject columns
|
||||
|
||||
#### Scenario: Pagination behavior
|
||||
- **WHEN** total records exceed per-page size
|
||||
- **THEN** Prev/Next and page summary SHALL be shown
|
||||
- **THEN** changing any filter SHALL reset page to 1
|
||||
|
||||
### Requirement: Reject History page SHALL support CSV export from current filter context
|
||||
The page SHALL allow users to export records using the exact active filters.
|
||||
|
||||
#### Scenario: Export with current filters
|
||||
- **WHEN** user clicks "匯出 CSV"
|
||||
- **THEN** export request SHALL include the current filter state and active reason filter
|
||||
- **THEN** downloaded file SHALL contain both `REJECT_TOTAL_QTY` and `DEFECT_QTY`
|
||||
|
||||
### Requirement: Reject History page SHALL provide robust feedback states
|
||||
The page SHALL provide loading, empty, and error states without breaking interactions.
|
||||
|
||||
#### Scenario: Initial loading
|
||||
- **WHEN** first query is running
|
||||
- **THEN** a loading overlay or skeleton SHALL be visible until required data sections are ready
|
||||
|
||||
#### Scenario: API failure
|
||||
- **WHEN** any section API fails
|
||||
- **THEN** a visible error banner SHALL be shown
|
||||
- **THEN** already loaded sections SHALL remain interactive
|
||||
|
||||
#### Scenario: Empty dataset
|
||||
- **WHEN** query returns no rows
|
||||
- **THEN** chart and table areas SHALL show explicit empty-state messages
|
||||
|
||||
### Requirement: Reject History page SHALL maintain responsive visual hierarchy
|
||||
The page SHALL keep the same semantic grouping across desktop and mobile layouts.
|
||||
|
||||
#### Scenario: Desktop layout
|
||||
- **WHEN** viewport is desktop width
|
||||
- **THEN** KPI cards SHALL render in multi-column layout
|
||||
- **THEN** trend and pareto sections SHALL render as two-column analytical panels
|
||||
|
||||
#### Scenario: Mobile layout
|
||||
- **WHEN** viewport width is below responsive breakpoint
|
||||
- **THEN** cards and chart panels SHALL stack in a single column
|
||||
- **THEN** filter controls SHALL remain operable without horizontal overflow
|
||||
|
||||
77
openspec/specs/reject-metric-semantics/spec.md
Normal file
77
openspec/specs/reject-metric-semantics/spec.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# reject-metric-semantics Specification
|
||||
|
||||
## Purpose
|
||||
TBD - created by archiving change reject-history-query-page. Update Purpose after archive.
|
||||
## Requirements
|
||||
### Requirement: Charge-off reject metric SHALL be computed from five reject component columns
|
||||
The system SHALL compute `REJECT_TOTAL_QTY` as the sum of five reject-related quantity columns.
|
||||
|
||||
#### Scenario: Reject total formula
|
||||
- **WHEN** a source record is transformed
|
||||
- **THEN** `REJECT_TOTAL_QTY` SHALL equal `REJECTQTY + STANDBYQTY + QTYTOPROCESS + INPROCESSQTY + PROCESSEDQTY`
|
||||
- **THEN** null component values SHALL be treated as zero
|
||||
|
||||
### Requirement: Defect metric SHALL remain independent from reject total
|
||||
The system SHALL compute `DEFECT_QTY` only from `DEFECTQTY` and SHALL NOT merge it into `REJECT_TOTAL_QTY`.
|
||||
|
||||
#### Scenario: Defect independence
|
||||
- **WHEN** a record has `DEFECTQTY > 0` and reject component sum equals 0
|
||||
- **THEN** `DEFECT_QTY` SHALL be non-zero
|
||||
- **THEN** `REJECT_TOTAL_QTY` SHALL remain 0
|
||||
|
||||
### Requirement: Yield-exclusion policy SHALL follow ERP exclusion table
|
||||
The system SHALL use `ERP_PJ_WIP_SCRAP_REASONS_EXCLUDE` as the policy source for "not included in yield" scrap reasons.
|
||||
|
||||
#### Scenario: Enabled policy rows
|
||||
- **WHEN** exclusion policy is evaluated
|
||||
- **THEN** only rows with `ENABLE_FLAG='Y'` SHALL be considered exclusion rules
|
||||
|
||||
#### Scenario: Default exclusion behavior
|
||||
- **WHEN** `include_excluded_scrap=false` (default)
|
||||
- **THEN** source rows matching enabled exclusion reasons SHALL be excluded before computing yield-related metrics
|
||||
|
||||
#### Scenario: Optional inclusion override
|
||||
- **WHEN** `include_excluded_scrap=true`
|
||||
- **THEN** the same matched rows SHALL be included back into metric calculations
|
||||
|
||||
### Requirement: Move-in denominator SHALL be deduplicated at event level
|
||||
The system SHALL deduplicate `MOVEIN_QTY` by event key before rate calculations.
|
||||
|
||||
#### Scenario: Primary dedupe key
|
||||
- **WHEN** `HISTORYMAINLINEID` is present
|
||||
- **THEN** only one row per `HISTORYMAINLINEID` SHALL contribute `MOVEIN_QTY`
|
||||
|
||||
#### Scenario: Fallback dedupe key
|
||||
- **WHEN** `HISTORYMAINLINEID` is missing
|
||||
- **THEN** fallback dedupe key SHALL use a deterministic composite key from transaction context
|
||||
|
||||
### Requirement: Reject and defect rates SHALL use the same deduplicated denominator
|
||||
The system SHALL calculate percentage rates from deduplicated `MOVEIN_QTY` to ensure comparability.
|
||||
|
||||
#### Scenario: Reject rate formula
|
||||
- **WHEN** `MOVEIN_QTY > 0`
|
||||
- **THEN** `REJECT_RATE_PCT` SHALL equal `REJECT_TOTAL_QTY / MOVEIN_QTY * 100`
|
||||
|
||||
#### Scenario: Defect rate formula
|
||||
- **WHEN** `MOVEIN_QTY > 0`
|
||||
- **THEN** `DEFECT_RATE_PCT` SHALL equal `DEFECT_QTY / MOVEIN_QTY * 100`
|
||||
|
||||
#### Scenario: Zero denominator handling
|
||||
- **WHEN** `MOVEIN_QTY = 0`
|
||||
- **THEN** both rate fields SHALL return 0 and SHALL NOT raise divide-by-zero errors
|
||||
|
||||
### Requirement: Reject share SHALL describe reject proportion within total loss
|
||||
The system SHALL calculate reject share against combined reject and defect loss quantities.
|
||||
|
||||
#### Scenario: Reject share formula
|
||||
- **WHEN** `REJECT_TOTAL_QTY + DEFECT_QTY > 0`
|
||||
- **THEN** `REJECT_SHARE_PCT` SHALL equal `REJECT_TOTAL_QTY / (REJECT_TOTAL_QTY + DEFECT_QTY) * 100`
|
||||
|
||||
### Requirement: Metric naming SHALL preserve semantic meaning across transformations
|
||||
The system SHALL keep explicit names for charge-off reject and non-charge-off defect metrics.
|
||||
|
||||
#### Scenario: No ambiguous remapping
|
||||
- **WHEN** service or export fields are generated
|
||||
- **THEN** `REJECT_TOTAL_QTY` SHALL NOT be renamed to `DEFECT_QTY`
|
||||
- **THEN** `DEFECT_QTY` SHALL refer only to `DEFECTQTY`
|
||||
|
||||
@@ -45,3 +45,27 @@ When contract loading falls back from the primary modernization contract artifac
|
||||
#### Scenario: Legacy contract fallback path selected
|
||||
- **WHEN** the primary contract artifact is unavailable and a legacy contract file is loaded
|
||||
- **THEN** the system SHALL log a warning that includes the selected legacy source path
|
||||
|
||||
### Requirement: Reject History route SHALL be included in governed shell route inventory
|
||||
The `/reject-history` route SHALL be represented in shell route contracts with complete governance metadata.
|
||||
|
||||
#### Scenario: Frontend route contract entry
|
||||
- **WHEN** route contract validation runs against `frontend/src/portal-shell/routeContracts.js`
|
||||
- **THEN** `/reject-history` SHALL exist with route id, title, owner, render mode, visibility policy, scope, and compatibility policy
|
||||
|
||||
#### Scenario: Native loader coverage
|
||||
- **WHEN** native module loader registry is validated
|
||||
- **THEN** `/reject-history` SHALL be resolvable in `nativeModuleRegistry`
|
||||
|
||||
### Requirement: Reject History governance metadata SHALL be parity-validated across sources
|
||||
Shell governance checks SHALL enforce parity for `/reject-history` between frontend and backend contract inventories.
|
||||
|
||||
#### Scenario: Contract parity for reject-history route
|
||||
- **WHEN** contract parity checks execute
|
||||
- **THEN** frontend and backend route inventories SHALL both include `/reject-history`
|
||||
- **THEN** metadata mismatch or missing route SHALL fail governance checks
|
||||
|
||||
#### Scenario: Navigation visibility governance
|
||||
- **WHEN** page status/navigation config is evaluated
|
||||
- **THEN** `/reject-history` SHALL have governed drawer assignment and ordering metadata
|
||||
|
||||
|
||||
@@ -137,3 +137,42 @@ The mid-section defect page SHALL use `AbortController` to cancel in-flight API
|
||||
- **THEN** the query SHALL NOT be cancelled by the pagination request
|
||||
- **THEN** the pagination SHALL use a separate abort key from the query
|
||||
|
||||
### Requirement: Reject History page SHALL be a pure Vite HTML entry
|
||||
The reject-history page SHALL be built from an HTML entry and emitted as static dist assets.
|
||||
|
||||
#### Scenario: Vite entry registration
|
||||
- **WHEN** Vite config inputs are evaluated
|
||||
- **THEN** `reject-history` SHALL map to `frontend/src/reject-history/index.html`
|
||||
|
||||
#### Scenario: Build output artifacts
|
||||
- **WHEN** `vite build` completes
|
||||
- **THEN** output SHALL include `reject-history.html`, `reject-history.js`, and `reject-history.css` in `static/dist/`
|
||||
|
||||
### Requirement: Reject History route SHALL serve static dist HTML
|
||||
The Flask route for `/reject-history` SHALL serve pre-built static HTML through `send_from_directory`.
|
||||
|
||||
#### Scenario: Static page serving
|
||||
- **WHEN** user navigates to `/reject-history`
|
||||
- **THEN** Flask SHALL serve `static/dist/reject-history.html` when the file exists
|
||||
- **THEN** HTML SHALL NOT be rendered through Jinja template interpolation
|
||||
|
||||
#### Scenario: Dist fallback response
|
||||
- **WHEN** `reject-history.html` is missing in dist
|
||||
- **THEN** route SHALL return a minimal fallback HTML that still references `/static/dist/reject-history.js`
|
||||
|
||||
### Requirement: Reject History shell integration SHALL use native module loading
|
||||
The page SHALL integrate with portal-shell native module loading policy.
|
||||
|
||||
#### Scenario: Native module registration
|
||||
- **WHEN** shell resolves a route component for `/reject-history`
|
||||
- **THEN** it SHALL dynamically import `frontend/src/reject-history/App.vue`
|
||||
- **THEN** the route style bundle SHALL be loaded via registered style loaders
|
||||
|
||||
### Requirement: Reject History page SHALL call APIs through shared core API module
|
||||
The page SHALL call backend APIs via `frontend/src/core/api.js` without legacy global dependencies.
|
||||
|
||||
#### Scenario: API call path
|
||||
- **WHEN** reject-history page executes GET or export requests
|
||||
- **THEN** requests SHALL use shared API utilities (`apiGet`/equivalent)
|
||||
- **THEN** page behavior SHALL NOT depend on `window.MesApi`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user