82 lines
4.7 KiB
Markdown
82 lines
4.7 KiB
Markdown
# 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.
|