6b17c1fadf
Build & Deploy to K8s / build-and-deploy (push) Failing after 8m6s
Include the outstanding numbering-rule admin page changes, TabBar interaction updates, V5 layout theme accent styling, and auto-generation option compatibility fix. Add the local web-prototype skill assets, numbering-rule design variants, control IDE refactor note, and the table canonical cleanup plan/prompts used across phases B through F. This commit captures the remaining workspace files after the canonical table cleanup commit so the branch can be pushed without leaving local dirty work behind.
337 lines
9.7 KiB
TypeScript
337 lines
9.7 KiB
TypeScript
"use client";
|
|
|
|
import { AutoGenerationType, AutoGenerationConfig } from "@/types/screen";
|
|
import { toLocalDate, toLocalTime, toLocalDateTime } from "@/lib/utils/localDate";
|
|
|
|
/**
|
|
* 자동생성 값 생성 유틸리티
|
|
*/
|
|
export class AutoGenerationUtils {
|
|
/**
|
|
* UUID 생성
|
|
*/
|
|
static generateUUID(): string {
|
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
const r = (Math.random() * 16) | 0;
|
|
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
return v.toString(16);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 랜덤 문자열 생성
|
|
*/
|
|
static generateRandomString(length: number = 8, prefix?: string, suffix?: string): string {
|
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
let result = "";
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
|
|
return `${prefix || ""}${result}${suffix || ""}`;
|
|
}
|
|
|
|
/**
|
|
* 랜덤 숫자 생성
|
|
*/
|
|
static generateRandomNumber(length: number = 6, prefix?: string, suffix?: string): string {
|
|
const min = Math.pow(10, length - 1);
|
|
const max = Math.pow(10, length) - 1;
|
|
const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
|
|
return `${prefix || ""}${randomNum}${suffix || ""}`;
|
|
}
|
|
|
|
/**
|
|
* 현재 시간 생성
|
|
*/
|
|
static generateCurrentTime(format?: string): string {
|
|
console.log("🕒 generateCurrentTime 호출됨:", { format });
|
|
const now = new Date();
|
|
console.log("🕒 현재 시간 객체:", now);
|
|
|
|
let result: string;
|
|
switch (format) {
|
|
case "date":
|
|
result = toLocalDate(now);
|
|
break;
|
|
case "time":
|
|
result = toLocalTime(now);
|
|
break;
|
|
case "datetime":
|
|
result = toLocalDateTime(now);
|
|
break;
|
|
case "timestamp":
|
|
result = now.getTime().toString();
|
|
break;
|
|
default:
|
|
result = toLocalDateTime(now);
|
|
break;
|
|
}
|
|
|
|
console.log("🕒 generateCurrentTime 결과:", { format, result });
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 시퀀스 번호 생성 (메모리 기반, 실제로는 DB 시퀀스 사용 권장)
|
|
*/
|
|
private static sequenceCounters: Map<string, number> = new Map();
|
|
|
|
static generateSequence(key: string = "default", startValue: number = 1, prefix?: string, suffix?: string): string {
|
|
if (!this.sequenceCounters.has(key)) {
|
|
this.sequenceCounters.set(key, startValue);
|
|
}
|
|
|
|
const current = this.sequenceCounters.get(key)!;
|
|
this.sequenceCounters.set(key, current + 1);
|
|
|
|
return `${prefix || ""}${current}${suffix || ""}`;
|
|
}
|
|
|
|
/**
|
|
* 현재 사용자 ID 가져오기 (실제로는 인증 컨텍스트에서 가져와야 함)
|
|
*/
|
|
static getCurrentUserId(): string {
|
|
// JWT 토큰에서 사용자 정보 추출 시도
|
|
if (typeof window !== "undefined") {
|
|
const token = localStorage.getItem("authToken");
|
|
if (token) {
|
|
try {
|
|
const payload = JSON.parse(atob(token.split(".")[1]));
|
|
return payload.user_id || payload.id || "unknown";
|
|
} catch {
|
|
// JWT 파싱 실패 시 fallback
|
|
}
|
|
}
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
/**
|
|
* 회사 코드 가져오기
|
|
*/
|
|
static getCompanyCode(): string {
|
|
// TODO: 실제 회사 정보와 연동
|
|
if (typeof window !== "undefined") {
|
|
const companyInfo = localStorage.getItem("companyInfo");
|
|
if (companyInfo) {
|
|
try {
|
|
const parsed = JSON.parse(companyInfo);
|
|
return parsed.company_code || parsed.code || "COMPANY";
|
|
} catch {
|
|
return "COMPANY";
|
|
}
|
|
}
|
|
}
|
|
return "COMPANY";
|
|
}
|
|
|
|
/**
|
|
* 부서 코드 가져오기
|
|
*/
|
|
static getDepartmentCode(): string {
|
|
// TODO: 실제 부서 정보와 연동
|
|
if (typeof window !== "undefined") {
|
|
const userInfo = localStorage.getItem("userInfo");
|
|
if (userInfo) {
|
|
try {
|
|
const parsed = JSON.parse(userInfo);
|
|
return parsed.departmentCode || parsed.deptCode || "DEPT";
|
|
} catch {
|
|
return "DEPT";
|
|
}
|
|
}
|
|
}
|
|
return "DEPT";
|
|
}
|
|
|
|
/**
|
|
* 채번 규칙 API 호출하여 코드 생성
|
|
*/
|
|
static async generateNumberingRuleCode(ruleId: string, formData?: Record<string, any>): Promise<string | null> {
|
|
try {
|
|
const { apiClient } = await import("@/lib/api/client");
|
|
const response = await apiClient.post(`/numbering-rules/${ruleId}/allocate`, {
|
|
formData: formData || {},
|
|
});
|
|
|
|
if (response.data.success && response.data.data) {
|
|
// API 응답에서 생성된 코드 추출
|
|
const generatedCode = response.data.data.generatedCode || response.data.data;
|
|
console.log("채번 규칙 코드 생성 성공:", generatedCode);
|
|
return generatedCode;
|
|
}
|
|
console.error("채번 규칙 코드 생성 실패:", response.data.message);
|
|
return null;
|
|
} catch (error) {
|
|
console.error("채번 규칙 API 호출 실패:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 자동생성 값 생성 메인 함수 (비동기)
|
|
*/
|
|
static async generateValue(config: AutoGenerationConfig, columnName?: string, formData?: Record<string, any>): Promise<string | null> {
|
|
console.log("AutoGenerationUtils.generateValue 호출:", {
|
|
config,
|
|
columnName,
|
|
enabled: config.enabled,
|
|
type: config.type,
|
|
});
|
|
|
|
if (!config.enabled || config.type === "none") {
|
|
console.log("AutoGenerationUtils.generateValue 스킵:", {
|
|
enabled: config.enabled,
|
|
type: config.type,
|
|
});
|
|
return null;
|
|
}
|
|
|
|
const options = config.options || {};
|
|
|
|
switch (config.type) {
|
|
case "uuid":
|
|
return this.generateUUID();
|
|
|
|
case "current_user":
|
|
return this.getCurrentUserId();
|
|
|
|
case "current_time":
|
|
console.log("AutoGenerationUtils.generateCurrentTime 호출:", {
|
|
format: options.format,
|
|
options,
|
|
});
|
|
const timeValue = this.generateCurrentTime(options.format);
|
|
console.log("AutoGenerationUtils.generateCurrentTime 결과:", timeValue);
|
|
return timeValue;
|
|
|
|
case "sequence":
|
|
return this.generateSequence(
|
|
columnName || "default",
|
|
(options as any).startValue ?? options.start_value ?? 1,
|
|
options.prefix,
|
|
options.suffix,
|
|
);
|
|
|
|
case "numbering_rule":
|
|
// 채번 규칙 ID가 있으면 API 호출
|
|
const numberingRuleId =
|
|
(options as any).numberingRuleId ?? options.numbering_rule_id;
|
|
if (numberingRuleId) {
|
|
return await this.generateNumberingRuleCode(numberingRuleId, formData);
|
|
}
|
|
console.warn("numbering_rule 타입인데 numberingRuleId가 없습니다");
|
|
return null;
|
|
|
|
case "random_string":
|
|
return this.generateRandomString(options.length || 8, options.prefix, options.suffix);
|
|
|
|
case "random_number":
|
|
return this.generateRandomNumber(options.length || 6, options.prefix, options.suffix);
|
|
|
|
case "company_code":
|
|
return this.getCompanyCode();
|
|
|
|
case "department":
|
|
return this.getDepartmentCode();
|
|
|
|
default:
|
|
console.warn(`Unknown auto generation type: ${config.type}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 자동생성 타입별 설명 가져오기
|
|
*/
|
|
static getTypeDescription(type: AutoGenerationType): string {
|
|
const descriptions: Record<string, string> = {
|
|
uuid: "고유 식별자 (UUID) 생성",
|
|
current_user: "현재 로그인한 사용자 ID",
|
|
current_time: "현재 날짜/시간",
|
|
sequence: "순차적 번호 생성",
|
|
numbering_rule: "채번 규칙 기반 코드 생성",
|
|
random_string: "랜덤 문자열 생성",
|
|
random_number: "랜덤 숫자 생성",
|
|
company_code: "현재 회사 코드",
|
|
department: "현재 부서 코드",
|
|
none: "자동생성 없음",
|
|
};
|
|
|
|
return descriptions[type] || "알 수 없는 타입";
|
|
}
|
|
|
|
/**
|
|
* 자동생성 미리보기 값 생성
|
|
*/
|
|
static generatePreviewValue(config: AutoGenerationConfig): string {
|
|
if (!config.enabled || config.type === "none") {
|
|
return "";
|
|
}
|
|
|
|
// 미리보기용으로 실제 값 대신 예시 값 반환
|
|
const options = config.options || {};
|
|
|
|
switch (config.type) {
|
|
case "uuid":
|
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
|
|
|
|
case "current_user":
|
|
return "user123";
|
|
|
|
case "current_time":
|
|
return this.generateCurrentTime(options.format);
|
|
|
|
case "sequence":
|
|
return `${options.prefix || ""}1${options.suffix || ""}`;
|
|
|
|
case "numbering_rule":
|
|
return "CODE-20251104-001"; // 채번 규칙 미리보기
|
|
|
|
case "random_string":
|
|
return `${options.prefix || ""}ABC123${options.suffix || ""}`;
|
|
|
|
case "random_number":
|
|
return `${options.prefix || ""}123456${options.suffix || ""}`;
|
|
|
|
case "company_code":
|
|
return "COMPANY";
|
|
|
|
case "department":
|
|
return "DEPT";
|
|
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
}
|
|
|
|
// 개발 모드에서 전역 함수로 등록 (테스트용)
|
|
if (typeof window !== "undefined") {
|
|
(window as any).__AUTO_GENERATION_TEST__ = {
|
|
generateCurrentTime: AutoGenerationUtils.generateCurrentTime,
|
|
generateValue: AutoGenerationUtils.generateValue,
|
|
test: () => {
|
|
console.log("🧪 자동생성 테스트 시작");
|
|
|
|
// 현재 시간 테스트
|
|
const dateResult = AutoGenerationUtils.generateCurrentTime("date");
|
|
console.log("📅 날짜 생성 결과:", dateResult);
|
|
|
|
// 자동생성 설정 테스트
|
|
const config = {
|
|
enabled: true,
|
|
type: "current_time" as any,
|
|
options: { format: "date" },
|
|
};
|
|
|
|
const autoResult = AutoGenerationUtils.generateValue(config);
|
|
console.log("🎯 자동생성 결과:", autoResult);
|
|
|
|
return { dateResult, autoResult };
|
|
},
|
|
};
|
|
}
|