docs: [종합정비] 구조 재편 — Phase 0+2+4 통합
- Phase 0: INDEX.md 전면 재작성, CLAUDE.md→INDEX.md 통합 삭제 - Phase 0: front/→guides/ 이관(5개 파일), changes/ D7 포맷 통일(3개) - Phase 0: guides/ai-config-설정.md→ai-config-settings.md D3 통일 - Phase 2: architecture/+specs/→system/ 이관(6개 이동, 4개 폐기) - Phase 2: 13개 파일 경로 참조 수정 (specs/→system/, architecture/→system/) - Phase 4: 7개 파일 11개 교차참조 깨진 링크 수정 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -380,7 +380,7 @@ class ExampleModel extends Model
|
||||
|
||||
### SAM 전체 문서
|
||||
```
|
||||
docs/specs/ # 시스템 스펙
|
||||
docs/system/ # 시스템 현황
|
||||
docs/reference/ # 레퍼런스
|
||||
docs/guides/ # 가이드 (이 문서 포함)
|
||||
```
|
||||
|
||||
353
guides/auto-login-guide.md
Normal file
353
guides/auto-login-guide.md
Normal file
@@ -0,0 +1,353 @@
|
||||
# MNG → DEV 자동 로그인 기능 (React 구현 가이드)
|
||||
|
||||
## 개요
|
||||
|
||||
MNG 관리자가 사용자 목록에서 "DEV 접속" 버튼을 클릭하면, 해당 사용자로 자동 로그인되어 DEV 사이트로 이동하는 기능.
|
||||
|
||||
## 아키텍처
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ MNG │ │ API │ │ React │
|
||||
│ (관리자) │ │ (토큰검증) │ │ (프론트) │
|
||||
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||||
│ │ │
|
||||
1. DEV접속 클릭 │ │
|
||||
│ │ │
|
||||
2. 토큰생성 ─────────────┼─── DB 저장 ───────┤
|
||||
│ │ (login_tokens) │
|
||||
3. URL반환 │ │
|
||||
│ │ │
|
||||
4. 새창열기 ─────────────┼───────────────────┼─→ /auto-login?token=xxx
|
||||
│ │ │
|
||||
│ 5. 토큰검증 ←────────────┤
|
||||
│ │ │
|
||||
│ 6. access_token 발급 ────┤
|
||||
│ │ │
|
||||
│ 7. 토큰삭제 (1회용) │
|
||||
│ │ │
|
||||
│ │ 8. 로그인 완료 → 대시보드
|
||||
```
|
||||
|
||||
## 환경별 URL
|
||||
|
||||
| 환경 | MNG | DEV |
|
||||
|------|-----|-----|
|
||||
| 로컬 | https://mng.sam.kr | https://dev.sam.kr |
|
||||
| 개발 | https://admin.codebridge-x.com | https://dev.codebridge-x.com |
|
||||
|
||||
---
|
||||
|
||||
## React 구현 작업
|
||||
|
||||
### 1. 신규 파일: `/auto-login` 페이지
|
||||
|
||||
**경로:** `src/app/[locale]/auto-login/page.tsx`
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { transformApiMenusToMenuItems } from "@/lib/utils/menuTransform";
|
||||
|
||||
export default function AutoLoginPage() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [status, setStatus] = useState<"loading" | "success" | "error">("loading");
|
||||
const [message, setMessage] = useState("자동 로그인 처리 중...");
|
||||
|
||||
useEffect(() => {
|
||||
const token = searchParams.get("token");
|
||||
|
||||
if (!token) {
|
||||
setStatus("error");
|
||||
setMessage("유효하지 않은 접근입니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
const performAutoLogin = async () => {
|
||||
try {
|
||||
// 1. 기존 세션 클리어 (기존 로그인 사용자 로그아웃)
|
||||
localStorage.removeItem("user");
|
||||
|
||||
// 기존 쿠키도 클리어하기 위해 logout API 호출 (선택사항)
|
||||
try {
|
||||
await fetch("/api/auth/logout", { method: "POST" });
|
||||
} catch {
|
||||
// 로그아웃 실패해도 계속 진행
|
||||
}
|
||||
|
||||
// 2. 토큰 로그인 API 호출
|
||||
const response = await fetch("/api/auth/token-login", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ token }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.error || "토큰이 만료되었거나 유효하지 않습니다.");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// 3. 사용자 정보 저장 (기존 로그인과 동일한 형식)
|
||||
const transformedMenus = transformApiMenusToMenuItems(data.menus || []);
|
||||
|
||||
const userData = {
|
||||
name: data.user?.name,
|
||||
position: data.roles?.[0]?.description || "사용자",
|
||||
userId: data.user?.user_id,
|
||||
menu: transformedMenus,
|
||||
roles: data.roles || [],
|
||||
tenant: data.tenant || {},
|
||||
};
|
||||
|
||||
localStorage.setItem("user", JSON.stringify(userData));
|
||||
|
||||
setStatus("success");
|
||||
setMessage("로그인 성공! 대시보드로 이동합니다...");
|
||||
|
||||
// 4. 대시보드로 리다이렉트
|
||||
setTimeout(() => router.push("/dashboard"), 500);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Auto login failed:", error);
|
||||
setStatus("error");
|
||||
setMessage(error instanceof Error ? error.message : "로그인에 실패했습니다.");
|
||||
}
|
||||
};
|
||||
|
||||
performAutoLogin();
|
||||
}, [searchParams, router]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center">
|
||||
<div className="text-center p-8">
|
||||
{status === "loading" && (
|
||||
<div className="animate-spin h-12 w-12 border-4 border-primary border-t-transparent rounded-full mx-auto mb-4" />
|
||||
)}
|
||||
{status === "success" && (
|
||||
<div className="h-12 w-12 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
{status === "error" && (
|
||||
<div className="h-12 w-12 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
<p className={`text-lg ${status === "error" ? "text-destructive" : "text-muted-foreground"}`}>
|
||||
{message}
|
||||
</p>
|
||||
{status === "error" && (
|
||||
<button
|
||||
onClick={() => router.push("/login")}
|
||||
className="mt-4 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90"
|
||||
>
|
||||
로그인 페이지로 이동
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. 신규 파일: 토큰 로그인 API Route
|
||||
|
||||
**경로:** `src/app/api/auth/token-login/route.ts`
|
||||
|
||||
```ts
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
/**
|
||||
* 토큰 자동 로그인 API
|
||||
*
|
||||
* MNG 관리자가 생성한 One-Time Token으로 자동 로그인 처리
|
||||
*
|
||||
* 흐름:
|
||||
* 1. token 파라미터 검증
|
||||
* 2. PHP API /v1/auth/token-login 호출
|
||||
* 3. access_token을 HttpOnly 쿠키로 저장
|
||||
* 4. 사용자 정보 반환
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { token } = await request.json();
|
||||
|
||||
if (!token) {
|
||||
return NextResponse.json(
|
||||
{ error: "Token is required" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// PHP 백엔드 호출
|
||||
const backendResponse = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/auth/token-login`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"X-API-KEY": process.env.NEXT_PUBLIC_API_KEY || "",
|
||||
},
|
||||
body: JSON.stringify({ token }),
|
||||
}
|
||||
);
|
||||
|
||||
if (!backendResponse.ok) {
|
||||
const errorText = await backendResponse.text();
|
||||
console.error("Token login backend error:", errorText);
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Invalid or expired token" },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
const data = await backendResponse.json();
|
||||
|
||||
// HttpOnly 쿠키 설정 (기존 login/route.ts와 동일)
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
const accessTokenCookie = [
|
||||
`access_token=${data.access_token}`,
|
||||
"HttpOnly",
|
||||
...(isProduction ? ["Secure"] : []),
|
||||
"SameSite=Lax",
|
||||
"Path=/",
|
||||
`Max-Age=${data.expires_in || 7200}`,
|
||||
].join("; ");
|
||||
|
||||
const refreshTokenCookie = [
|
||||
`refresh_token=${data.refresh_token}`,
|
||||
"HttpOnly",
|
||||
...(isProduction ? ["Secure"] : []),
|
||||
"SameSite=Lax",
|
||||
"Path=/",
|
||||
"Max-Age=604800",
|
||||
].join("; ");
|
||||
|
||||
console.log("✅ Token login successful - tokens stored in HttpOnly cookies");
|
||||
|
||||
const response = NextResponse.json({
|
||||
message: data.message,
|
||||
user: data.user,
|
||||
tenant: data.tenant,
|
||||
menus: data.menus,
|
||||
roles: data.roles,
|
||||
expires_in: data.expires_in,
|
||||
expires_at: data.expires_at,
|
||||
});
|
||||
|
||||
response.headers.append("Set-Cookie", accessTokenCookie);
|
||||
response.headers.append("Set-Cookie", refreshTokenCookie);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error("Token login error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Internal server error" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 수정 파일: auth-config.ts
|
||||
|
||||
**경로:** `src/lib/api/auth/auth-config.ts`
|
||||
|
||||
```ts
|
||||
// guestOnlyRoutes 배열에 /auto-login 추가
|
||||
guestOnlyRoutes: [
|
||||
'/login',
|
||||
'/forgot-password',
|
||||
'/auto-login', // 추가
|
||||
],
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 수정 파일: middleware.ts (확인 필요)
|
||||
|
||||
`/auto-login` 경로가 인증 없이 접근 가능한지 확인 필요.
|
||||
`guestOnlyRoutes`에 추가되면 자동으로 처리될 수 있음.
|
||||
|
||||
---
|
||||
|
||||
## API 엔드포인트 (백엔드)
|
||||
|
||||
### POST /api/v1/auth/token-login
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"token": "abc123..." // 64자 랜덤 문자열
|
||||
}
|
||||
```
|
||||
|
||||
**Response (성공):**
|
||||
```json
|
||||
{
|
||||
"message": "로그인 성공",
|
||||
"access_token": "1|xxx...",
|
||||
"refresh_token": "2|yyy...",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 7200,
|
||||
"expires_at": "2025-12-20 15:00:00",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"user_id": "testuser",
|
||||
"name": "테스트 사용자",
|
||||
"email": "test@example.com"
|
||||
},
|
||||
"tenant": { ... },
|
||||
"menus": [ ... ],
|
||||
"roles": [ ... ]
|
||||
}
|
||||
```
|
||||
|
||||
**Response (실패):**
|
||||
```json
|
||||
{
|
||||
"error": "Invalid or expired token"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 보안 고려사항
|
||||
|
||||
1. **토큰 1회 사용**: 사용 후 즉시 삭제
|
||||
2. **토큰 만료**: 5분 (생성 후)
|
||||
3. **HTTPS 필수**: 토큰이 URL에 노출되므로
|
||||
4. **관리자 권한**: MNG 로그인한 관리자만 토큰 생성 가능
|
||||
|
||||
---
|
||||
|
||||
## 테스트 시나리오
|
||||
|
||||
1. MNG에서 사용자 목록 → "DEV 접속" 버튼 클릭
|
||||
2. 새 창에서 DEV 사이트 열림
|
||||
3. 자동 로그인 처리 (로딩 표시)
|
||||
4. 성공 시 대시보드로 이동
|
||||
5. 실패 시 에러 메시지 + 로그인 페이지 이동 버튼
|
||||
|
||||
---
|
||||
|
||||
## 작성일
|
||||
|
||||
2025-12-20
|
||||
1442
guides/erp-api-detail.md
Normal file
1442
guides/erp-api-detail.md
Normal file
File diff suppressed because it is too large
Load Diff
396
guides/erp-api-list.md
Normal file
396
guides/erp-api-list.md
Normal file
@@ -0,0 +1,396 @@
|
||||
# ERP API 목록 (List vs Detail 구분)
|
||||
|
||||
> **작성일**: 2025-12-19
|
||||
> **기준 문서**: [erp-api-development-plan.md](../plans/erp-api-development-plan.md)
|
||||
> **Swagger UI**: http://sam.kr/api-docs/index.html
|
||||
|
||||
---
|
||||
|
||||
## 📊 API 유형 분류
|
||||
|
||||
| 유형 | 설명 | HTTP Method |
|
||||
|------|------|-------------|
|
||||
| **LIST** | 목록 조회 (페이지네이션) | GET |
|
||||
| **DETAIL** | 단건 조회 | GET |
|
||||
| **CREATE** | 생성 | POST |
|
||||
| **UPDATE** | 수정 | PUT/PATCH |
|
||||
| **DELETE** | 삭제 | DELETE |
|
||||
| **ACTION** | 상태 변경/특수 액션 | POST/PATCH |
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Phase 1: 확장 개발 API
|
||||
|
||||
### 1. 휴가 관리 (Leaves) - 11개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/leaves` | 휴가 목록 조회 |
|
||||
| DETAIL | GET | `/v1/leaves/{id}` | 휴가 상세 조회 |
|
||||
| CREATE | POST | `/v1/leaves` | 휴가 신청 |
|
||||
| UPDATE | PATCH | `/v1/leaves/{id}` | 휴가 수정 |
|
||||
| DELETE | DELETE | `/v1/leaves/{id}` | 휴가 삭제 |
|
||||
| ACTION | POST | `/v1/leaves/{id}/approve` | 휴가 승인 |
|
||||
| ACTION | POST | `/v1/leaves/{id}/reject` | 휴가 반려 |
|
||||
| ACTION | POST | `/v1/leaves/{id}/cancel` | 휴가 취소 |
|
||||
| DETAIL | GET | `/v1/leaves/balance` | 내 잔여휴가 조회 |
|
||||
| DETAIL | GET | `/v1/leaves/balance/{userId}` | 특정 사용자 잔여휴가 |
|
||||
| UPDATE | PUT | `/v1/leaves/balance` | 잔여휴가 설정 |
|
||||
|
||||
---
|
||||
|
||||
### 2. 근무/출퇴근 설정 (Work Settings) - 10개 API
|
||||
|
||||
#### 2.1 근무 설정 (2개)
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| DETAIL | GET | `/v1/settings/work` | 근무 설정 조회 |
|
||||
| UPDATE | PUT | `/v1/settings/work` | 근무 설정 수정 |
|
||||
|
||||
#### 2.2 출퇴근 설정 (2개)
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| DETAIL | GET | `/v1/settings/attendance` | 출퇴근 설정 조회 |
|
||||
| UPDATE | PUT | `/v1/settings/attendance` | 출퇴근 설정 수정 |
|
||||
|
||||
#### 2.3 현장 관리 (Sites) - 6개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/sites` | 현장 목록 조회 |
|
||||
| LIST | GET | `/v1/sites/active` | 활성 현장 목록 (셀렉트박스용) |
|
||||
| DETAIL | GET | `/v1/sites/{id}` | 현장 상세 조회 |
|
||||
| CREATE | POST | `/v1/sites` | 현장 등록 |
|
||||
| UPDATE | PUT | `/v1/sites/{id}` | 현장 수정 |
|
||||
| DELETE | DELETE | `/v1/sites/{id}` | 현장 삭제 |
|
||||
|
||||
---
|
||||
|
||||
### 3. 카드/계좌 관리 - 15개 API
|
||||
|
||||
#### 3.1 카드 관리 (Cards) - 7개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/cards` | 카드 목록 조회 |
|
||||
| LIST | GET | `/v1/cards/active` | 활성 카드 목록 (셀렉트박스용) |
|
||||
| DETAIL | GET | `/v1/cards/{id}` | 카드 상세 조회 |
|
||||
| CREATE | POST | `/v1/cards` | 카드 등록 |
|
||||
| UPDATE | PUT | `/v1/cards/{id}` | 카드 수정 |
|
||||
| DELETE | DELETE | `/v1/cards/{id}` | 카드 삭제 |
|
||||
| ACTION | PATCH | `/v1/cards/{id}/toggle` | 카드 사용/정지 토글 |
|
||||
|
||||
#### 3.2 계좌 관리 (Bank Accounts) - 8개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/bank-accounts` | 계좌 목록 조회 |
|
||||
| LIST | GET | `/v1/bank-accounts/active` | 활성 계좌 목록 (셀렉트박스용) |
|
||||
| DETAIL | GET | `/v1/bank-accounts/{id}` | 계좌 상세 조회 |
|
||||
| CREATE | POST | `/v1/bank-accounts` | 계좌 등록 |
|
||||
| UPDATE | PUT | `/v1/bank-accounts/{id}` | 계좌 수정 |
|
||||
| DELETE | DELETE | `/v1/bank-accounts/{id}` | 계좌 삭제 |
|
||||
| ACTION | PATCH | `/v1/bank-accounts/{id}/toggle` | 계좌 사용/정지 토글 |
|
||||
| ACTION | PATCH | `/v1/bank-accounts/{id}/set-primary` | 대표계좌 설정 |
|
||||
|
||||
---
|
||||
|
||||
### 4. 입금/출금 관리 - 12개 API
|
||||
|
||||
#### 4.1 입금 관리 (Deposits) - 6개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/deposits` | 입금 목록 조회 |
|
||||
| LIST | GET | `/v1/deposits/summary` | 입금 요약 (집계) |
|
||||
| DETAIL | GET | `/v1/deposits/{id}` | 입금 상세 조회 |
|
||||
| CREATE | POST | `/v1/deposits` | 입금 등록 |
|
||||
| UPDATE | PUT | `/v1/deposits/{id}` | 입금 수정 |
|
||||
| DELETE | DELETE | `/v1/deposits/{id}` | 입금 삭제 |
|
||||
|
||||
#### 4.2 출금 관리 (Withdrawals) - 6개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/withdrawals` | 출금 목록 조회 |
|
||||
| LIST | GET | `/v1/withdrawals/summary` | 출금 요약 (집계) |
|
||||
| DETAIL | GET | `/v1/withdrawals/{id}` | 출금 상세 조회 |
|
||||
| CREATE | POST | `/v1/withdrawals` | 출금 등록 |
|
||||
| UPDATE | PUT | `/v1/withdrawals/{id}` | 출금 수정 |
|
||||
| DELETE | DELETE | `/v1/withdrawals/{id}` | 출금 삭제 |
|
||||
|
||||
---
|
||||
|
||||
### 5. 매출/매입 관리 - 17개 API
|
||||
|
||||
#### 5.1 매출 관리 (Sales) - 10개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/sales` | 매출 목록 조회 |
|
||||
| LIST | GET | `/v1/sales/summary` | 매출 요약 (집계) |
|
||||
| DETAIL | GET | `/v1/sales/{id}` | 매출 상세 조회 |
|
||||
| CREATE | POST | `/v1/sales` | 매출 등록 |
|
||||
| UPDATE | PUT | `/v1/sales/{id}` | 매출 수정 |
|
||||
| DELETE | DELETE | `/v1/sales/{id}` | 매출 삭제 |
|
||||
| ACTION | POST | `/v1/sales/{id}/confirm` | 매출 확정 |
|
||||
| DETAIL | GET | `/v1/sales/{id}/statement` | 거래명세서 조회 |
|
||||
| ACTION | POST | `/v1/sales/{id}/statement/issue` | 거래명세서 발행 |
|
||||
| ACTION | POST | `/v1/sales/{id}/statement/send` | 거래명세서 이메일 발송 |
|
||||
|
||||
#### 5.2 매입 관리 (Purchases) - 7개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/purchases` | 매입 목록 조회 |
|
||||
| LIST | GET | `/v1/purchases/summary` | 매입 요약 (집계) |
|
||||
| DETAIL | GET | `/v1/purchases/{id}` | 매입 상세 조회 |
|
||||
| CREATE | POST | `/v1/purchases` | 매입 등록 |
|
||||
| UPDATE | PUT | `/v1/purchases/{id}` | 매입 수정 |
|
||||
| DELETE | DELETE | `/v1/purchases/{id}` | 매입 삭제 |
|
||||
| ACTION | POST | `/v1/purchases/{id}/confirm` | 매입 확정 |
|
||||
|
||||
---
|
||||
|
||||
### 6. 보고서 (Reports) - 4개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| DETAIL | GET | `/v1/reports/daily` | 일일 일보 조회 |
|
||||
| ACTION | GET | `/v1/reports/daily/export` | 일일 일보 엑셀 다운로드 |
|
||||
| DETAIL | GET | `/v1/reports/expense-estimate` | 지출 예상 내역서 조회 |
|
||||
| ACTION | GET | `/v1/reports/expense-estimate/export` | 지출 예상 내역서 엑셀 다운로드 |
|
||||
|
||||
---
|
||||
|
||||
## 👤 Phase 5: 사용자/계정 관리 API
|
||||
|
||||
### 16. 사용자 초대 (User Invitations) - 5개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/users/invitations` | 초대 목록 조회 |
|
||||
| CREATE | POST | `/v1/users/invite` | 사용자 초대 발송 |
|
||||
| ACTION | POST | `/v1/users/invitations/{token}/accept` | 초대 수락 |
|
||||
| DELETE | DELETE | `/v1/users/invitations/{id}` | 초대 취소 |
|
||||
| ACTION | POST | `/v1/users/invitations/{id}/resend` | 초대 재발송 |
|
||||
|
||||
---
|
||||
|
||||
### 17. 알림 설정 (Notification Settings) - 3개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/users/me/notification-settings` | 알림 설정 조회 |
|
||||
| UPDATE | PUT | `/v1/users/me/notification-settings` | 알림 설정 수정 (단일) |
|
||||
| ACTION | PUT | `/v1/users/me/notification-settings/bulk` | 알림 설정 일괄 저장 |
|
||||
|
||||
---
|
||||
|
||||
### 18. 계정 관리 (Account) - 4개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| ACTION | POST | `/v1/account/withdraw` | 회원 탈퇴 (SAM 완전 탈퇴) |
|
||||
| ACTION | POST | `/v1/account/suspend` | 사용 중지 (현재 테넌트에서만 탈퇴) |
|
||||
| DETAIL | GET | `/v1/account/agreements` | 약관 동의 정보 조회 |
|
||||
| UPDATE | PUT | `/v1/account/agreements` | 약관 동의 정보 수정 |
|
||||
|
||||
---
|
||||
|
||||
## 🔨 Phase 2: 핵심 신규 개발 API
|
||||
|
||||
### 7. 전자결재 모듈 - 26개 API
|
||||
|
||||
#### 7.1 결재 양식 (Approval Forms) - 6개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/approval-forms` | 결재 양식 목록 |
|
||||
| LIST | GET | `/v1/approval-forms/active` | 활성 결재 양식 (셀렉트박스용) |
|
||||
| DETAIL | GET | `/v1/approval-forms/{id}` | 결재 양식 상세 |
|
||||
| CREATE | POST | `/v1/approval-forms` | 결재 양식 등록 |
|
||||
| UPDATE | PATCH | `/v1/approval-forms/{id}` | 결재 양식 수정 |
|
||||
| DELETE | DELETE | `/v1/approval-forms/{id}` | 결재 양식 삭제 |
|
||||
|
||||
#### 7.2 결재선 템플릿 (Approval Lines) - 5개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/approval-lines` | 결재선 목록 |
|
||||
| DETAIL | GET | `/v1/approval-lines/{id}` | 결재선 상세 |
|
||||
| CREATE | POST | `/v1/approval-lines` | 결재선 등록 |
|
||||
| UPDATE | PATCH | `/v1/approval-lines/{id}` | 결재선 수정 |
|
||||
| DELETE | DELETE | `/v1/approval-lines/{id}` | 결재선 삭제 |
|
||||
|
||||
#### 7.3 결재 문서 (Approvals) - 15개
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/approvals/drafts` | 기안함 (내가 작성한 문서) |
|
||||
| LIST | GET | `/v1/approvals/drafts/summary` | 기안함 요약 |
|
||||
| LIST | GET | `/v1/approvals/inbox` | 결재함 (결재 대기 문서) |
|
||||
| LIST | GET | `/v1/approvals/inbox/summary` | 결재함 요약 |
|
||||
| LIST | GET | `/v1/approvals/reference` | 참조함 (참조 문서) |
|
||||
| DETAIL | GET | `/v1/approvals/{id}` | 결재 문서 상세 |
|
||||
| CREATE | POST | `/v1/approvals` | 결재 문서 작성 (임시저장) |
|
||||
| UPDATE | PATCH | `/v1/approvals/{id}` | 결재 문서 수정 |
|
||||
| DELETE | DELETE | `/v1/approvals/{id}` | 결재 문서 삭제 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/submit` | 결재 상신 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/approve` | 결재 승인 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/reject` | 결재 반려 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/cancel` | 결재 취소/회수 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/read` | 참조 열람 처리 |
|
||||
| ACTION | POST | `/v1/approvals/{id}/unread` | 참조 미열람 처리 |
|
||||
|
||||
---
|
||||
|
||||
### 8. 급여 관리 (Payrolls) - 13개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/payrolls` | 급여 목록 조회 |
|
||||
| LIST | GET | `/v1/payrolls/summary` | 급여 현황 요약 |
|
||||
| DETAIL | GET | `/v1/payrolls/{id}` | 급여 상세 조회 |
|
||||
| DETAIL | GET | `/v1/payrolls/{id}/payslip` | 급여명세서 조회 |
|
||||
| CREATE | POST | `/v1/payrolls` | 급여 등록 |
|
||||
| UPDATE | PUT | `/v1/payrolls/{id}` | 급여 수정 |
|
||||
| DELETE | DELETE | `/v1/payrolls/{id}` | 급여 삭제 |
|
||||
| ACTION | POST | `/v1/payrolls/calculate` | 급여 일괄 계산 |
|
||||
| ACTION | POST | `/v1/payrolls/bulk-confirm` | 급여 일괄 확정 |
|
||||
| ACTION | POST | `/v1/payrolls/{id}/confirm` | 급여 확정 |
|
||||
| ACTION | POST | `/v1/payrolls/{id}/pay` | 급여 지급 처리 |
|
||||
| DETAIL | GET | `/v1/settings/payroll` | 급여 설정 조회 |
|
||||
| UPDATE | PUT | `/v1/settings/payroll` | 급여 설정 수정 |
|
||||
|
||||
---
|
||||
|
||||
### 9. 대시보드 (Dashboard) - 3개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| DETAIL | GET | `/v1/dashboard/summary` | 대시보드 요약 데이터 |
|
||||
| DETAIL | GET | `/v1/dashboard/charts` | 차트 데이터 |
|
||||
| DETAIL | GET | `/v1/dashboard/approvals` | 결재 현황 |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Phase 3: 추가 기능 API
|
||||
|
||||
### 10. AI 리포트 (AI Reports) - 4개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/reports/ai` | AI 리포트 목록 |
|
||||
| DETAIL | GET | `/v1/reports/ai/{id}` | AI 리포트 상세 |
|
||||
| ACTION | POST | `/v1/reports/ai/generate` | AI 리포트 생성 |
|
||||
| DELETE | DELETE | `/v1/reports/ai/{id}` | AI 리포트 삭제 |
|
||||
|
||||
---
|
||||
|
||||
### 11. 가지급금 관리 (Loans) - 9개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/loans` | 가지급금 목록 조회 |
|
||||
| LIST | GET | `/v1/loans/summary` | 가지급금 요약 |
|
||||
| DETAIL | GET | `/v1/loans/{id}` | 가지급금 상세 조회 |
|
||||
| DETAIL | GET | `/v1/loans/interest-report/{year}` | 연도별 인정이자 리포트 |
|
||||
| CREATE | POST | `/v1/loans` | 가지급금 등록 |
|
||||
| UPDATE | PUT | `/v1/loans/{id}` | 가지급금 수정 |
|
||||
| DELETE | DELETE | `/v1/loans/{id}` | 가지급금 삭제 |
|
||||
| ACTION | POST | `/v1/loans/calculate-interest` | 인정이자 계산 |
|
||||
| ACTION | POST | `/v1/loans/{id}/settle` | 가지급금 정산 |
|
||||
|
||||
---
|
||||
|
||||
### 12. 바로빌 연동 (세금계산서) - 12개 API
|
||||
|
||||
#### 12.1 바로빌 설정 (3개)
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| DETAIL | GET | `/v1/barobill-settings` | 바로빌 설정 조회 |
|
||||
| UPDATE | PUT | `/v1/barobill-settings` | 바로빌 설정 저장 |
|
||||
| ACTION | POST | `/v1/barobill-settings/test-connection` | 연동 테스트 |
|
||||
|
||||
#### 12.2 세금계산서 (9개)
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/tax-invoices` | 세금계산서 목록 |
|
||||
| LIST | GET | `/v1/tax-invoices/summary` | 세금계산서 요약 통계 |
|
||||
| DETAIL | GET | `/v1/tax-invoices/{id}` | 세금계산서 상세 |
|
||||
| DETAIL | GET | `/v1/tax-invoices/{id}/check-status` | 국세청 전송 상태 조회 |
|
||||
| CREATE | POST | `/v1/tax-invoices` | 세금계산서 생성 |
|
||||
| UPDATE | PUT | `/v1/tax-invoices/{id}` | 세금계산서 수정 |
|
||||
| DELETE | DELETE | `/v1/tax-invoices/{id}` | 세금계산서 삭제 |
|
||||
| ACTION | POST | `/v1/tax-invoices/{id}/issue` | 세금계산서 발행 |
|
||||
| ACTION | POST | `/v1/tax-invoices/{id}/cancel` | 세금계산서 취소 |
|
||||
|
||||
---
|
||||
|
||||
## 💼 Phase 4: SaaS 기능 API
|
||||
|
||||
### 13. 요금제 관리 (Plans) - 7개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/plans` | 요금제 목록 |
|
||||
| LIST | GET | `/v1/plans/active` | 활성 요금제 목록 |
|
||||
| DETAIL | GET | `/v1/plans/{id}` | 요금제 상세 |
|
||||
| CREATE | POST | `/v1/plans` | 요금제 등록 |
|
||||
| UPDATE | PUT | `/v1/plans/{id}` | 요금제 수정 |
|
||||
| DELETE | DELETE | `/v1/plans/{id}` | 요금제 삭제 |
|
||||
| ACTION | PATCH | `/v1/plans/{id}/toggle` | 요금제 활성/비활성 |
|
||||
|
||||
---
|
||||
|
||||
### 14. 구독 관리 (Subscriptions) - 8개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/subscriptions` | 구독 목록 |
|
||||
| DETAIL | GET | `/v1/subscriptions/current` | 현재 구독 조회 |
|
||||
| DETAIL | GET | `/v1/subscriptions/{id}` | 구독 상세 |
|
||||
| CREATE | POST | `/v1/subscriptions` | 구독 신청 |
|
||||
| ACTION | POST | `/v1/subscriptions/{id}/cancel` | 구독 해지 |
|
||||
| ACTION | POST | `/v1/subscriptions/{id}/renew` | 구독 갱신 |
|
||||
| ACTION | POST | `/v1/subscriptions/{id}/suspend` | 구독 일시정지 |
|
||||
| ACTION | POST | `/v1/subscriptions/{id}/resume` | 구독 재개 |
|
||||
|
||||
---
|
||||
|
||||
### 15. 결제 관리 (Payments) - 7개 API
|
||||
|
||||
| 유형 | Method | Endpoint | 설명 |
|
||||
|------|--------|----------|------|
|
||||
| LIST | GET | `/v1/payments` | 결제 내역 목록 |
|
||||
| LIST | GET | `/v1/payments/summary` | 결제 요약 |
|
||||
| DETAIL | GET | `/v1/payments/{id}` | 결제 상세 |
|
||||
| CREATE | POST | `/v1/payments` | 결제 처리 |
|
||||
| ACTION | POST | `/v1/payments/{id}/complete` | 결제 완료 처리 |
|
||||
| ACTION | POST | `/v1/payments/{id}/cancel` | 결제 취소 |
|
||||
| ACTION | POST | `/v1/payments/{id}/refund` | 결제 환불 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 API 통계 요약
|
||||
|
||||
| Phase | 카테고리 | API 개수 |
|
||||
|-------|----------|----------|
|
||||
| Phase 1 | 휴가 관리 | 11 |
|
||||
| Phase 1 | 근무/출퇴근 설정 | 10 |
|
||||
| Phase 1 | 카드/계좌 관리 | 15 |
|
||||
| Phase 1 | 입금/출금 관리 | 12 |
|
||||
| Phase 1 | 매출/매입 관리 | 17 |
|
||||
| Phase 1 | 보고서 | 4 |
|
||||
| Phase 2 | 전자결재 | 26 |
|
||||
| Phase 2 | 급여 관리 | 13 |
|
||||
| Phase 2 | 대시보드 | 3 |
|
||||
| Phase 3 | AI 리포트 | 4 |
|
||||
| Phase 3 | 가지급금 | 9 |
|
||||
| Phase 3 | 바로빌 연동 | 12 |
|
||||
| Phase 4 | 요금제 관리 | 7 |
|
||||
| Phase 4 | 구독 관리 | 8 |
|
||||
| Phase 4 | 결제 관리 | 7 |
|
||||
| Phase 5 | 사용자 초대 | 5 |
|
||||
| Phase 5 | 알림 설정 | 3 |
|
||||
| Phase 5 | 계정 관리 | 4 |
|
||||
| **Total** | - | **170개** |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 관련 문서
|
||||
|
||||
- [ERP API 개발 계획](../plans/erp-api-development-plan.md)
|
||||
- [ERP API 상세 스펙](./erp-api-detail.md)
|
||||
- Swagger UI: http://sam.kr/api-docs/index.html
|
||||
339
guides/item-master-guide.md
Normal file
339
guides/item-master-guide.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# 품목기준관리(ItemMaster) API 가이드
|
||||
|
||||
> 품목 입력 화면을 구성하는 **페이지-섹션-필드** 구조 관리 시스템
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 핵심 개념
|
||||
|
||||
| 엔티티 | 테이블 | 설명 |
|
||||
|--------|--------|------|
|
||||
| **Page** | `item_pages` | 품목 유형별 화면 (FG, PT, SM, RM, CS) |
|
||||
| **Section** | `item_sections` | 페이지 내 논리적 영역 |
|
||||
| **Field** | `item_fields` | 섹션 내 입력 항목 |
|
||||
| **BomItem** | `item_bom_items` | BOM 섹션 내 부품 항목 |
|
||||
| **CustomTab** | `custom_tabs` | 커스텀 탭 설정 |
|
||||
| **UnitOption** | `unit_options` | 단위 옵션 |
|
||||
|
||||
### 1.2 아키텍처
|
||||
|
||||
- **독립 엔티티 구조**: 섹션, 필드, BOM은 독립적으로 존재하며 재사용 가능
|
||||
- **링크 테이블**: `entity_relationships`로 관계 관리
|
||||
- **연결 잠금**: 중요한 구조는 잠금으로 보호 가능
|
||||
|
||||
```
|
||||
ItemPage (item_type: FG, PT, SM, RM, CS)
|
||||
│
|
||||
│ entity_relationships (is_locked)
|
||||
▼
|
||||
ItemSection (type: default, bom, custom)
|
||||
│
|
||||
├─ entity_relationships → ItemField
|
||||
└─ entity_relationships → ItemBomItem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. API 엔드포인트
|
||||
|
||||
### 2.1 초기화
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/init` | 전체 데이터 로드 |
|
||||
|
||||
**응답 구조:**
|
||||
```json
|
||||
{
|
||||
"pages": [], // 페이지 + 연결된 섹션/필드
|
||||
"sections": [], // 모든 독립 섹션
|
||||
"fields": [], // 모든 독립 필드
|
||||
"customTabs": [], // 커스텀 탭
|
||||
"unitOptions": [] // 단위 옵션
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 페이지
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/pages` | 페이지 목록 |
|
||||
| POST | `/api/v1/item-master/pages` | 페이지 생성 |
|
||||
| PUT | `/api/v1/item-master/pages/{id}` | 페이지 수정 |
|
||||
| DELETE | `/api/v1/item-master/pages/{id}` | 페이지 삭제 |
|
||||
|
||||
### 2.3 섹션
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/sections` | 독립 섹션 목록 |
|
||||
| POST | `/api/v1/item-master/sections` | 독립 섹션 생성 |
|
||||
| POST | `/api/v1/item-master/pages/{pageId}/sections` | 섹션 생성 + 페이지 연결 |
|
||||
| PUT | `/api/v1/item-master/sections/{id}` | 섹션 수정 |
|
||||
| DELETE | `/api/v1/item-master/sections/{id}` | 섹션 삭제 |
|
||||
| POST | `/api/v1/item-master/sections/{id}/clone` | 섹션 복제 |
|
||||
| GET | `/api/v1/item-master/sections/{id}/usage` | 사용처 조회 |
|
||||
| PUT | `/api/v1/item-master/pages/{pageId}/sections/reorder` | 섹션 순서 변경 |
|
||||
|
||||
### 2.4 필드
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/fields` | 독립 필드 목록 |
|
||||
| POST | `/api/v1/item-master/fields` | 독립 필드 생성 |
|
||||
| POST | `/api/v1/item-master/sections/{sectionId}/fields` | 필드 생성 + 섹션 연결 |
|
||||
| PUT | `/api/v1/item-master/fields/{id}` | 필드 수정 |
|
||||
| DELETE | `/api/v1/item-master/fields/{id}` | 필드 삭제 |
|
||||
| POST | `/api/v1/item-master/fields/{id}/clone` | 필드 복제 |
|
||||
| GET | `/api/v1/item-master/fields/{id}/usage` | 사용처 조회 |
|
||||
| PUT | `/api/v1/item-master/sections/{sectionId}/fields/reorder` | 필드 순서 변경 |
|
||||
|
||||
### 2.5 BOM
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/bom-items` | 독립 BOM 목록 |
|
||||
| POST | `/api/v1/item-master/bom-items` | 독립 BOM 생성 |
|
||||
| POST | `/api/v1/item-master/sections/{sectionId}/bom-items` | BOM 생성 + 섹션 연결 |
|
||||
| PUT | `/api/v1/item-master/bom-items/{id}` | BOM 수정 |
|
||||
| DELETE | `/api/v1/item-master/bom-items/{id}` | BOM 삭제 |
|
||||
|
||||
### 2.6 섹션 템플릿
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/section-templates` | 템플릿 목록 |
|
||||
| POST | `/api/v1/item-master/section-templates` | 템플릿 생성 |
|
||||
| PUT | `/api/v1/item-master/section-templates/{id}` | 템플릿 수정 |
|
||||
| DELETE | `/api/v1/item-master/section-templates/{id}` | 템플릿 삭제 |
|
||||
|
||||
### 2.7 커스텀 탭
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/custom-tabs` | 탭 목록 |
|
||||
| POST | `/api/v1/item-master/custom-tabs` | 탭 생성 |
|
||||
| PUT | `/api/v1/item-master/custom-tabs/{id}` | 탭 수정 |
|
||||
| DELETE | `/api/v1/item-master/custom-tabs/{id}` | 탭 삭제 |
|
||||
| PUT | `/api/v1/item-master/custom-tabs/reorder` | 탭 순서 변경 |
|
||||
|
||||
### 2.8 단위 옵션
|
||||
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/unit-options` | 단위 목록 |
|
||||
| POST | `/api/v1/item-master/unit-options` | 단위 생성 |
|
||||
| DELETE | `/api/v1/item-master/unit-options/{id}` | 단위 삭제 |
|
||||
|
||||
### 2.9 엔티티 관계 (Link/Unlink)
|
||||
|
||||
**페이지-섹션 연결:**
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| POST | `/api/v1/item-master/pages/{pageId}/link-section` | 섹션 연결 |
|
||||
| DELETE | `/api/v1/item-master/pages/{pageId}/unlink-section/{sectionId}` | 섹션 연결 해제 |
|
||||
|
||||
**페이지-필드 연결:**
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| POST | `/api/v1/item-master/pages/{pageId}/link-field` | 필드 연결 |
|
||||
| DELETE | `/api/v1/item-master/pages/{pageId}/unlink-field/{fieldId}` | 필드 연결 해제 |
|
||||
|
||||
**섹션-필드 연결:**
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| POST | `/api/v1/item-master/sections/{sectionId}/link-field` | 필드 연결 |
|
||||
| DELETE | `/api/v1/item-master/sections/{sectionId}/unlink-field/{fieldId}` | 필드 연결 해제 |
|
||||
|
||||
**섹션-BOM 연결:**
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| POST | `/api/v1/item-master/sections/{sectionId}/link-bom` | BOM 연결 |
|
||||
| DELETE | `/api/v1/item-master/sections/{sectionId}/unlink-bom/{bomId}` | BOM 연결 해제 |
|
||||
|
||||
**관계 조회/정렬:**
|
||||
| Method | Endpoint | 설명 |
|
||||
|--------|----------|------|
|
||||
| GET | `/api/v1/item-master/pages/{pageId}/relationships` | 페이지 관계 조회 |
|
||||
| GET | `/api/v1/item-master/pages/{pageId}/structure` | 페이지 구조 조회 |
|
||||
| GET | `/api/v1/item-master/sections/{sectionId}/relationships` | 섹션 관계 조회 |
|
||||
| POST | `/api/v1/item-master/relationships/reorder` | 관계 순서 변경 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 구조
|
||||
|
||||
### 3.1 ItemPage
|
||||
|
||||
```typescript
|
||||
interface ItemPage {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
group_id: number;
|
||||
page_name: string;
|
||||
item_type: 'FG' | 'PT' | 'SM' | 'RM' | 'CS';
|
||||
source_table: 'products' | 'materials';
|
||||
absolute_path?: string;
|
||||
is_active: boolean;
|
||||
sections: ItemSection[]; // init 응답에 포함
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 ItemSection
|
||||
|
||||
```typescript
|
||||
interface ItemSection {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
group_id: number;
|
||||
title: string;
|
||||
type: string;
|
||||
order_no: number;
|
||||
is_template: boolean;
|
||||
is_default: boolean;
|
||||
is_locked?: boolean; // 연결 잠금 상태
|
||||
description?: string;
|
||||
fields?: ItemField[];
|
||||
bom_items?: ItemBomItem[];
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 ItemField
|
||||
|
||||
```typescript
|
||||
interface ItemField {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
group_id: number;
|
||||
field_name: string;
|
||||
field_key: string; // 저장 시 사용할 키
|
||||
field_type: FieldType;
|
||||
order_no: number;
|
||||
is_required: boolean;
|
||||
is_common: boolean;
|
||||
is_active: boolean;
|
||||
is_locked: boolean;
|
||||
default_value?: string;
|
||||
placeholder?: string;
|
||||
display_condition?: object; // 조건부 표시
|
||||
validation_rules?: object; // 유효성 검사 규칙
|
||||
options?: object; // dropdown 옵션 등
|
||||
properties?: object; // 추가 설정
|
||||
category?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
type FieldType = 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea';
|
||||
```
|
||||
|
||||
### 3.4 EntityRelationship
|
||||
|
||||
```typescript
|
||||
interface EntityRelationship {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
group_id: number;
|
||||
parent_type: 'page' | 'section';
|
||||
parent_id: number;
|
||||
child_type: 'section' | 'field' | 'bom';
|
||||
child_id: number;
|
||||
order_no: number;
|
||||
is_locked: boolean;
|
||||
locked_by?: number;
|
||||
locked_at?: string;
|
||||
metadata?: object;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 잠금(Lock) 기능
|
||||
|
||||
### 4.1 잠금의 의미
|
||||
|
||||
**연결이 잠기면:**
|
||||
- 해당 연결(관계)를 해제할 수 없음
|
||||
- 연결된 자식 엔티티를 삭제할 수 없음
|
||||
- 이름 변경, 속성 추가 등 **비구조적 수정은 허용**
|
||||
|
||||
```
|
||||
예시: page→section 연결이 잠김
|
||||
├─ ❌ 섹션을 페이지에서 분리할 수 없음
|
||||
├─ ❌ 해당 섹션을 삭제할 수 없음
|
||||
├─ ✅ 섹션 제목 변경 가능
|
||||
└─ ✅ 섹션에 새 필드 추가 가능
|
||||
```
|
||||
|
||||
### 4.2 잠금 상태 확인
|
||||
|
||||
init API 응답에 `is_locked` 필드가 포함됩니다.
|
||||
|
||||
```json
|
||||
{
|
||||
"pages": [{
|
||||
"id": 1,
|
||||
"sections": [{
|
||||
"id": 10,
|
||||
"is_locked": true,
|
||||
"fields": [{
|
||||
"id": 100,
|
||||
"is_locked": false
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 잠금 관련 에러
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "잠금된 연결은 해제할 수 없습니다.",
|
||||
"error": "entity_protected_by_locked_relationship"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 필드 타입
|
||||
|
||||
| field_type | 설명 | 렌더링 컴포넌트 |
|
||||
|------------|------|----------------|
|
||||
| `textbox` | 텍스트 입력 | `<Input type="text" />` |
|
||||
| `number` | 숫자 입력 | `<Input type="number" />` |
|
||||
| `dropdown` | 드롭다운 선택 | `<Select />` |
|
||||
| `checkbox` | 체크박스 | `<Checkbox />` |
|
||||
| `date` | 날짜 선택 | `<DatePicker />` |
|
||||
| `textarea` | 장문 텍스트 | `<Textarea />` |
|
||||
|
||||
---
|
||||
|
||||
## 6. 주의사항
|
||||
|
||||
### 6.1 삭제 시 동작
|
||||
- **페이지 삭제**: 연결된 섹션/필드는 삭제되지 않고 관계만 해제
|
||||
- **섹션 삭제**: 연결된 필드/BOM은 삭제되지 않고 관계만 해제
|
||||
- **잠금된 연결이 있으면**: 삭제/해제 불가
|
||||
|
||||
### 6.2 복제(Clone) 시 동작
|
||||
- 섹션 복제: 섹션 + 필드 + BOM 모두 복제
|
||||
- 필드 복제: 필드만 복제
|
||||
- 복제된 항목은 독립 엔티티로 생성됨
|
||||
|
||||
### 6.3 순서 변경
|
||||
- Drag & Drop 후 reorder API 호출 필요
|
||||
- `items` 배열에 `{id, order_no}` 형태로 전달
|
||||
|
||||
---
|
||||
|
||||
## 7. 변경 이력
|
||||
|
||||
| 날짜 | 변경 내용 |
|
||||
|------|----------|
|
||||
| 2025-12-09 | 시스템 기반 문서 전면 재작성 |
|
||||
| 2025-11-27 | 잠금(Lock) 기능 추가 |
|
||||
| 2025-11-26 | 독립 엔티티 아키텍처 적용 |
|
||||
| 2025-11-20 | entity_relationships 링크 테이블 도입 |
|
||||
763
guides/item-master-items-api.md
Normal file
763
guides/item-master-items-api.md
Normal file
@@ -0,0 +1,763 @@
|
||||
# 품목기준관리(ItemMaster) & 품목관리(Items) API 문서
|
||||
|
||||
> 프론트엔드 개발자를 위한 API 스펙 문서
|
||||
> 작성일: 2025-12-10
|
||||
|
||||
## 목차
|
||||
1. [개요](#개요)
|
||||
2. [품목관리 (Items) API](#품목관리-items-api)
|
||||
3. [품목기준관리 (ItemMaster) API](#품목기준관리-itemmaster-api)
|
||||
4. [공통 응답 형식](#공통-응답-형식)
|
||||
5. [에러 처리](#에러-처리)
|
||||
|
||||
---
|
||||
|
||||
## 개요
|
||||
|
||||
### 품목관리 (Items) vs 품목기준관리 (ItemMaster)
|
||||
|
||||
| 구분 | 품목관리 (Items) | 품목기준관리 (ItemMaster) |
|
||||
|------|------------------|---------------------------|
|
||||
| **역할** | 실제 품목 데이터 CRUD | 품목 입력 화면/폼 구성 관리 |
|
||||
| **대상 데이터** | products, materials 테이블 | item_pages, item_sections, item_fields 테이블 |
|
||||
| **사용자** | 품목 등록/수정하는 일반 사용자 | 화면 구성을 설정하는 관리자 |
|
||||
| **비유** | 엑셀 데이터 | 엑셀 양식(템플릿) |
|
||||
|
||||
### 품목 유형 코드 (item_type / product_type)
|
||||
|
||||
| 코드 | 설명 | 저장 테이블 |
|
||||
|------|------|-------------|
|
||||
| `FG` | 완제품 (Finished Goods) | products |
|
||||
| `PT` | 반제품/부품 (Part) | products |
|
||||
| `SM` | 반자재 (Semi-Material) | materials |
|
||||
| `RM` | 원자재 (Raw Material) | materials |
|
||||
| `CS` | 소모품 (Consumables) | materials |
|
||||
|
||||
---
|
||||
|
||||
## 품목관리 (Items) API
|
||||
|
||||
실제 품목 데이터를 조회/생성/수정/삭제하는 API입니다.
|
||||
|
||||
### 1. 통합 품목 목록 조회
|
||||
|
||||
**역할**: products와 materials를 통합하여 조회 (UNION 방식)
|
||||
|
||||
```
|
||||
GET /api/v1/items
|
||||
```
|
||||
|
||||
#### Request Parameters (Query)
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `type` | string | N | 품목 유형 필터 (쉼표 구분). 기본값: `FG,PT,SM,RM,CS` |
|
||||
| `search` 또는 `q` | string | N | 검색어 (코드, 이름, 태그) |
|
||||
| `category_id` | integer | N | 카테고리 ID 필터 |
|
||||
| `size` | integer | N | 페이지당 항목 수. 기본값: 20 |
|
||||
| `page` | integer | N | 페이지 번호. 기본값: 1 |
|
||||
| `include_deleted` | boolean | N | 삭제된 항목 포함 여부. 기본값: false |
|
||||
|
||||
#### Request 예시
|
||||
```http
|
||||
GET /api/v1/items?type=FG,PT&search=모터&size=10&page=1
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "조회되었습니다.",
|
||||
"data": {
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"item_type": "FG",
|
||||
"code": "P-001",
|
||||
"name": "완제품A",
|
||||
"specification": null,
|
||||
"unit": "EA",
|
||||
"category_id": 5,
|
||||
"type_code": "FG",
|
||||
"created_at": "2025-01-01T00:00:00.000000Z",
|
||||
"deleted_at": null,
|
||||
"safety_stock": 100,
|
||||
"lead_time": 7
|
||||
}
|
||||
],
|
||||
"current_page": 1,
|
||||
"per_page": 20,
|
||||
"total": 150,
|
||||
"last_page": 8
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Response 필드 설명
|
||||
|
||||
| 필드 | 설명 |
|
||||
|------|------|
|
||||
| `id` | 품목 고유 ID (테이블별 독립) |
|
||||
| `item_type` | 품목 유형 코드 |
|
||||
| `code` | 품목 코드 |
|
||||
| `name` | 품목명 |
|
||||
| `specification` | 규격 (materials만 해당) |
|
||||
| `unit` | 단위 (EA, KG, M 등) |
|
||||
| `category_id` | 카테고리 ID |
|
||||
| `type_code` | 품목 유형 코드 (item_type과 동일) |
|
||||
| `created_at` | 생성일시 |
|
||||
| `deleted_at` | 삭제일시 (Soft Delete) |
|
||||
| `safety_stock` | 안전재고 (attributes에서 플랫 전개) |
|
||||
| `lead_time` | 리드타임 (attributes에서 플랫 전개) |
|
||||
|
||||
> **Note**: `attributes` JSON 필드는 자동으로 최상위로 플랫 전개되어 반환됩니다.
|
||||
|
||||
---
|
||||
|
||||
### 2. 단일 품목 조회 (ID 기반)
|
||||
|
||||
**역할**: 특정 ID의 품목 상세 정보 조회 (가격 정보 옵션)
|
||||
|
||||
```
|
||||
GET /api/v1/items/{id}
|
||||
```
|
||||
|
||||
#### Path Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `id` | integer | Y | 품목 ID |
|
||||
|
||||
#### Query Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `item_type` | string | N | 품목 유형 코드. 기본값: `FG` |
|
||||
| `include_price` | boolean | N | 가격 정보 포함 여부. 기본값: false |
|
||||
| `client_id` | integer | N | 고객 ID (가격 조회 시) |
|
||||
| `price_date` | string | N | 가격 기준일 (YYYY-MM-DD) |
|
||||
|
||||
#### Request 예시
|
||||
```http
|
||||
GET /api/v1/items/123?item_type=SM&include_price=true&client_id=5
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "조회되었습니다.",
|
||||
"data": {
|
||||
"id": 123,
|
||||
"item_type": "SM",
|
||||
"code": "M-001",
|
||||
"name": "반자재A",
|
||||
"specification": "10mm x 20mm",
|
||||
"unit": "EA",
|
||||
"category_id": 10,
|
||||
"category": {
|
||||
"id": 10,
|
||||
"name": "철강류"
|
||||
},
|
||||
"type_code": "SM",
|
||||
"prices": {
|
||||
"sale": {
|
||||
"unit_price": 15000,
|
||||
"currency": "KRW",
|
||||
"effective_from": "2025-01-01"
|
||||
},
|
||||
"purchase": {
|
||||
"unit_price": 10000,
|
||||
"currency": "KRW",
|
||||
"effective_from": "2025-01-01"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 단일 품목 조회 (코드 기반)
|
||||
|
||||
**역할**: 품목 코드로 상세 정보 조회 (Product → Material 순서로 검색)
|
||||
|
||||
```
|
||||
GET /api/v1/items/code/{code}
|
||||
```
|
||||
|
||||
#### Path Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `code` | string | Y | 품목 코드 |
|
||||
|
||||
#### Query Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `include_bom` | boolean | N | BOM 정보 포함 여부. 기본값: false |
|
||||
|
||||
#### Request 예시
|
||||
```http
|
||||
GET /api/v1/items/code/P-001?include_bom=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 품목 생성
|
||||
|
||||
**역할**: 새 품목 등록 (product_type에 따라 products 또는 materials에 저장)
|
||||
|
||||
```
|
||||
POST /api/v1/items
|
||||
```
|
||||
|
||||
#### Request Body
|
||||
|
||||
| 필드 | 타입 | 필수 | 설명 |
|
||||
|------|------|------|------|
|
||||
| `code` | string | Y | 품목 코드 (최대 50자, 중복 시 자동 증가) |
|
||||
| `name` | string | Y | 품목명 (최대 255자) |
|
||||
| `product_type` | string | Y | 품목 유형: `FG`, `PT`, `SM`, `RM`, `CS` |
|
||||
| `unit` | string | Y | 단위 (최대 20자) |
|
||||
| `category_id` | integer | N | 카테고리 ID |
|
||||
| `description` | string | N | 설명 |
|
||||
| `is_sellable` | boolean | N | 판매 가능 여부. 기본값: true |
|
||||
| `is_purchasable` | boolean | N | 구매 가능 여부. 기본값: false |
|
||||
| `is_producible` | boolean | N | 생산 가능 여부. 기본값: false |
|
||||
| `safety_stock` | integer | N | 안전재고 (0 이상) |
|
||||
| `lead_time` | integer | N | 리드타임 (0 이상) |
|
||||
| `is_variable_size` | boolean | N | 가변 사이즈 여부 |
|
||||
| `product_category` | string | N | 제품 분류 (최대 20자) |
|
||||
| `part_type` | string | N | 부품 유형 (최대 20자) |
|
||||
| `attributes` | object | N | 동적 필드 (JSON) |
|
||||
| `material_code` | string | N | 자재 코드 (Material 전용) |
|
||||
| `item_name` | string | N | 품명 (Material 전용) |
|
||||
| `specification` | string | N | 규격 (Material 전용) |
|
||||
| `is_inspection` | string | N | 검수 여부: `Y`, `N` |
|
||||
| `search_tag` | string | N | 검색 태그 |
|
||||
| `remarks` | string | N | 비고 |
|
||||
| `options` | object | N | 옵션 (JSON) |
|
||||
|
||||
#### Request 예시
|
||||
```json
|
||||
{
|
||||
"code": "P-NEW-001",
|
||||
"name": "신규 완제품",
|
||||
"product_type": "FG",
|
||||
"unit": "EA",
|
||||
"category_id": 5,
|
||||
"is_sellable": true,
|
||||
"safety_stock": 50,
|
||||
"attributes": {
|
||||
"color": "red",
|
||||
"size": "L"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "품목이 생성되었습니다.",
|
||||
"data": {
|
||||
"id": 999,
|
||||
"code": "P-NEW-001",
|
||||
"name": "신규 완제품",
|
||||
"product_type": "FG",
|
||||
"unit": "EA",
|
||||
"category_id": 5,
|
||||
"is_active": true,
|
||||
"is_sellable": true,
|
||||
"is_purchasable": false,
|
||||
"is_producible": false,
|
||||
"created_by": 1,
|
||||
"created_at": "2025-12-10T10:00:00.000000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **중복 코드 처리**: 코드가 이미 존재하면 자동으로 증가합니다.
|
||||
> - `P-001` 중복 → `P-002`
|
||||
> - `ABC` 중복 → `ABC-001`
|
||||
|
||||
---
|
||||
|
||||
### 5. 품목 수정
|
||||
|
||||
**역할**: 기존 품목 정보 수정
|
||||
|
||||
```
|
||||
PUT /api/v1/items/{id}
|
||||
```
|
||||
|
||||
#### Path Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `id` | integer | Y | 품목 ID |
|
||||
|
||||
#### Request Body
|
||||
|
||||
| 필드 | 타입 | 필수 | 설명 |
|
||||
|------|------|------|------|
|
||||
| `item_type` | string | Y | 품목 유형 (테이블 분기용) |
|
||||
| `code` | string | N | 품목 코드 |
|
||||
| `name` | string | N | 품목명 |
|
||||
| ... | | | (생성과 동일한 필드, 모두 선택) |
|
||||
|
||||
#### Request 예시
|
||||
```json
|
||||
{
|
||||
"item_type": "FG",
|
||||
"name": "수정된 완제품명",
|
||||
"safety_stock": 100
|
||||
}
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "품목이 수정되었습니다.",
|
||||
"data": {
|
||||
"id": 999,
|
||||
"code": "P-NEW-001",
|
||||
"name": "수정된 완제품명",
|
||||
"safety_stock": 100,
|
||||
"updated_by": 1,
|
||||
"updated_at": "2025-12-10T11:00:00.000000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 품목 삭제 (Soft Delete)
|
||||
|
||||
**역할**: 품목 삭제 (BOM 구성품으로 사용 중이면 삭제 불가)
|
||||
|
||||
```
|
||||
DELETE /api/v1/items/{id}
|
||||
```
|
||||
|
||||
#### Path Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `id` | integer | Y | 품목 ID |
|
||||
|
||||
#### Query Parameters
|
||||
|
||||
| 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------|------|------|------|
|
||||
| `item_type` | string | N | 품목 유형. 기본값: `FG` |
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "품목이 삭제되었습니다.",
|
||||
"data": "success"
|
||||
}
|
||||
```
|
||||
|
||||
#### 에러 Response (BOM 사용 중)
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "해당 품목은 3건의 BOM에서 구성품으로 사용 중입니다."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. 품목 일괄 삭제
|
||||
|
||||
**역할**: 여러 품목 일괄 삭제
|
||||
|
||||
```
|
||||
DELETE /api/v1/items/batch
|
||||
```
|
||||
|
||||
#### Request Body
|
||||
|
||||
| 필드 | 타입 | 필수 | 설명 |
|
||||
|------|------|------|------|
|
||||
| `item_type` | string | Y | 품목 유형 |
|
||||
| `ids` | array | Y | 삭제할 품목 ID 배열 |
|
||||
|
||||
#### Request 예시
|
||||
```json
|
||||
{
|
||||
"item_type": "FG",
|
||||
"ids": [1, 2, 3, 4, 5]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 품목기준관리 (ItemMaster) API
|
||||
|
||||
품목 입력 화면의 구성(페이지, 섹션, 필드)을 관리하는 API입니다.
|
||||
|
||||
### 구조 개요
|
||||
|
||||
```
|
||||
ItemMaster 계층 구조:
|
||||
|
||||
Page (페이지)
|
||||
├── Section (섹션) - fields 타입
|
||||
│ ├── Field (필드)
|
||||
│ ├── Field (필드)
|
||||
│ └── Field (필드)
|
||||
└── Section (섹션) - bom 타입
|
||||
├── BomItem (BOM 항목)
|
||||
└── BomItem (BOM 항목)
|
||||
```
|
||||
|
||||
- **Page**: 품목 유형별 입력 화면 (예: 완제품 등록 페이지)
|
||||
- **Section**: 페이지 내 영역 구분 (예: 기본정보, BOM 구성)
|
||||
- **Field**: 입력 필드 정의 (예: 품목코드, 품목명)
|
||||
- **BomItem**: BOM 섹션의 구성품 정의
|
||||
|
||||
### 1. 초기화 데이터 로드
|
||||
|
||||
**역할**: 프론트엔드 앱 초기화 시 필요한 전체 ItemMaster 데이터 로드
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/init
|
||||
```
|
||||
|
||||
#### Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "조회되었습니다.",
|
||||
"data": {
|
||||
"pages": [
|
||||
{
|
||||
"id": 1,
|
||||
"tenant_id": 1,
|
||||
"group_id": null,
|
||||
"page_name": "완제품 등록",
|
||||
"item_type": "FG",
|
||||
"absolute_path": "/items/fg/create",
|
||||
"is_active": true,
|
||||
"sections": [
|
||||
{
|
||||
"id": 10,
|
||||
"title": "기본정보",
|
||||
"type": "fields",
|
||||
"order_no": 1,
|
||||
"is_locked": false,
|
||||
"fields": [
|
||||
{
|
||||
"id": 100,
|
||||
"field_name": "품목코드",
|
||||
"field_key": "code",
|
||||
"field_type": "textbox",
|
||||
"is_required": true,
|
||||
"order_no": 1,
|
||||
"is_locked": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"sections": [...],
|
||||
"fields": [...],
|
||||
"customTabs": [...],
|
||||
"unitOptions": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Response 필드 설명
|
||||
|
||||
| 필드 | 설명 |
|
||||
|------|------|
|
||||
| `pages` | 페이지 목록 (섹션, 필드 중첩 포함) |
|
||||
| `sections` | 모든 독립 섹션 목록 (재사용 가능) |
|
||||
| `fields` | 모든 독립 필드 목록 (재사용 가능) |
|
||||
| `customTabs` | 커스텀 탭 목록 (컬럼 설정 포함) |
|
||||
| `unitOptions` | 단위 옵션 목록 |
|
||||
|
||||
---
|
||||
|
||||
### 2. 페이지 API
|
||||
|
||||
#### 페이지 목록 조회
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/pages
|
||||
```
|
||||
|
||||
| Query 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------------|------|------|------|
|
||||
| `item_type` | string | N | 품목 유형 필터 |
|
||||
|
||||
#### 페이지 생성
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/pages
|
||||
```
|
||||
|
||||
| Request Body | 타입 | 필수 | 설명 |
|
||||
|--------------|------|------|------|
|
||||
| `page_name` | string | Y | 페이지명 (최대 255자) |
|
||||
| `item_type` | string | Y | 품목 유형: `FG`, `PT`, `SM`, `RM`, `CS` |
|
||||
| `absolute_path` | string | N | 절대 경로 (최대 500자) |
|
||||
|
||||
#### 페이지 수정
|
||||
|
||||
```
|
||||
PUT /api/v1/item-master/pages/{id}
|
||||
```
|
||||
|
||||
#### 페이지 삭제
|
||||
|
||||
```
|
||||
DELETE /api/v1/item-master/pages/{id}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 섹션 API
|
||||
|
||||
#### 독립 섹션 목록 조회
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/sections
|
||||
```
|
||||
|
||||
| Query 파라미터 | 타입 | 필수 | 설명 |
|
||||
|----------------|------|------|------|
|
||||
| `is_template` | boolean | N | 템플릿 섹션 필터 |
|
||||
|
||||
#### 독립 섹션 생성 (페이지 연결 없음)
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/sections
|
||||
```
|
||||
|
||||
| Request Body | 타입 | 필수 | 설명 |
|
||||
|--------------|------|------|------|
|
||||
| `group_id` | integer | N | 계층 번호 |
|
||||
| `title` | string | Y | 섹션 제목 (최대 255자) |
|
||||
| `type` | string | Y | 섹션 타입: `fields`, `bom` |
|
||||
|
||||
#### 페이지에 섹션 생성 (연결)
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/pages/{pageId}/sections
|
||||
```
|
||||
|
||||
#### 섹션 복제
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/sections/{id}/clone
|
||||
```
|
||||
|
||||
#### 섹션 사용처 조회
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/sections/{id}/usage
|
||||
```
|
||||
|
||||
**역할**: 해당 섹션이 어떤 페이지에서 사용되고 있는지 조회
|
||||
|
||||
#### 섹션 수정
|
||||
|
||||
```
|
||||
PUT /api/v1/item-master/sections/{id}
|
||||
```
|
||||
|
||||
#### 섹션 삭제
|
||||
|
||||
```
|
||||
DELETE /api/v1/item-master/sections/{id}
|
||||
```
|
||||
|
||||
#### 섹션 순서 변경
|
||||
|
||||
```
|
||||
PUT /api/v1/item-master/pages/{pageId}/sections/reorder
|
||||
```
|
||||
|
||||
| Request Body | 타입 | 필수 | 설명 |
|
||||
|--------------|------|------|------|
|
||||
| `items` | array | Y | `[{id: 1, order_no: 1}, {id: 2, order_no: 2}]` |
|
||||
|
||||
---
|
||||
|
||||
### 4. 필드 API
|
||||
|
||||
#### 독립 필드 목록 조회
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/fields
|
||||
```
|
||||
|
||||
#### 독립 필드 생성 (섹션 연결 없음)
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/fields
|
||||
```
|
||||
|
||||
| Request Body | 타입 | 필수 | 설명 |
|
||||
|--------------|------|------|------|
|
||||
| `group_id` | integer | N | 계층 번호 |
|
||||
| `field_name` | string | Y | 필드 표시명 (최대 255자) |
|
||||
| `field_key` | string | N | 필드 키 (최대 80자, 영문 시작) |
|
||||
| `field_type` | string | Y | 필드 타입 (아래 참조) |
|
||||
| `is_required` | boolean | N | 필수 입력 여부 |
|
||||
| `default_value` | string | N | 기본값 |
|
||||
| `placeholder` | string | N | 플레이스홀더 (최대 255자) |
|
||||
| `display_condition` | object | N | 표시 조건 (JSON) |
|
||||
| `validation_rules` | object | N | 검증 규칙 (JSON) |
|
||||
| `options` | array | N | 드롭다운 옵션 등 (JSON) |
|
||||
| `properties` | object | N | 추가 속성 (JSON) |
|
||||
| `is_locked` | boolean | N | 잠금 여부 |
|
||||
|
||||
#### 필드 타입 (field_type)
|
||||
|
||||
| 타입 | 설명 |
|
||||
|------|------|
|
||||
| `textbox` | 한 줄 텍스트 입력 |
|
||||
| `number` | 숫자 입력 |
|
||||
| `dropdown` | 드롭다운 선택 |
|
||||
| `checkbox` | 체크박스 |
|
||||
| `date` | 날짜 선택 |
|
||||
| `textarea` | 여러 줄 텍스트 입력 |
|
||||
|
||||
#### 섹션에 필드 생성 (연결)
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/sections/{sectionId}/fields
|
||||
```
|
||||
|
||||
#### 필드 복제
|
||||
|
||||
```
|
||||
POST /api/v1/item-master/fields/{id}/clone
|
||||
```
|
||||
|
||||
#### 필드 사용처 조회
|
||||
|
||||
```
|
||||
GET /api/v1/item-master/fields/{id}/usage
|
||||
```
|
||||
|
||||
**역할**: 해당 필드가 어떤 섹션에서 사용되고 있는지 조회
|
||||
|
||||
#### 필드 수정
|
||||
|
||||
```
|
||||
PUT /api/v1/item-master/fields/{id}
|
||||
```
|
||||
|
||||
#### 필드 삭제
|
||||
|
||||
```
|
||||
DELETE /api/v1/item-master/fields/{id}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 공통 응답 형식
|
||||
|
||||
모든 API는 동일한 응답 구조를 따릅니다.
|
||||
|
||||
### 성공 응답
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "처리되었습니다.",
|
||||
"data": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### 페이지네이션 응답
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "조회되었습니다.",
|
||||
"data": {
|
||||
"data": [...],
|
||||
"current_page": 1,
|
||||
"per_page": 20,
|
||||
"total": 100,
|
||||
"last_page": 5,
|
||||
"from": 1,
|
||||
"to": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 에러 처리
|
||||
|
||||
### 에러 응답 형식
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "에러 메시지",
|
||||
"errors": {
|
||||
"field_name": ["검증 오류 메시지"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 주요 HTTP 상태 코드
|
||||
|
||||
| 코드 | 설명 |
|
||||
|------|------|
|
||||
| `200` | 성공 |
|
||||
| `201` | 생성 성공 |
|
||||
| `400` | 잘못된 요청 (검증 실패, 중복 코드 등) |
|
||||
| `401` | 인증 필요 |
|
||||
| `403` | 권한 없음 |
|
||||
| `404` | 리소스 없음 |
|
||||
| `422` | 검증 실패 (Validation Error) |
|
||||
| `500` | 서버 오류 |
|
||||
|
||||
### 주요 에러 케이스
|
||||
|
||||
| 상황 | 메시지 예시 |
|
||||
|------|-------------|
|
||||
| 품목 없음 | "해당 품목을 찾을 수 없습니다." |
|
||||
| 코드 중복 | "이미 사용 중인 품목코드입니다." |
|
||||
| BOM 사용 중 | "해당 품목은 N건의 BOM에서 구성품으로 사용 중입니다." |
|
||||
| 필수 필드 누락 | "품목코드는 필수입니다." |
|
||||
| 잘못된 품목 유형 | "품목 유형은 FG, PT, SM, RM, CS 중 하나여야 합니다." |
|
||||
|
||||
---
|
||||
|
||||
## 인증
|
||||
|
||||
모든 API는 다음 인증이 필요합니다:
|
||||
|
||||
1. **API Key**: `X-API-KEY` 헤더
|
||||
2. **Bearer Token**: `Authorization: Bearer {token}` 헤더
|
||||
|
||||
```http
|
||||
GET /api/v1/items
|
||||
X-API-KEY: your-api-key
|
||||
Authorization: Bearer your-access-token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 날짜 | 버전 | 변경 내용 |
|
||||
|------|------|----------|
|
||||
| 2025-12-10 | 1.0 | 최초 작성 |
|
||||
@@ -267,7 +267,7 @@ sh 'export NODE_OPTIONS="--max-old-space-size=2048" && npm run build'
|
||||
|
||||
- [운영 환경 배포 계획서](../plans/production-deployment-plan.md) - Jenkinsfile 상세, 브랜치 전략
|
||||
- [.env 동기화 절차](production-env-sync.md) - 환경 변수 분리
|
||||
- [Docker 환경 스펙](../specs/docker-setup.md) - 현재 개발 환경
|
||||
- [Docker 환경 스펙](../system/docker-setup.md) - 현재 개발 환경
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ fastcgi_param SCRIPT_FILENAME /var/www/mng/public$fastcgi_script_name;
|
||||
|
||||
| 문서 | 설명 |
|
||||
|------|------|
|
||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ docker exec sam-mng-1 supervisorctl status
|
||||
|
||||
| 문서 | 설명 |
|
||||
|------|------|
|
||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -306,8 +306,8 @@ docker exec sam-mng-1 php artisan config:clear
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [Docker 환경 구성](../specs/docker-setup.md)
|
||||
- [시스템 아키텍처](../architecture/system-overview.md)
|
||||
- [Docker 환경 구성](../system/docker-setup.md)
|
||||
- [시스템 아키텍처](../system/overview.md)
|
||||
- [바로빌 카카오톡 연동](../features/barobill-kakaotalk/README.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -249,8 +249,8 @@ API 호출 시 → Next.js API Route 프록시 → api.sam.kr
|
||||
|
||||
| 문서 | 설명 |
|
||||
|------|------|
|
||||
| [docker-setup.md](../specs/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
| [system-overview.md](../architecture/system-overview.md) | 시스템 아키텍처 레퍼런스 |
|
||||
| [docker-setup.md](../system/docker-setup.md) | Docker 환경 설정값 상세 |
|
||||
| [overview.md](../system/overview.md) | 시스템 아키텍처 레퍼런스 |
|
||||
| [production-deployment-plan.md](../plans/production-deployment-plan.md) | 운영 배포 계획 |
|
||||
| [dev-commands.md](../quickstart/dev-commands.md) | 개발 명령어 모음 |
|
||||
|
||||
|
||||
@@ -237,8 +237,8 @@ php artisan l5-swagger:generate
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [API 개발 규칙](./api_rules.md)
|
||||
- [개발 명령어](./dev_commands.md)
|
||||
- [API 개발 규칙](../standards/api-rules.md)
|
||||
- [개발 명령어](../quickstart/dev-commands.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user