package com.kaidi.oa.seed; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.kaidi.oa.domain.FormTemplate; import com.kaidi.oa.repository.FormTemplateRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.InputStream; /** * Loads extra form templates from classpath:seed-templates/*.json on startup and * upserts them (by id) as built-in templates. Each JSON file is an array of * { id, name, category, org, instructions, form, flow } objects whose form/flow * mirror the frontend FormSchema / FlowSchema. Runs after the main DataSeeder * and is idempotent (re-running re-applies the latest JSON), so dropping a new * JSON file under resources/seed-templates and rebuilding adds templates without * any code change. This is how 凯迪科技's real approval processes are catalogued. */ @DemoSeed @Order(100) public class TemplateJsonSeeder implements CommandLineRunner { private final FormTemplateRepository repo; private final ObjectMapper om; public TemplateJsonSeeder(FormTemplateRepository repo, ObjectMapper om) { this.repo = repo; this.om = om; } @Override public void run(String... args) { Resource[] files; try { files = new PathMatchingResourcePatternResolver() .getResources("classpath*:seed-templates/*.json"); } catch (Exception e) { return; } int upserted = 0; for (Resource f : files) { try (InputStream in = f.getInputStream()) { JsonNode arr = om.readTree(in); if (arr == null || !arr.isArray()) { continue; } for (JsonNode t : arr) { String id = t.path("id").asText(null); if (id == null || id.isBlank()) { continue; } FormTemplate tpl = repo.findById(id).orElseGet(FormTemplate::new); tpl.setId(id); tpl.setName(t.path("name").asText("")); tpl.setCategory(t.path("category").asText("")); tpl.setOrg(t.path("org").asText("")); tpl.setInstructions(t.path("instructions").asText("")); tpl.setFormSchemaJson(t.has("form") ? t.get("form").toString() : "{}"); tpl.setFlowSchemaJson(t.has("flow") ? t.get("flow").toString() : "{}"); tpl.setBuiltin(true); if (tpl.getPublishedAt() == null || tpl.getPublishedAt().isBlank()) { tpl.setPublishedAt("2026-06-11"); } repo.save(tpl); upserted++; } } catch (Exception ignore) { // skip malformed file, keep going } } if (upserted > 0) { System.out.println("TemplateJsonSeeder: upserted " + upserted + " templates from seed-templates/*.json"); } } }