feat: add skipReason and skipDetail attributes to Suggestion#1372
feat: add skipReason and skipDetail attributes to Suggestion#1372Kanishkavijay39 wants to merge 7 commits intomainfrom
Conversation
|
This PR will trigger a minor release when merged. |
solaris007
left a comment
There was a problem hiding this comment.
Review: Skip Reason Attributes for Suggestion
What was done well
The enum + schema attribute pattern correctly follows the existing STATUSES/TYPES approach with Object.values() for type validation. Both attributes are optional (correct for supplementary skip metadata). The skipDetail validate function handles the falsy case properly. Already uses postgrestField mappings - PostgreSQL-ready.
Important
1. Opportunity model not updated despite PR title and description
Title says "Suggestion and Opportunity schemas", description says "ignores an opportunity from the UI" - but only Suggestion is changed. The Opportunity model has an IGNORED status and would logically need analogous fields (ignoreReason/ignoreDetail). Either add them or update the PR title/description.
2. No database migration for skip_reason/skip_detail columns
The suggestions table in mysticat-data-service/db/migrations/20250130000007_suggestions.sql has no skip_reason or skip_detail columns. Without a corresponding ALTER TABLE migration, any PostgREST PATCH with these fields will fail at runtime. Needs:
ADD COLUMN skip_reason TEXT(or a PG enum type)ADD COLUMN skip_detail VARCHAR(500)(or TEXT with CHECK constraint)- CHECK constraint on
skip_reasonto match the enum values
3. Enum value casing inconsistent within Suggestion model
Existing enums on Suggestion use UPPER_CASE values (STATUSES.NEW = 'NEW', TYPES.CODE_CHANGE = 'CODE_CHANGE'). The new SKIP_REASONS uses snake_case values ('already_implemented'). This is confusing within the same model. Either align with the existing UPPER_CASE convention or document why snake_case was chosen.
4. Missing negative/edge test cases
- No test for invalid skip reason value (should trigger
guardEnumrejection) - No test for
skipDetailexceeding 500 chars - No test for null values
- SKIP_REASONS enum test only checks 3 of 5 values (
INACCURATE_OR_INCOMPLETEandNO_REASONnot asserted)
5. skipDetail 500-char limit only enforced on creation, not on setter
The validate function is only invoked during collection-level validateItem() (creation), not by the Patcher's setSkipDetail(). So instance.setSkipDetail('a'.repeat(1000)) succeeds silently. This is a framework-level behavior, not specific to this PR, but worth being aware of - the DB-level constraint (VARCHAR or CHECK) becomes the real enforcement point.
Minor
postgrestFieldannotations are redundant -camelToSnakeinpostgrest.utils.jsalready convertsskipReasontoskip_reasonautomatically. No other non-id attribute in the schema uses explicitpostgrestField.NO_REASONenum value is semantically questionable - leavingskipReasonnull/undefined already means "no reason provided". Clarify whether the UI has an explicit "No reason" button that needs a distinct value.- JSDoc comment "Maps to PostgreSQL skip_reason" references the database column - model layer should be DB-agnostic. Simplify to "Predefined categories for skip reasons."
- Uses
typeof value === 'string'instead of theisString()utility from@adobe/spacecat-shared-utilsalready used elsewhere in the codebase.
Recommended Actions
| Priority | Action |
|---|---|
| Block | Create DB migration in mysticat-data-service before merging |
| Block | Update PR title/description, or add Opportunity model changes |
| Before merge | Align enum value casing with existing Suggestion enums |
| Before merge | Add negative test cases (invalid enum, length boundary) |
| Nice to have | Remove redundant postgrestField, clarify NO_REASON intent |
Optional free-text field to capture reason/note when a user skips a suggestion or ignores an opportunity from the UI.
…stion only) - Add Suggestion.SKIP_REASONS enum - Add skipReason and skipDetail attributes to Suggestion schema with postgrestField mapping - Remove statusMessage from Opportunity (hold out of scope per review) - Update unit tests
- Align SKIP_REASONS enum values to UPPER_CASE convention (matches STATUSES/TYPES) - Remove NO_REASON enum value (null/undefined already conveys no reason) - Remove redundant postgrestField annotations (camelToSnake handles mapping) - Use isString() utility instead of typeof check - Simplify JSDoc to be DB-agnostic - Add missing test coverage: all enum values asserted, null handling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6ea1d23 to
7832238
Compare
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thanks for the thorough review. All points addressed:
Minor items — all addressed:
|
There was a problem hiding this comment.
Hey @Kanishkavijay39
All blocking and pre-merge items from the previous review have been resolved:
- DB migration created - mysticat-data-service #108 with PG enum type
suggestion_skip_reason+varchar(500)for detail - PR title/description updated - Scoped to Suggestion only, Opportunity deferred. Comprehensive description with related issues (SITES-38900), related PRs, and test plan
- Enum casing aligned - UPPER_CASE values (
ALREADY_IMPLEMENTED,TOO_RISKY, etc.) matching existingSTATUSES/TYPESconvention - Tests improved - All 5 enum values asserted with
lengthOf(5)check, null handling tests for bothskipReasonandskipDetail - Redundant
postgrestFieldannotations removed -camelToSnakehandles the mapping - JSDoc simplified - "Predefined categories for skip reasons."
isString()utility - Now uses the shared-utils import instead oftypeofNO_REASONclarified - UI has an explicit "No reason" button, justifying the enum value
Clean, well-scoped change with proper cross-repo coordination (DB migration, API controller, frontend PRs linked).
Summary
Adds skipReason (enum) and skipDetail (string, max 500 chars) as optional attributes on the Suggestion model, enabling structured tracking of why users skip
suggestions.
Related Issues
Related PRs
Test plan
Thanks for contributing!