feat(OPS-5772): enforce BLI obligate-by date within SC Period of Performance#5828
Draft
rajohnson90 wants to merge 26 commits into
Draft
feat(OPS-5772): enforce BLI obligate-by date within SC Period of Performance#5828rajohnson90 wants to merge 26 commits into
rajohnson90 wants to merge 26 commits into
Conversation
…ate by outside POP window
Contributor
Author
|
Hold on sorry I messed up. The description as is is NOT correct. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Enforces that a Budget Line Item's Need By Date (obligate-by date) falls within the Period of Performance (PoP) window defined by the agreement's Service Components, and prevents SC edits that would push non-draft BLIs outside that window.
backend/ops_api/ops/services/budget_line_items.py_validation_change_status_higher_than_draftinto three focused helpers:_validate_agreement_for_status_change,_validate_amount_and_date_for_status_change, and_validate_date_within_sc_window._validate_date_within_sc_window: for non-superusers, rejects any non-DRAFT BLI whosedate_neededfalls outside[sc_start_date, sc_end_date](inclusive). Both bounds are optional — a missing bound places no constraint.backend/ops_api/ops/services/services_component.py_validate_bli_pop_window: called on SCperiod_start/period_endupdates; rejects the change if any non-draft BLI would fall outside the resulting aggregate window across all SCs._validate_bli_pop_window_for_create: called when a new SC is created with dates; same check against the combined window of new + existing SCs.backend/models/agreements.pysc_start_dateproperty:min(period_start)across all SCs (None if no SC has a start date).sc_end_dateproperty:max(period_end)across all SCs (None if no SC has an end date).frontend/src/components/BudgetLineItems/BudgetLinesForm/datePickerSuite.jsneedByDateVest test: "Date must fall within the agreement's period of performance." Guards onscStartDate/scEndDatebeing present and uses string comparison onYYYY-MM-DDto avoid timezone issues. Each bound is independently optional (one-sided window supported).frontend/src/components/BudgetLineItems/BudgetLinesForm/BudgetLinesForm.jsxscStartDateandscEndDateprops, passes them through to the date picker suite on every run. AuseEffectre-runs the suite whenever the SC window changes so the PoP error appears without the user touching the date field.frontend/src/components/ServicesComponents/ServicesComponentForm/suite.jsservicesComponentSelectis non-zero. Inadd/editmode, computes the aggregate SC window fromallServicesComponents(pre-merged with live form values by the hook) and rejects changes that would leave any non-draft BLI outside the window. Each bound guards independently — absent bound = no constraint.frontend/src/components/ServicesComponents/ServicesComponentForm/ServicesComponentForm.jsxscFormSuite,allServicesComponentsForSuite, andnonDraftBudgetLinesprops. Runs the suite on every form-data change and surfaces errors onservicesComponentSelect,popStartDate, andpopEndDatefields. SC number field errors only shown after the field has been touched.frontend/src/components/ServicesComponents/ServicesComponents.hooks.jsscFormSuiteparam. ComputesallServicesComponentsForSuite(memos the SC array with live form dates merged in for the SC being edited). BlockshandleSubmitif the suite has errors. Resets the suite on cancel.frontend/src/components/CreateBLIsAndSCs/CreateBLIsAndSCs.jsx/.hooks.jsscStartDate/scEndDatefrom the agreement's SC window down toBudgetLinesForm.backend/openapi.yml403responses; correctsServicesComponentschema (nullablefields, properrequiredplacement).frontend/src/types/AgreementTypes.d.tssc_start_dateandsc_end_dateto theAgreementtype.Tests
test_budget_line_item.py: SC window boundary tests (before/on/after start and end), one-sided window (start-only, end-only), undefined window (multi-SC all-null), DRAFT→PLANNED transitions under each scenario, superuser bypass.test_budget_line_item_power_user.py: Superusers can setdate_neededoutside the SC PoP window.test_services_component.py: SC update/create validations that protect existing non-draft BLIs.datePickerSuite.test.js/BudgetLinesForm.test.jsx: PoP boundary validation in the BLI date picker.ServicesComponentForm/suite.test.js: Full suite — required-field validation, add/edit mode PoP checks, one-sided windows, undefined windows, two-SC scenarios, draft BLI exemption.Issue
#5772
How to test
Backend (from
backend/ops_api/):Frontend (from
frontend/):Manual (UI)
period_start = 2025-01-01andperiod_end = 2025-12-31.date_neededoutside[2025-01-01, 2025-12-31]shows an inline error and blocks save.period_endto before the BLI'sdate_needed. Verify the form shows an error and blocks the save.date_neededis accepted.A11y impact
A11Y-SUPPRESSIONmetadata (owner, expires, rationale)Storybook
Screenshots
Please add screenshots showing the inline validation error on the BLI date picker and the SC form PoP error.
Definition of Done Checklist
Links
N/A