material_manage_system/docs/superpowers/plans/2026-09-20-obsolete-material-policy.md
2026-09-20 14:29:41 +08:00

4.7 KiB

Obsolete Material Policy Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Exclude obsolete materials from operational selection and reject them in new or edited warehouse operations while preserving administrative management, historical records, and readable disabled selections when editing old documents.

Architecture: GET /materials gains a validated status scope that defaults to active records. The material-management UI requests all records, while shared operational options keep the active default. A distinct active-status check is applied at server-side operation boundaries; historical queries remain status-agnostic.

Tech Stack: Go 1.21, Gin, MySQL, Vue 3, Pinia, Vitest, sqlmock.

Spec: User-approved table in this conversation: operational selectors return active materials; material management returns all; historical documents remain readable; new and edited operations require active materials.

Global Constraints

  • Do not delete or mutate historical document records.
  • Keep Exists as an existence check; use a new active-status check for operational validation.
  • Default list scope is active; only material management requests all.
  • Use test-first development for each behavior change.

Task 1: Status-scoped material lists

Files:

  • Modify: internal/handler/api.go, internal/service/material.go, internal/repository/material.go
  • Modify: internal/repository/material_test.go
  • Modify: frontend/src/stores/materials.js, frontend/src/views/Materials.vue, docs/api.md

Interfaces:

  • Produces: MaterialService.List(search, status string, limit, offset int) and repository equivalent.

  • Produces: GET /materials defaults to status=active; status=all returns active and obsolete records.

  • Write sqlmock tests for active and all list SQL predicates.

  • Run the focused repository tests and observe missing status-aware query behavior.

  • Add a status filter to the count and result queries; accept active, obsolete, and all in the handler.

  • Make fetchMaterials accept a status argument and have Materials.vue request all; leave fetchMaterialOptions on the active default.

  • Update API documentation and run focused backend/frontend tests.

Task 2: Server-side active material validation

Files:

  • Modify: internal/service/material.go, internal/service/errors.go
  • Modify: internal/service/inbound.go, internal/service/outbound.go, internal/service/application.go
  • Modify: internal/handler/api.go, internal/service/material_test.go

Interfaces:

  • Produces: MaterialService.IsActive(id int64) (bool, error) and ErrMaterialObsolete.

  • Consumes: active check in inbound, outbound, and application create/edit validation.

  • Write a failing service test for a material whose status is obsolete.

  • Run it and observe that existence currently passes without evaluating status.

  • Implement IsActive and use it before transaction work in inbound/outbound/application workflows.

  • Map ErrMaterialObsolete to a clear 400 API response.

  • Run related service/handler tests.

Task 3: Cache and regression verification

Files:

  • Modify: frontend/src/stores/materials.js, frontend/src/stores/materials.test.js

  • Modify: docs/api.md

  • Write a failing frontend store test proving obsolete/restore refreshes operational options.

  • Refresh materialOptions after obsolete and restore calls.

  • Run the full frontend test suite and go test ./....

  • Confirm historical document detail queries remain unfiltered by material status.

Task 4: Read-only representation of obsolete historical selections

Files:

  • Modify: internal/model/model.go, internal/repository/inbound.go, internal/repository/outbound.go
  • Modify: frontend/src/views/Inbound.vue, frontend/src/views/Outbound.vue
  • Modify: frontend/src/views/Inbound.test.js

Interfaces:

  • Produces: inbound/outbound item responses that include the material status used by editing forms.

  • Produces: selected obsolete items are kept in their edit-form options with disabled: true.

  • Write a failing view test that opens a historical document containing an obsolete material and expects its code/name to remain visible in a disabled select option.

  • Include m.status in document item detail queries and responses without filtering the historical join.

  • Merge an obsolete item from the document detail into that edit row's options only; mark it disabled and do not add it to shared active options.

  • Verify save remains blocked server-side by Task 2 when the old obsolete material is retained.