diff --git a/backend/lcfs/web/api/base.py b/backend/lcfs/web/api/base.py index d072e8531..ed21cbadc 100644 --- a/backend/lcfs/web/api/base.py +++ b/backend/lcfs/web/api/base.py @@ -224,6 +224,7 @@ def apply_number_filter_conditions(field, filter_value, filter_option): "greaterThanOrEqual": field >= filter_value, "lessThan": field < filter_value, "lessThanOrEqual": field <= filter_value, + "startsWith": cast(field, String).like(f"{filter_value}%"), } return number_filter_mapping.get(filter_option) diff --git a/backend/lcfs/web/api/fuel_code/__init__.py b/backend/lcfs/web/api/fuel_code/__init__.py index 51f29b311..45fe85147 100644 --- a/backend/lcfs/web/api/fuel_code/__init__.py +++ b/backend/lcfs/web/api/fuel_code/__init__.py @@ -1,4 +1,4 @@ -"""User API.""" +"""Fuel code API.""" from lcfs.web.api.fuel_code.views import router diff --git a/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReport.test.js b/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReport.test.js index 7190e79a9..e175c8f20 100644 --- a/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReport.test.js +++ b/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReport.test.js @@ -30,6 +30,68 @@ When('the supplier creates a new compliance report', () => { cy.contains('.MuiList-root li', currentYear).click() }) +When('the supplier navigates to the fuel supply page', () => { + cy.get( + '[data-test="schedule-list"] > :nth-child(1) > .MuiTypography-root' + ).click() + + cy.contains('.MuiTypography-h5', 'Add new supply of fuel').should( + 'be.visible' + ) +}) + +When('the supplier enters a valid fuel supply row', () => { + // First, ensure the grid is loaded + cy.get('.ag-root').should('be.visible') + + cy.wait(1000) + + // Set "Fuel type" to "CNG" + cy.get('div[col-id="fuelType"][title="Select the fuel type from the list"]') + .click() + .find('input') + .type('CNG{enter}') + + cy.wait(800) + + // Set "Fuel category" to "Gasoline" + cy.get( + 'div[col-id="fuelCategory"][title="Select the fuel category from the list"]' + ) + .click() + .find('input') + .type('Gasoline{enter}') + cy.wait(800) + + // Set "Determining carbon intensity" to "Default carbon intensity - section 19 (b) (ii)" + cy.get( + 'div[col-id="provisionOfTheAct"][title="Act Relied Upon to Determine Carbon Intensity: Identify the appropriate provision of the Act relied upon to determine the carbon intensity of each fuel."]' + ).click() + + cy.get('body').click() + cy.contains('Row updated successfully.').should('be.visible') + cy.wait(700) + cy.get('.ag-body-horizontal-scroll-viewport').scrollTo(1000, 0) + cy.wait(1200) + + // Set "Quantity" to "10,000" + cy.get('div.ag-cell[col-id="quantity"]') + .click() + .wait(1200) + .find('input') + .type('10000{enter}') + + cy.contains('Row updated successfully.').should('be.visible') +}) + +When('saves and returns to the report', () => { + cy.get('.MuiButton-contained').click() + + cy.get('[data-test="compliance-report-status"]') + .should('be.visible') + .and('have.text', 'Status: Draft') +}) + Then('the compliance report introduction is shown', () => { // Assert the header cy.get('[data-test="compliance-report-header"]') @@ -57,3 +119,24 @@ Then('the compliance report introduction is shown', () => { 'Welcome to the British Columbia Low Carbon Fuel Standard Portal' ) }) + +Then('the compliance report summary includes the quantity', () => { + cy.wait(2000) + cy.get( + '[data-test="renewable-summary"] > .MuiTable-root > .MuiTableBody-root > :nth-child(2) > :nth-child(3) > span' + ) + .should('be.visible') + .and('have.text', '10,000') + + cy.get( + '[data-test="renewable-summary"] > .MuiTable-root > .MuiTableBody-root > :nth-child(3) > :nth-child(3) > span' + ) + .should('be.visible') + .and('have.text', '10,000') + + cy.get( + '[data-test="renewable-summary"] > .MuiTable-root > .MuiTableBody-root > :nth-child(4) > :nth-child(3) > span' + ) + .should('be.visible') + .and('have.text', '500') +}) diff --git a/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReportManagement.feature b/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReportManagement.feature index 01361dcff..a0e9c1975 100644 --- a/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReportManagement.feature +++ b/frontend/cypress/e2e/Pages/ComplianceReport/ComplianceReportManagement.feature @@ -6,3 +6,7 @@ Feature: Compliance Report Management And the supplier navigates to the compliance reports page And the supplier creates a new compliance report Then the compliance report introduction is shown + When the supplier navigates to the fuel supply page + And the supplier enters a valid fuel supply row + And saves and returns to the report + Then the compliance report summary includes the quantity diff --git a/frontend/src/views/Admin/AdminMenu/components/_schema.js b/frontend/src/views/Admin/AdminMenu/components/_schema.js index 85691e6c8..70b652b71 100644 --- a/frontend/src/views/Admin/AdminMenu/components/_schema.js +++ b/frontend/src/views/Admin/AdminMenu/components/_schema.js @@ -162,7 +162,12 @@ export const userLoginHistoryColDefs = (t) => [ { field: 'userLoginHistoryId', headerName: t('admin:userLoginHistoryColLabels.userLoginHistoryId'), - cellDataType: 'number' + cellDataType: 'number', + filter: 'agNumberColumnFilter', + filterParams: { + filterOptions: ['startsWith'], + buttons: ['clear'] + } }, { field: 'keycloakEmail', @@ -230,7 +235,12 @@ export const auditLogColDefs = (t) => [ headerName: t('admin:auditLogColLabels.rowId'), minWidth: 100, sortable: true, - filter: 'agTextColumnFilter' + cellDataType: 'number', + filter: 'agNumberColumnFilter', + filterParams: { + filterOptions: ['startsWith'], + buttons: ['clear'] + } }, { colId: 'changedFields', diff --git a/frontend/src/views/ComplianceReports/components/ActivityLinkList.jsx b/frontend/src/views/ComplianceReports/components/ActivityLinkList.jsx index 7eba514ff..c968f8e4a 100644 --- a/frontend/src/views/ComplianceReports/components/ActivityLinkList.jsx +++ b/frontend/src/views/ComplianceReports/components/ActivityLinkList.jsx @@ -83,7 +83,11 @@ export const ActivityLinksList = () => { }, [t, navigate, compliancePeriod, complianceReportId]) return ( - + {activityList.map((activity, index) => ( diff --git a/frontend/src/views/FuelCodes/_schema.jsx b/frontend/src/views/FuelCodes/_schema.jsx index 6f59ffceb..db7fc62d5 100644 --- a/frontend/src/views/FuelCodes/_schema.jsx +++ b/frontend/src/views/FuelCodes/_schema.jsx @@ -31,13 +31,24 @@ export const fuelCodeColDefs = (t) => [ { field: 'fuelSuffix', headerName: t('fuelCode:fuelCodeColLabels.fuelSuffix'), - cellRenderer: TextRenderer + cellRenderer: TextRenderer, + type: 'numericColumn', + filter: 'agNumberColumnFilter', + filterParams: { + filterOptions: ['startsWith'], + buttons: ['clear'] + } }, { field: 'carbonIntensity', headerName: t('fuelCode:fuelCodeColLabels.carbonIntensity'), cellRenderer: TextRenderer, - type: 'numericColumn' + type: 'numericColumn', + filter: 'agNumberColumnFilter', + filterParams: { + filterOptions: ['startsWith'], + buttons: ['clear'] + } }, { field: 'edrms', diff --git a/frontend/src/views/Transactions/_schema.js b/frontend/src/views/Transactions/_schema.js index 9978771a7..46bbbc82c 100644 --- a/frontend/src/views/Transactions/_schema.js +++ b/frontend/src/views/Transactions/_schema.js @@ -2,7 +2,7 @@ import { numberFormatter, currencyFormatter, dateFormatter, - spacesFormatter, + spacesFormatter } from '@/utils/formatters' import { TransactionStatusRenderer } from '@/utils/grid/cellRenderers' import { BCColumnSetFilter } from '@/components/BCDataGrid/components' @@ -26,7 +26,7 @@ export const transactionsColDefs = (t) => [ return `${prefix}${params.data.transactionId}` }, filterParams: { - buttons:["clear"], + buttons: ['clear'] } }, { @@ -39,11 +39,11 @@ export const transactionsColDefs = (t) => [ textFormatter: (value) => value.replace(/\s+/g, '').toLowerCase(), textCustomComparator: (filter, value, filterText) => { // Remove spaces and convert both to lowercase for comparison - const cleanFilterText = filterText.replace(/\s+/g, '').toLowerCase(); - const cleanValue = value.replace(/\s+/g, '').toLowerCase(); - return cleanValue.includes(cleanFilterText); + const cleanFilterText = filterText.replace(/\s+/g, '').toLowerCase() + const cleanValue = value.replace(/\s+/g, '').toLowerCase() + return cleanValue.includes(cleanFilterText) }, - buttons:["clear"], + buttons: ['clear'] }, width: 222 }, @@ -54,7 +54,7 @@ export const transactionsColDefs = (t) => [ minWidth: 300, flex: 2, filterParams: { - buttons:["clear"], + buttons: ['clear'] } }, { @@ -64,7 +64,7 @@ export const transactionsColDefs = (t) => [ minWidth: 300, flex: 2, filterParams: { - buttons:["clear"], + buttons: ['clear'] } }, { @@ -76,7 +76,8 @@ export const transactionsColDefs = (t) => [ width: 140, filter: 'agNumberColumnFilter', filterParams: { - buttons:["clear"], + filterOptions: ['startsWith'], + buttons: ['clear'] } }, { @@ -86,12 +87,13 @@ export const transactionsColDefs = (t) => [ valueFormatter: currencyFormatter, width: 190, valueGetter: (params) => { - const value = params.data?.pricePerUnit; - return value !== null && value !== undefined ? value : null; + const value = params.data?.pricePerUnit + return value !== null && value !== undefined ? value : null }, filter: 'agNumberColumnFilter', filterParams: { - buttons:["clear"], + filterOptions: ['startsWith'], + buttons: ['clear'] } }, { @@ -122,20 +124,20 @@ export const transactionsColDefs = (t) => [ filterOptions: ['inRange', 'equals', 'lessThan', 'greaterThan'], defaultOption: 'inRange', comparator: (filterDate, cellValue) => { - const cellDate = new Date(cellValue).setHours(0, 0, 0, 0); - const filterDateOnly = new Date(filterDate).setHours(0, 0, 0, 0); + const cellDate = new Date(cellValue).setHours(0, 0, 0, 0) + const filterDateOnly = new Date(filterDate).setHours(0, 0, 0, 0) - if (cellDate < filterDateOnly) { - return -1; // Cell date is before the filter date - } else if (cellDate > filterDateOnly) { - return 1; // Cell date is after the filter date - } else { - return 0; // Dates are the same (ignoring time) - } + if (cellDate < filterDateOnly) { + return -1 // Cell date is before the filter date + } else if (cellDate > filterDateOnly) { + return 1 // Cell date is after the filter date + } else { + return 0 // Dates are the same (ignoring time) + } }, browserDatePicker: true, // Uses the browser's date picker if available - buttons:["clear"], - } + buttons: ['clear'] + } } ]