refactor(WEB): 회계/견적/설정/생산 등 전반적 코드 개선 및 공통화 2차

- 회계 모듈 전면 개선: 청구/입금/출금/매입/매출/세금계산서/일반전표/거래처원장 등
- 견적 모듈 금액 포맷/할인/수식/미리보기 등 코드 정리
- 설정 모듈: 계정관리/직급/직책/권한 상세 간소화
- 생산 모듈: 작업지시서/작업자화면/검수 문서 코드 정리
- UniversalListPage 엑셀 다운로드 및 필터 기능 확장
- 대시보드/게시판/수주 등 날짜 유틸 공통화 적용
- claudedocs 문서 인덱스 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-20 10:45:47 +09:00
parent 71352923c8
commit f344dc7d00
123 changed files with 877 additions and 789 deletions

View File

@@ -23,6 +23,7 @@ import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';
import type { InspectionTemplateData, InspectionTemplateSectionItem } from './types';
import { formatNumber } from '@/lib/utils/amount';
// 중간검사 공정 타입
export type InspectionProcessType =
@@ -278,7 +279,7 @@ function resolveRefValue(
function formatDimension(val: number | undefined): string {
if (val === undefined || val === null) return '-';
return val.toLocaleString();
return formatNumber(val);
}
// ===== 항목별 입력 유형 판별 =====
@@ -337,7 +338,7 @@ function DynamicInspectionForm({
if (isNumericItem(item)) {
const numValue = formValues[fieldKey] as number | null | undefined;
const designLabel = designValue !== undefined ? designValue.toLocaleString() : '';
const designLabel = designValue !== undefined ? formatNumber(designValue) : '';
const toleranceLabel = item.tolerance
? ` (${designLabel ? designLabel + ' ' : ''}${formatToleranceLabel(item.tolerance)})`
: designLabel ? ` (${designLabel})` : '';
@@ -381,8 +382,8 @@ function DynamicInspectionForm({
const hasStandard = designValue !== undefined || item.standard;
const standardDisplay = designValue !== undefined
? (item.tolerance
? `${designValue.toLocaleString()} ${formatToleranceLabel(item.tolerance)}`
: String(designValue.toLocaleString()))
? `${formatNumber(designValue)} ${formatToleranceLabel(item.tolerance)}`
: String(formatNumber(designValue)))
: item.standard;
return (

View File

@@ -31,6 +31,7 @@ import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { getMaterialsForWorkOrder, registerMaterialInput, getMaterialsForItem, registerMaterialInputForItem, type MaterialForInput, type MaterialForItemInput } from './actions';
import type { WorkOrder } from '../ProductionDashboard/types';
import type { MaterialInput } from './types';
import { formatNumber } from '@/lib/utils/amount';
interface MaterialInputModalProps {
open: boolean;
@@ -55,7 +56,7 @@ interface MaterialGroup {
lots: MaterialForInput[];
}
const fmtQty = (v: number) => parseFloat(String(v)).toLocaleString();
const fmtQty = (v: number) => formatNumber(parseFloat(String(v)));
export function MaterialInputModal({
open,

View File

@@ -32,6 +32,7 @@ import type {
WorkStepData,
MaterialListItem,
} from './types';
import { formatNumber } from '@/lib/utils/amount';
interface WorkItemCardProps {
item: WorkItemData;
@@ -91,7 +92,7 @@ export const WorkItemCard = memo(function WorkItemCard({
<div className="flex items-center gap-1.5 text-sm text-gray-700">
<span className="text-gray-500"> </span>
<span className="font-medium">
{item.width.toLocaleString()} X {item.height.toLocaleString()} mm
{formatNumber(item.width)} X {formatNumber(item.height)} mm
</span>
<span className="font-medium text-gray-900">{item.quantity}</span>
</div>
@@ -205,7 +206,7 @@ export const WorkItemCard = memo(function WorkItemCard({
<TableRow key={mat.id}>
<TableCell className="text-center text-xs">{mat.lotNo}</TableCell>
<TableCell className="text-center text-xs">{mat.itemName}</TableCell>
<TableCell className="text-center text-xs">{parseFloat(String(mat.quantity)).toLocaleString()}</TableCell>
<TableCell className="text-center text-xs">{formatNumber(parseFloat(String(mat.quantity)))}</TableCell>
<TableCell className="text-center text-xs">{mat.unit}</TableCell>
<TableCell className="text-center">
<div className="flex items-center justify-center gap-1">
@@ -246,7 +247,7 @@ function ScreenCuttingInfo({ width, sheets }: { width: number; sheets: number })
<div className="p-4 bg-gray-50 rounded-lg border border-gray-100">
<p className="text-xs text-gray-400 mb-1.5"></p>
<p className="text-base font-semibold text-gray-900">
{width.toLocaleString()}mm X {sheets}
{formatNumber(width)}mm X {sheets}
</p>
</div>
);
@@ -265,7 +266,7 @@ function SlatExtraInfo({
return (
<div className="flex gap-2">
<Badge variant="outline" className="text-xs px-2.5 py-1 border-gray-300">
{length.toLocaleString()}mm
{formatNumber(length)}mm
</Badge>
<Badge variant="outline" className="text-xs px-2.5 py-1 border-gray-300">
{slatCount}
@@ -317,7 +318,7 @@ function BendingExtraInfo({ info }: { info: BendingInfo }) {
<div key={i} className="flex gap-2 text-xs">
<span className="text-gray-500 w-14">{i === 0 ? '길이별 수량' : ''}</span>
<span className="text-gray-900 font-medium">
{lq.length.toLocaleString()}mm X {lq.quantity}
{formatNumber(lq.length)}mm X {lq.quantity}
</span>
</div>
))}