30 lines
1.6 KiB
TypeScript
30 lines
1.6 KiB
TypeScript
import type { KbxImportDefinition, KbxImportMapping } from '@kbx/contracts'
|
|
|
|
export type KbxImportMappingIssueCode = 'required-missing' | 'duplicate-target'
|
|
export interface KbxImportMappingIssue {
|
|
code: KbxImportMappingIssueCode
|
|
fieldKey: string
|
|
message: string
|
|
}
|
|
|
|
export function validateKbxImportMappings(definition:KbxImportDefinition,mappings:readonly KbxImportMapping[]):KbxImportMappingIssue[]{
|
|
const fields=definition.fields.filter(field=>field.importable!==false)
|
|
const targets=mappings.map(mapping=>mapping.targetField).filter((value):value is string=>Boolean(value))
|
|
const issues:KbxImportMappingIssue[]=[]
|
|
for(const target of [...new Set(targets.filter((value,index)=>targets.indexOf(value)!==index))]){
|
|
const field=fields.find(item=>item.key===target)
|
|
issues.push({code:'duplicate-target',fieldKey:target,message:`${field?.label ?? target} 필드에 Excel 열이 두 개 이상 연결되어 있습니다.`})
|
|
}
|
|
for(const field of fields.filter(item=>item.required)){
|
|
if(!targets.includes(field.key))issues.push({code:'required-missing',fieldKey:field.key,message:`${field.label} 필수 필드를 매핑하세요.`})
|
|
}
|
|
return issues
|
|
}
|
|
|
|
export function validateKbxImportFileCandidate(definition:KbxImportDefinition,file:{name:string;size:number}):string|null{
|
|
if(!file.name.toLocaleLowerCase().endsWith('.xlsx'))return 'Excel .xlsx 파일만 업로드할 수 있습니다.'
|
|
const maxBytes=definition.maxFileSizeBytes??10*1024*1024
|
|
if(file.size>maxBytes)return `파일 크기는 ${Math.round(maxBytes/1048576)}MB 이하여야 합니다.`
|
|
return null
|
|
}
|