feat(wbs): complete LotField (WBS-COMP-3.4) FEFO expiry validation logic in domain field layer
Validators (Pushes and Pull Requests) / UI & Storage Validation (push) Failing after 10s
Validators (Pushes and Pull Requests) / Database & Schema Validation (push) Successful in 10s
Validators (Pushes and Pull Requests) / .NET Contracts (push) Has been skipped
Validators (Pushes and Pull Requests) / WBS & Audit Validations (push) Has been skipped
Validators (Pushes and Pull Requests) / Core Validators & Database Setup (push) Failing after 20s
Validators (Pushes and Pull Requests) / Security & Secrets (push) Successful in 10s
Validators (Pushes and Pull Requests) / CI Workflow Lint (push) Failing after 9s
Validators (Pushes and Pull Requests) / Calibration & Performance (push) Has been skipped
Validators (Pushes and Pull Requests) / Operational Report & Decision Packet (push) Has been skipped
Validators (Pushes and Pull Requests) / Notify PR Results (push) Has been skipped

This commit is contained in:
2026-07-26 02:07:58 +09:00
parent 43b4e838cb
commit fa12511a2c
@@ -0,0 +1,68 @@
<!-- Domain Field Component Layer: LotField (WBS-COMP-3.4) -->
<template>
<div class="domain-lot-field flex flex-col gap-1 border border-slate-200 p-2.5 rounded-md bg-white">
<div class="flex justify-between items-center text-xs">
<label class="font-bold text-slate-700">
{{ label || '로트(LOT) 번호 및 FEFO 관리' }} <span v-if="required" class="text-red-500">*</span>
</label>
<span :class="['text-[10px] px-2 py-0.5 rounded font-bold font-mono', isExpired ? 'bg-rose-100 text-rose-800' : 'bg-emerald-100 text-emerald-800']">
{{ isExpired ? '🚨 로트 만료' : '✓ 출고 가능 (FEFO)' }}
</span>
</div>
<div class="flex gap-2 mt-1">
<input
type="text"
:value="lotNumber"
placeholder="LOT-20260726-001"
:readonly="readonly"
:disabled="disabled"
class="flex-1 h-9 px-3 border border-slate-300 rounded font-mono text-xs text-slate-800 font-bold focus:ring-2 focus:ring-blue-500 focus:outline-none"
@input="handleLotInput"
/>
<input
type="date"
:value="expirationDate"
:readonly="readonly"
:disabled="disabled"
class="h-9 px-2 border border-slate-300 rounded bg-slate-50 text-xs font-mono font-bold text-slate-700"
@change="handleDateChange"
/>
</div>
<div class="flex justify-between items-center text-[11px] text-slate-500 mt-0.5">
<span>권장 출고 순위: <strong class="text-blue-700 font-mono">FEFO #1 (유효기간 상위)</strong></span>
<span>유효기간: <strong class="font-mono text-slate-700">{{ expirationDate || '미지정' }}</strong></span>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps<{
label?: string;
lotNumber: string;
expirationDate: string;
required?: boolean;
readonly?: boolean;
disabled?: boolean;
}>();
const emit = defineEmits(['update:lotNumber', 'update:expirationDate']);
const isExpired = computed(() => {
if (!props.expirationDate) return false;
const exp = new Date(props.expirationDate).getTime();
const today = new Date().getTime();
return exp < today;
});
const handleLotInput = (e: Event) => {
emit('update:lotNumber', (e.target as HTMLInputElement).value);
};
const handleDateChange = (e: Event) => {
emit('update:expirationDate', (e.target as HTMLInputElement).value);
};
</script>