Initial commit: Add project files
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { UiGridColumn } from '../../../shared/ui/adapter/contracts'
|
||||
import DataGridShell from '../../../shared/ui/DataGridShell.vue'
|
||||
import type { DataQualityRun } from '../schema'
|
||||
|
||||
// Template fixture only. Production data must come from DAT-03 and pass Zod validation.
|
||||
const rows: DataQualityRun[] = []
|
||||
const columns = computed<UiGridColumn[]>(() => [
|
||||
{ field: 'source', header: 'Source' },
|
||||
{ field: 'session', header: 'Session' },
|
||||
{ field: 'status', header: 'DQ' },
|
||||
{ field: 'rowCount', header: 'Rows' },
|
||||
{ field: 'failedRows', header: 'Failed' },
|
||||
{ field: 'sourceWatermark', header: 'Watermark' },
|
||||
{ field: 'datasetId', header: 'Dataset' },
|
||||
{ field: 'completedAt', header: 'Completed' }
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main>
|
||||
<header>
|
||||
<h1>데이터 품질 운영</h1>
|
||||
<p>Raw→PIT→DQ→Dataset lineage를 확인합니다. QUARANTINED 데이터는 추천에 사용할 수 없습니다.</p>
|
||||
</header>
|
||||
<DataGridShell
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
empty-message="DAT-03 계약이 구현되면 서버 검증 결과가 표시됩니다."
|
||||
/>
|
||||
</main>
|
||||
</template>
|
||||
@@ -0,0 +1,27 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
export const dataQualityStatusSchema = z.enum(['PASS', 'WARN', 'QUARANTINED'])
|
||||
|
||||
export const dataQualityRunSchema = z.object({
|
||||
runId: z.string().uuid(),
|
||||
source: z.string().min(1),
|
||||
session: z.string().min(1),
|
||||
status: dataQualityStatusSchema,
|
||||
rowCount: z.number().int().nonnegative(),
|
||||
failedRows: z.number().int().nonnegative(),
|
||||
sourceWatermark: z.string().min(1),
|
||||
datasetId: z.string().min(1),
|
||||
contentHash: z.string().min(1),
|
||||
completedAt: z.string().datetime({ offset: true })
|
||||
}).superRefine((value, ctx) => {
|
||||
if (value.failedRows > value.rowCount) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: '실패 행 수는 전체 행 수를 초과할 수 없습니다.',
|
||||
path: ['failedRows']
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export const dataQualityRunsSchema = z.array(dataQualityRunSchema)
|
||||
export type DataQualityRun = z.infer<typeof dataQualityRunSchema>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { dataQualityRunSchema } from '../schema'
|
||||
|
||||
const valid = {
|
||||
runId: '00000000-0000-0000-0000-000000000001',
|
||||
source: 'KRX',
|
||||
session: '2026-08-01',
|
||||
status: 'PASS',
|
||||
rowCount: 100,
|
||||
failedRows: 0,
|
||||
sourceWatermark: 'KRX:2026-08-01',
|
||||
datasetId: 'dataset-1',
|
||||
contentHash: 'hash-1',
|
||||
completedAt: '2026-08-01T09:00:00Z'
|
||||
}
|
||||
|
||||
describe('data quality contract', () => {
|
||||
it('accepts a valid run', () => {
|
||||
expect(dataQualityRunSchema.safeParse(valid).success).toBe(true)
|
||||
})
|
||||
|
||||
it('rejects failed rows greater than total rows', () => {
|
||||
expect(dataQualityRunSchema.safeParse({ ...valid, failedRows: 101 }).success).toBe(false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user