feat(t-paliad-209): rename DeadlineRule.Code → SubmissionCode across Go layer
Workstream B Go sweep — matches mig 098. Every place the deadline-rules service reads/writes the per-rule identifier now uses the new column name and the new struct field. Distinct from rule_code (legal citation) and from proceeding_types.code (the proceeding's 3-segment code). Touch points: - models.DeadlineRule.Code → SubmissionCode (db + json tags renamed in lockstep — JSON contract `submission_code` is the new shape). - deadline_rule_service: ruleColumns SELECT list updated. - rule_editor_service: CreateRuleInput.Code → SubmissionCode (json tag too), INSERT + CloneAsDraft SELECT updated. - projection_service: lookupRuleByCode → lookupRuleBySubmissionCode (SQL WHERE clause + error message); every r.Code / parent.Code / rule.Code / first.Code / src.rule.Code read renamed. - fristenrechner: r.Code / prev.Code / rule.Code reads renamed in Calculate (parent-anchor + override-key + computed-by-code map) and in CalculateRule's LocalCode emission; the proceeding-code+submission- code resolver query uses `submission_code = $2`. - event_trigger_service / deadline_calculator: r.Code reads renamed. UIDeadline.Code (the calculator's wire response) is unchanged — that field is a separate API contract pointing at the same value; renaming it would force every frontend deadline-renderer through a contract break that isn't part of this workstream. Test fixtures updated to the new SubmissionCode field name; live-DB tests updated to the post-mig-098 prefixed values (`inf.sod` → `upc.inf.cfi.sod` etc.). New submission_codes_shape_test asserts every active+published row matches the 4+-segment proceeding-prefixed shape (sibling of TestProceedingCodeShape; mirrors mig 098 §6.1). go build ./... clean. go test ./internal/... green.
This commit is contained in:
116
internal/services/submission_codes_shape_test.go
Normal file
116
internal/services/submission_codes_shape_test.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"mgit.msbls.de/m/paliad/internal/db"
|
||||
)
|
||||
|
||||
// submissionCodeShapeRegex is the proceeding-code-prefixed shape
|
||||
// installed by mig 098 (t-paliad-209): the proceeding's 3-segment code
|
||||
// (`^[a-z_]+\.[a-z_]+\.[a-z_]+\.`) followed by at least one suffix
|
||||
// segment (and optional further dot-separated segments). The regex
|
||||
// allows underscores so the legacy archived bucket (`_archived_…`) and
|
||||
// hand-seeded test rules (e.g. `s11a.initial`) match alongside the
|
||||
// canonical taxonomy. Mirrors the assertion in mig 098 §6.1.
|
||||
var submissionCodeShapeRegex = regexp.MustCompile(
|
||||
`^[a-z_]+\.[a-z_]+\.[a-z_]+\.[a-z_]+(\..*)?$`)
|
||||
|
||||
// TestSubmissionCodeShape walks every active+published row in
|
||||
// paliad.deadline_rules and asserts that submission_code matches the
|
||||
// 4+-segment proceeding-code-prefixed shape ratified for t-paliad-209.
|
||||
// Sibling of TestProceedingCodeShape — same pattern, same goal: catch
|
||||
// drift between the migration's hard invariant and runtime state.
|
||||
//
|
||||
// Archived rows (proceeding `_archived_litigation`) are exempted; mig
|
||||
// 098's §6.1 assertion does the same by gating on lifecycle_state =
|
||||
// 'published'. Their codes get the archived prefix and the wider shape
|
||||
// they end up with sits outside the 4+-segment canonical form by
|
||||
// design.
|
||||
//
|
||||
// Skipped when TEST_DATABASE_URL is unset, mirroring the pattern in
|
||||
// proceeding_codes_shape_test.go.
|
||||
func TestSubmissionCodeShape(t *testing.T) {
|
||||
url := os.Getenv("TEST_DATABASE_URL")
|
||||
if url == "" {
|
||||
t.Skip("TEST_DATABASE_URL not set — skipping live DB test")
|
||||
}
|
||||
if err := db.ApplyMigrations(url); err != nil {
|
||||
t.Fatalf("apply migrations: %v", err)
|
||||
}
|
||||
pool, err := sqlx.Connect("postgres", url)
|
||||
if err != nil {
|
||||
t.Fatalf("connect: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
var rows []struct {
|
||||
ID string `db:"id"`
|
||||
SubmissionCode *string `db:"submission_code"`
|
||||
}
|
||||
if err := pool.SelectContext(ctx, &rows,
|
||||
`SELECT dr.id::text AS id, dr.submission_code
|
||||
FROM paliad.deadline_rules dr
|
||||
JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
|
||||
WHERE dr.is_active = true
|
||||
AND dr.lifecycle_state = 'published'
|
||||
AND pt.category = 'fristenrechner'
|
||||
ORDER BY dr.id`); err != nil {
|
||||
t.Fatalf("load active+published deadline_rules rows: %v", err)
|
||||
}
|
||||
if len(rows) == 0 {
|
||||
t.Fatal("no active+published fristenrechner deadline_rules — mig 098 likely not applied")
|
||||
}
|
||||
for _, r := range rows {
|
||||
if r.SubmissionCode == nil {
|
||||
t.Errorf("deadline_rules[id=%s] submission_code is NULL", r.ID)
|
||||
continue
|
||||
}
|
||||
if !submissionCodeShapeRegex.MatchString(*r.SubmissionCode) {
|
||||
t.Errorf("deadline_rules[id=%s] submission_code=%q does not match shape %s",
|
||||
r.ID, *r.SubmissionCode, submissionCodeShapeRegex.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestSubmissionCodeShapeRegexStandalone exercises the regex without a
|
||||
// DB so the shape rule is verified on every `go test ./...` run.
|
||||
func TestSubmissionCodeShapeRegexStandalone(t *testing.T) {
|
||||
good := []string{
|
||||
"upc.inf.cfi.soc",
|
||||
"upc.inf.cfi.sod",
|
||||
"upc.inf.cfi.def_to_ccr",
|
||||
"upc.rev.cfi.app",
|
||||
"de.inf.lg.klage",
|
||||
"de.inf.bgh.revision",
|
||||
"de.null.bgh.berufung",
|
||||
"dpma.appeal.bpatg.begruendung",
|
||||
"epa.opp.opd.beschwerde_begr",
|
||||
}
|
||||
for _, code := range good {
|
||||
if !submissionCodeShapeRegex.MatchString(code) {
|
||||
t.Errorf("good code %q rejected by submission-code shape regex", code)
|
||||
}
|
||||
}
|
||||
bad := []string{
|
||||
"inf.soc", // pre-mig-098: 2 segments
|
||||
"upc.inf", // 2 segments
|
||||
"upc.inf.cfi", // proceeding code shape, not a submission code
|
||||
"UPC.INF.CFI.SOC", // uppercase
|
||||
"upc-inf-cfi-soc", // dashes
|
||||
"",
|
||||
}
|
||||
for _, code := range bad {
|
||||
if submissionCodeShapeRegex.MatchString(code) {
|
||||
t.Errorf("bad code %q accepted by submission-code shape regex", code)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user