datatestool/macos/Sources/DataTestApp/Models.swift

281 lines
7.7 KiB
Swift

import Foundation
struct ProjectItem: Codable, Identifiable, Sendable {
let id: String
let name: String
let created_at: String
}
struct RequirementItem: Codable, Identifiable, Sendable {
let id: String
let project_id: String
let name: String
let status: String
let current_version: Int
let created_at: String
let source_path: String
let extraction: RequirementExtraction?
let metadata_ready: Bool
let metadata_complete: Bool
let metadata_missing_tables: [String]
}
struct RequirementExtraction: Codable, Sendable {
let requirement_name: String
let tasks: [ExtractedTask]
let open_questions: [String]
}
struct ExtractedTask: Codable, Identifiable, Sendable {
var id: String { name + targets.joined(separator: "|") }
let name: String
let sources: [String]
let targets: [String]
let field_mappings: [JSONValue]
let rules: [String]
}
struct CaseCount: Codable, Identifiable, Sendable {
var id: String { status }
let status: String
let count: Int
}
struct TestCaseItem: Codable, Identifiable, Sendable {
let id: String
let requirement_id: String
let requirement_name: String
let name: String
let table_name: String
let category: String
let status: String
let version: Int
let fields: [String]
let sql: String
let assertions: [CaseAssertion]
let validation_errors: [String]
let created_at: String
}
struct CaseAssertion: Codable, Sendable {
let type: String
let actual: String?
let expected: JSONValue?
let minimum: Double?
let maximum: Double?
}
enum JSONValue: Codable, Sendable, CustomStringConvertible {
case string(String)
case number(Double)
case boolean(Bool)
case object([String: JSONValue])
case array([JSONValue])
case null
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() { self = .null }
else if let value = try? container.decode(Bool.self) { self = .boolean(value) }
else if let value = try? container.decode(Double.self) { self = .number(value) }
else if let value = try? container.decode(String.self) { self = .string(value) }
else if let value = try? container.decode([String: JSONValue].self) { self = .object(value) }
else { self = .array(try container.decode([JSONValue].self)) }
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let value): try container.encode(value)
case .number(let value): try container.encode(value)
case .boolean(let value): try container.encode(value)
case .object(let value): try container.encode(value)
case .array(let value): try container.encode(value)
case .null: try container.encodeNil()
}
}
var description: String {
switch self {
case .string(let value): value
case .number(let value): value.rounded() == value ? String(Int(value)) : String(value)
case .boolean(let value): String(value)
case .object(let value): value.map { "\($0.key)=\($0.value)" }.sorted().joined(separator: ", ")
case .array(let value): value.map(\.description).joined(separator: ", ")
case .null: "null"
}
}
}
struct MetadataColumn: Codable, Identifiable, Sendable {
var id: Int { cid }
let cid: Int
let name: String
let type: String
let notNull: Int
let defaultValue: String?
let pk: Int
var ordinalText: String { String(cid + 1) }
var nullableText: String { notNull == 0 ? "" : "" }
var defaultText: String { defaultValue ?? "" }
var primaryKeyText: String { pk > 0 ? "" : "" }
enum CodingKeys: String, CodingKey {
case cid, name, type, pk
case notNull = "notnull"
case defaultValue = "dflt_value"
}
}
struct MetadataTableItem: Codable, Identifiable, Sendable {
let id: String
let requirement_id: String
let requirement_name: String
let database_name: String
let name: String
let type: String
let row_count: Int
let columns: [MetadataColumn]
}
struct RunItem: Codable, Identifiable, Sendable {
let id: String
let requirement_id: String
let requirement_version: Int
let status: String
let batch_id: String
let biz_date: String?
let started_at: String
let finished_at: String?
}
struct MetricItem: Codable, Identifiable, Sendable {
let id: Int
let requirement_id: String
let table_name: String
let field_name: String?
let batch_id: String
let biz_date: String?
let metric_type: String
let metric_value: Double?
let metric_json: String?
let definition_version: Int
let collected_at: String
}
struct ReportItem: Codable, Identifiable, Sendable {
let id: String
let run_id: String
let requirement_id: String
let requirement_version: Int
let status: String
let format: String
let file_path: String
let content: String
let created_at: String
}
struct CaseResultItem: Codable, Identifiable, Sendable {
let id: Int
let run_id: String
let case_id: String
let requirement_id: String
let case_name: String
let status: String
let actual_json: String?
let assertion_json: String
let sample_json: String?
let error_message: String?
let duration_ms: Int
let created_at: String
}
struct FailureAnalysis: Codable, Sendable {
let summary: String
let suspected_layer: String
let root_cause: String
let evidence: [String]
let recommendations: [String]
let validation_sql: [String]
let confidence: String
}
struct FailureAnalysisItem: Codable, Identifiable, Sendable {
let id: Int
let result_id: Int
let run_id: String
let case_id: String
let requirement_id: String
let status: String
let created_at: String
let analysis: FailureAnalysis
}
struct CaseAgentMessageItem: Codable, Identifiable, Sendable {
let id: Int
let requirement_id: String
let role: String
let content: String
let operation_json: String?
let created_at: String
}
struct CaseChatProgressEvent: Codable, Identifiable, Sendable {
var id: Int { sequence }
let type: String
let sequence: Int
let phase: String
let status: String
let title: String
let detail: String
let timestamp: String
}
struct TestRunProgressEvent: Codable, Identifiable, Sendable {
var id: Int { sequence }
let type: String
let sequence: Int
let event: String
let run_id: String?
let case_id: String?
let case_name: String?
let status: String
let index: Int?
let total: Int?
let duration_ms: Int?
let error: String?
let detail: String?
let timestamp: String
}
struct CaseReviewEventItem: Codable, Identifiable, Sendable {
let id: Int
let case_id: String
let requirement_id: String
let case_version: Int
let decision: String
let comment: String?
let created_at: String
}
struct Dashboard: Codable, Sendable {
let projects: [ProjectItem]
let requirements: [RequirementItem]
let cases: [CaseCount]
let case_items: [TestCaseItem]
let metadata: [MetadataTableItem]
let runs: [RunItem]
let metrics: [MetricItem]
let reports: [ReportItem]
let result_items: [CaseResultItem]
let failure_analyses: [FailureAnalysisItem]
let case_agent_messages: [CaseAgentMessageItem]
let case_review_events: [CaseReviewEventItem]
static let empty = Dashboard(
projects: [], requirements: [], cases: [], case_items: [], metadata: [], runs: [], metrics: [], reports: [],
result_items: [], failure_analyses: [], case_agent_messages: [], case_review_events: []
)
}