- Deleted the following files as they are no longer relevant to the current project structure: - 결재 시스템 구현 현황 - 결재 시스템 v2 사용 가이드 - WACE 시스템 문제점 분석 및 개선 계획 - Agent Pipeline 한계점 분석 - AI 기반 화면 자동 생성 시스템 설계서 - WACE ERP Backend - 분석 문서 인덱스 These deletions help streamline the documentation and remove obsolete information, ensuring that only current and relevant resources are maintained.
30 KiB
MES 구조 및 PC-POP 연동 가이드
작성일: 2026-03-20 대상: PC 화면 개발자 / POP 연동 담당자 목적: PC에서 작업지시를 등록할 때, POP(생산실적관리)에 공정이 자동 연동되는 전체 구조를 설명
1. 전체 구조 개요
1.1 시스템 구성
[PC 영역 - 브라우저] [POP 영역 - 태블릿]
작업지시 등록 화면 생산실적관리 화면 (4480)
(screen 4155, 4493) 카드 리스트 + 상세 모달
| |
| (1) work_instruction INSERT | (3) 카드 리스트 조회
| (2) create-work-processes 호출 | (4) 접수/실적/확정
v v
=================================================================
[백엔드 - Express + PostgreSQL]
/api/data/work_instruction (범용 CRUD)
/api/pop/production/* (MES 전용 API 10개)
=================================================================
1.2 데이터 흐름 요약
PC 등록 서버 자동 처리 POP 표시
--------- ---------------- ----------
1. 품목 선택 3. 라우팅 공정 조회 5. 카드 목록
2. 작업지시 INSERT ---> 4. work_order_process 6. 접수
+ create-work-processes N건 일괄 INSERT ---> 7. 실적 입력
API 호출 + process_work_result 8. 완료 확정
체크리스트 복사
2. DB 테이블 상세 구조
2.1 테이블 관계도
[마스터 데이터 - PC에서 사전 등록]
item_info process_mng defect_standard_mng
(품목 마스터) (공정 마스터) (불량 유형 마스터)
| |
v v
item_routing_version -----> item_routing_detail
(품목별 라우팅 버전) (공정 순서 정의)
|
v
process_work_item -----> process_work_item_detail
(공정별 작업항목) (체크리스트 상세)
[트랜잭션 데이터 - PC 등록 + POP 실행]
work_instruction ─── 1:N ──> work_order_process ─── 1:N ──> process_work_result
(작업지시 마스터) (공정별 작업 단위) (체크리스트 결과)
|
parent_process_id (자기참조)
|
work_order_process (분할 행)
(접수/재작업 분할 카드)
|
work_order_process_log
(변경 이력 - 트리거 자동)
2.2 work_instruction (작업지시 마스터) - 19컬럼
PC에서 등록하는 핵심 테이블. POP에서는 읽기 전용으로 참조.
| 컬럼 | 타입 | 기본값 | 역할 | 비고 |
|---|---|---|---|---|
id |
varchar | gen_random_uuid() | PK | UUID 자동 생성 |
work_instruction_no |
varchar | - | 작업지시번호 | 사용자 채번 (예: WI-20260320-001) |
item_id |
varchar | - | 품목 FK | -> item_info.id |
status |
varchar | - | 작업지시 상태 | waiting / in_progress / completed / cancelled |
progress_status |
varchar | - | 진행상태 | POP에서 완료 시 'completed'로 자동 갱신 |
qty |
varchar | - | 지시수량 | 핵심. POP 접수 상한의 기준 |
completed_qty |
varchar | '0' | 완성수량 | 마지막 공정 양품 합계로 자동 갱신 |
routing |
varchar | - | 라우팅 참조 | 현재 미사용 (비어있음) |
worker |
varchar | - | 작업자 | |
work_team |
varchar | - | 작업팀 | |
equipment_id |
varchar | - | 설비 FK | |
start_date |
varchar | - | 시작일 | |
end_date |
varchar | - | 종료일(납기) | |
reason |
varchar | - | 사유 | |
remark |
text | - | 비고 | |
company_code |
varchar | - | 멀티테넌시 | 필수 |
created_date |
timestamp | now() | 생성일 | |
updated_date |
timestamp | now() | 수정일 | |
writer |
varchar | - | 작성자 |
2.3 work_order_process (공정별 작업 단위) - 37컬럼
create-work-processes API 호출 시 자동 생성. POP에서 접수/실적/완료를 처리하는 핵심 테이블.
| 컬럼 그룹 | 컬럼 | 타입 | 기본값 | 역할 |
|---|---|---|---|---|
| 연결 | wo_id |
varchar | - | -> work_instruction.id (작업지시 FK) |
seq_no |
varchar | - | 공정 순서 (1, 2, 3...) | |
routing_detail_id |
varchar | - | -> item_routing_detail.id (라우팅 스냅샷) | |
parent_process_id |
varchar | NULL | 분할 시 마스터 행 참조 (NULL = 마스터) | |
| 공정정보 | process_code |
varchar | - | 공정코드 (예: P002) |
process_name |
varchar | - | 공정명 (예: 가공) | |
is_required |
varchar | - | 필수 여부 | |
is_fixed_order |
varchar | - | 순서 고정 여부 | |
standard_time |
varchar | - | 표준시간 | |
equipment_code |
varchar | - | 사용 설비 | |
| 수량 | plan_qty |
varchar | - | 계획수량 |
input_qty |
varchar | - | 접수량 (접수 시 설정) | |
good_qty |
varchar | - | 양품수량 (누적) | |
defect_qty |
varchar | - | 불량수량 (누적) | |
total_production_qty |
varchar | - | 총 생산수량 (누적) | |
concession_qty |
varchar | '0' | 특채수량 (양품에 합산 + 별도 추적) | |
| 상태 | status |
varchar | - | waiting / acceptable / in_progress / completed |
result_status |
varchar | 'draft' | draft / confirmed | |
| 타이머 | started_at |
varchar | - | 작업 시작 시각 |
paused_at |
varchar | - | 일시정지 시각 | |
total_paused_time |
varchar | 0 | 누적 일시정지 시간(초) | |
completed_at |
varchar | - | 완료 시각 | |
actual_work_time |
varchar | NULL | 실 작업시간(초) | |
| 작업자 | accepted_by |
varchar | - | 접수자 |
accepted_at |
varchar | - | 접수 시각 | |
completed_by |
varchar | NULL | 완료 처리자 | |
| 실적 | defect_detail |
varchar | - | 불량 상세 JSON (코드/수량/처분) |
result_note |
varchar | - | 실적 메모 | |
attachments |
varchar | - | 첨부파일 | |
| 재작업 | is_rework |
varchar | 'N' | 재작업 카드 여부 (Y/N) |
rework_source_id |
varchar | NULL | 재작업 원본 행 참조 | |
| 표준 | company_code, created_date, updated_date, writer, remark |
- | - | 표준 컬럼 |
2.4 process_work_result (체크리스트/검사 결과) - 35컬럼
공정별 체크리스트. create-work-processes 시 마스터 템플릿에서 복사.
| 컬럼 그룹 | 컬럼 | 역할 |
|---|---|---|
| 연결 | work_order_process_id |
-> work_order_process.id |
source_work_item_id |
-> process_work_item.id (템플릿 원본) | |
source_detail_id |
-> process_work_item_detail.id (템플릿 상세) | |
| 작업항목 | work_phase |
작업 단계 (PRE/IN/POST) |
item_title |
작업항목 제목 | |
item_sort_order |
항목 정렬 순서 | |
| 검사 상세 | detail_content |
검사 내용 |
detail_type |
상세 유형 | |
detail_sort_order |
상세 정렬 순서 | |
is_required |
필수 여부 | |
| 검사 기준 | inspection_code |
검사 코드 |
inspection_method |
검사 방법 | |
unit |
단위 | |
lower_limit / upper_limit |
하한/상한 | |
| 입력 | input_type |
입력 유형 |
lookup_target |
조회 대상 | |
display_fields |
표시 필드 | |
duration_minutes |
소요시간(분) | |
| 결과 | result_value |
입력 결과값 |
is_passed |
합격 여부 | |
status |
pending / completed | |
recorded_by |
기록자 | |
recorded_at |
기록 시각 | |
| 그룹 타이머 | group_started_at, group_paused_at |
그룹 시작/정지 |
group_total_paused_time, group_completed_at |
누적 정지/완료 |
2.5 마스터 데이터 테이블
item_info (품목 마스터)
| 주요 컬럼 | 역할 |
|---|---|
id |
PK (UUID) |
item_number |
품목코드 (라우팅 연결 키) |
item_name |
품목명 |
type |
품목 유형 |
division |
구분 |
process_mng (공정 마스터)
| 주요 컬럼 | 역할 |
|---|---|
process_code |
공정코드 (PK 역할) |
process_name |
공정명 (예: 가공, 검사, 포장) |
process_type |
공정 유형 |
use_yn |
사용 여부 |
item_routing_version (품목별 라우팅 버전)
| 주요 컬럼 | 역할 |
|---|---|
id |
PK (UUID) |
item_code |
-> item_info.item_number |
version_name |
버전명 (예: 기본 라우팅, v1) |
is_default |
기본 버전 여부 (boolean) |
item_routing_detail (공정 순서 정의)
| 주요 컬럼 | 역할 |
|---|---|
id |
PK (UUID) |
routing_version_id |
-> item_routing_version.id |
seq_no |
공정 순서 (1, 2, 3...) |
process_code |
-> process_mng.process_code |
is_required |
필수 여부 |
is_fixed_order |
순서 고정 여부 |
standard_time |
표준시간 |
3. PC에서 작업지시 등록 -> POP 연동 흐름
3.1 전체 시퀀스 다이어그램
[PC 사용자] [프론트엔드] [백엔드] [DB]
| | | |
| 1. 품목 선택 | | |
|------------------>| | |
| | 2. 라우팅 버전 조회 | |
| |--- GET /api/data/ | |
| | item_routing_ |--- SELECT |
| | version | item_routing_ |
| | ?item_code=XXX ->| version -->|
| |<-------------------|<----------------------|
| | | |
| 3. 정보 입력 | | |
| (수량/납기/etc) | | |
|------------------>| | |
| | | |
| 4. "등록" 클릭 | | |
|------------------>| | |
| | 5. 작업지시 INSERT | |
| |--- POST /api/data/ | |
| | work_instruction |--- INSERT |
| | --->| work_instruction -->|
| |<-------------------|<-- RETURNING id ------|
| | | |
| | 6. 공정 일괄 생성 | |
| |--- POST /api/pop/ | |
| | production/ | |
| | create-work- | |
| | processes -->| |
| | |-- SELECT item_routing |
| | | _detail + process_mng|
| | |<----------------------|
| | | |
| | |-- FOR EACH 공정: |
| | | INSERT work_order_ |
| | | process -->|
| | | INSERT process_work_ |
| | | result (체크리스트)->|
| | | |
| |<-- 성공 응답 ------| |
|<-- 등록 완료 -----| | |
| | | |
| | [이 시점부터 POP에서 조회 가능] |
3.2 Step 1: 작업지시 INSERT (필수)
API: POST /api/data/work_instruction
필수 데이터:
{
"item_id": "품목 UUID (item_info.id)",
"qty": "지시수량 (예: 500)",
"status": "waiting",
"work_instruction_no": "작업지시번호 (예: WI-20260320-001)"
}
선택 데이터:
{
"worker": "작업자",
"work_team": "작업팀",
"equipment_id": "설비 UUID",
"start_date": "시작일",
"end_date": "종료일(납기)",
"remark": "비고"
}
응답 예시:
{
"success": true,
"data": {
"id": "a1b2c3d4-...",
"work_instruction_no": "WI-20260320-001",
"status": "waiting"
}
}
이 시점에서는 work_instruction 행만 생성되고, POP에서 공정 카드가 표시되지 않는다.
3.3 Step 2: 공정 일괄 생성 (핵심 - 반드시 호출해야 POP 연동됨)
API: POST /api/pop/production/create-work-processes
인증: JWT 토큰 필수 (Authorization 헤더)
필수 파라미터:
| 파라미터 | 타입 | 설명 |
|---|---|---|
work_instruction_id |
string | Step 1에서 받은 작업지시 ID |
routing_version_id |
string | 선택한 라우팅 버전 UUID |
선택 파라미터:
| 파라미터 | 타입 | 설명 |
|---|---|---|
item_code |
string | 품목코드 (참고용) |
plan_qty |
string | 계획수량 (work_order_process.plan_qty에 저장) |
요청 예시:
{
"work_instruction_id": "a1b2c3d4-...작업지시ID",
"routing_version_id": "e5f6g7h8-...라우팅버전ID",
"plan_qty": "500"
}
서버 내부 동작:
- 중복 방지: 해당 work_instruction_id로 이미 공정이 있으면 409 에러
- 라우팅 조회:
item_routing_detail+process_mngJOIN으로 공정 목록 취득 - 공정별 INSERT: seq_no 순서대로 work_order_process 행 생성
- 1공정:
status = 'acceptable'(POP에서 즉시 접수 가능) - 2~N공정:
status = 'waiting'(앞공정 완료 대기)
- 1공정:
- 체크리스트 복사: 각 공정의
routing_detail_id에 연결된process_work_item+process_work_item_detail을process_work_result로 복사
응답 예시:
{
"success": true,
"data": {
"processes": [
{ "id": "uuid-1", "seq_no": "1", "process_name": "가공", "checklist_count": 3 },
{ "id": "uuid-2", "seq_no": "2", "process_name": "검사", "checklist_count": 5 },
{ "id": "uuid-3", "seq_no": "3", "process_name": "포장", "checklist_count": 2 }
],
"total_processes": 3,
"total_checklists": 10
}
}
에러 케이스:
| HTTP | 상황 | 메시지 |
|---|---|---|
| 400 | 필수 파라미터 누락 | "work_instruction_id와 routing_version_id는 필수입니다." |
| 409 | 이미 공정이 존재 | "이미 공정이 생성된 작업지시입니다." |
| 404 | 라우팅에 공정 없음 | "라우팅 버전에 등록된 공정이 없습니다." |
3.4 Step 1 + Step 2를 하나의 트랜잭션으로 묶는 방법
PC 화면에서 "등록" 버튼 1회 클릭으로 두 API를 순차 호출해야 한다.
// PC 프론트엔드 예시 코드
async function registerWorkInstruction(formData) {
// Step 1: 작업지시 INSERT
const wiResponse = await apiClient.post("/api/data/work_instruction", {
item_id: formData.itemId,
qty: formData.qty,
status: "waiting",
work_instruction_no: formData.wiNo,
worker: formData.worker,
start_date: formData.startDate,
end_date: formData.endDate,
});
if (!wiResponse.data.success) {
throw new Error("작업지시 등록 실패: " + wiResponse.data.message);
}
const workInstructionId = wiResponse.data.data.id;
// Step 2: 공정 일괄 생성 (이것이 POP 연동의 핵심)
const processResponse = await apiClient.post(
"/api/pop/production/create-work-processes",
{
work_instruction_id: workInstructionId,
routing_version_id: formData.routingVersionId,
plan_qty: formData.qty,
}
);
if (!processResponse.data.success) {
// 실패 시 작업지시도 삭제 또는 상태 변경 필요
throw new Error("공정 생성 실패: " + processResponse.data.message);
}
return {
workInstruction: wiResponse.data.data,
processes: processResponse.data.data.processes,
};
}
3.5 PC 화면에서 필요한 사전 데이터 조회
3.5.1 품목 목록 조회
GET /api/data/item_info
3.5.2 선택한 품목의 라우팅 버전 목록 조회
GET /api/data/item_routing_version?item_code={선택한 품목의 item_number}
is_default = true인 버전을 자동 선택하면 UX가 좋다.
3.5.3 라우팅 버전의 공정 목록 미리보기 (선택사항)
GET /api/data/item_routing_detail?routing_version_id={선택한 버전 ID}
등록 전에 사용자에게 "이 라우팅에 포함된 공정 목록"을 보여줄 수 있다.
4. POP 워크플로우 상세
4.1 공정 상태 전이 다이어그램
[PC 등록]
|
v
waiting ---------> acceptable ---------> in_progress ---------> completed
(대기중) (접수가능) (진행중) (완료)
| | |
| (접수 취소) | | (실적 저장 -> 자동완료)
|<--------------------+ |
| | (수동 확정)
| +----> completed + confirmed
|
| (앞공정에서 양품 발생 시 자동 전환)
|
waiting ---> acceptable
상태별 의미:
| 상태 | 의미 | POP 탭 | 전환 조건 |
|---|---|---|---|
waiting |
앞공정 미완료, 접수 불가 | 대기 탭 | 앞공정 양품 발생 시 -> acceptable |
acceptable |
접수 가능, 작업자 대기 | 접수가능 탭 | 작업자가 접수 시 -> in_progress (분할 행) |
in_progress |
작업 진행 중 | 진행 탭 | 실적 전량 생산 시 -> completed (자동) |
completed |
작업 완료 | 완료 탭 | 수동 확정 또는 자동 완료 |
4.2 수량 계산 공식
접수가능량 = 앞공정.양품합계 - 내공정.접수합계
= (앞공정 SUM(good_qty + concession_qty)) - (내공정 분할행 SUM(input_qty))
(1공정은 앞공정.양품합계 = work_instruction.qty)
양품 = 생산수량 - 불량수량
= production_qty - defect_qty
(서버에서 계산, 클라이언트 값은 참고만)
특채(concession) = 불량 중 disposition='accept'인 항목 합계
양품에는 포함되지 않으나, 다음 공정 전달량에 합산
자동완료 조건:
- 분할 행: total_production_qty >= input_qty
- 마스터 행: 모든 분할 행 completed + 잔여 접수가능 <= 0
- 작업지시: 마지막 seq_no의 모든 행 completed
4.3 접수(Accept) 상세
[접수가능 카드 클릭] -> [수량 입력 모달] -> [접수 확인]
|
v
POST /api/pop/production/accept-process
body: { work_order_process_id: 마스터행ID,
accept_qty: 접수수량 }
|
v
[분할 행 INSERT]
- parent_process_id = 마스터행ID
- input_qty = 접수수량
- status = 'in_progress'
- accepted_by = 로그인 사용자
- 체크리스트 복사
|
v
[POP 카드 갱신]
- 새 분할 카드가 "진행중" 탭에 표시
- 잔여 접수가능량이 남으면 마스터 카드도 "접수가능"에 유지
4.4 실적 저장(Save Result) 상세
[진행중 카드 클릭] -> [상세 모달 열림] -> [실적 입력]
|
생산수량 + 불량상세(코드/수량/처분) 입력
|
v
POST /api/pop/production/save-result
body: { work_order_process_id: 분할행ID,
production_qty: 생산수량,
defect_detail: [
{ defect_code, defect_name, qty, disposition }
] }
|
v
[서버 처리]
1. 양품/불량/특채 서버 계산
2. 기존 수량에 누적 (total_production_qty += production_qty)
3. 불량 상세 JSON 병합
4. disposition='rework' -> 재작업 카드 자동 생성
5. 양품 발생 -> 다음 공정 마스터 acceptable로 전환
6. 접수분 전량 생산 -> 분할 행 자동 completed
7. 모든 분할 행 완료 + 잔여 0 -> 마스터 자동 completed
8. 마지막 공정 전부 완료 -> work_instruction 완료
불량 처분(disposition) 3종:
| 처분 | 의미 | 수량 영향 |
|---|---|---|
scrap (폐기) |
폐기 처리 | 불량 집계에 포함, 양품에서 차감 |
rework (재작업) |
같은 공정에서 재작업 | 재작업 카드 자동 생성, 양품에서 차감 |
accept (특채) |
조건부 합격 | concession_qty에 기록, 다음 공정 전달량에 합산 |
4.5 확정(Confirm Result) 상세
수동 확정 = 접수분 전량 미생산이지만 강제로 완료 처리
(예: 생산 중단, 일부만 완료 등)
POST /api/pop/production/confirm-result
body: { work_order_process_id: 분할행ID }
결과:
- status = 'completed'
- result_status = 'confirmed'
- 양품 있으면 다음 공정 활성화
- 마스터/작업지시 캐스케이드 완료 판정
5. MES 전용 API 엔드포인트 정리
베이스 URL: /api/pop/production
인증: 모든 엔드포인트에 JWT 토큰 필수
| 순서 | 메서드 | URL | 용도 | 호출 주체 |
|---|---|---|---|---|
| 1 | POST | /create-work-processes |
작업지시에 공정 일괄 생성 | PC |
| 2 | POST | /accept-process |
공정 접수 (분할 행 생성) | POP |
| 3 | POST | /cancel-accept |
접수 취소 | POP |
| 4 | POST | /save-result |
실적 저장 (누적) | POP |
| 5 | POST | /confirm-result |
실적 확정 (수동 완료) | POP |
| 6 | GET | /available-qty |
접수가능량 조회 | POP |
| 7 | GET | /result-history |
차수별 실적 이력 | POP |
| 8 | GET | /defect-types |
불량 유형 목록 | POP |
| 9 | POST | /timer |
공정 타이머 (시작/정지/완료) | POP |
| 10 | POST | /group-timer |
그룹 타이머 (체크리스트별) | POP |
6. PC 화면 현황 (COMPANY_7 탑씰)
6.1 등록된 화면 목록
| 화면 ID | 이름 | 메인 테이블 | 용도 |
|---|---|---|---|
| 4155 | 작업지시 목록 | work_instruction | 목록 조회 |
| 4493 | 작업지시 등록화면 | work_instruction | 신규 등록 |
| 4156 | 수주 선택 | sales_order_detail | 모달 (수주 참조) |
| 4157 | 적용 확인 | work_instruction | 모달 (등록 확인) |
6.2 메뉴 구조
생산관리 (COMPANY_7)
├── 생산옵션설정 (/screens/1606)
├── 생산계획 (/screens/3985)
├── 작업지시 (/production/work-instruction) <-- React 페이지 미구현
├── 공정정보관리 (/production/process-info)
├── 생산실적 (하위 없음)
└── 생산리포트 (/admin/report/production)
6.3 현재 미구현 사항 (PC 개발 필요)
- 라우팅 버전 선택 UI: 품목 선택 시 해당 품목의 라우팅 버전 목록을 표시하고 선택하는 기능
- create-work-processes 호출 연동: 작업지시 등록 시 자동으로 공정 생성 API를 호출하는 로직
- work_instruction.routing 컬럼 활용: 현재 비어있음. routing_version_id를 저장하면 추적 가능
- 작업지시 상태 관리: 등록/수정/취소 워크플로우
7. 마스터 데이터 사전 등록 요건
작업지시 등록 전에 다음 마스터 데이터가 반드시 등록되어 있어야 한다.
7.1 필수 사전 등록 순서
1. process_mng (공정 마스터) 등록
예: P002=가공, P003=검사, P009=포장
2. item_info (품목 마스터) 등록
예: item_number=R_FREE3_002, item_name=원제_AK1000
3. item_routing_version (라우팅 버전) 등록
item_code = item_info.item_number
is_default = true (기본 버전)
4. item_routing_detail (공정 순서) 등록
routing_version_id = 위에서 만든 버전 ID
seq_no = 1, process_code = P002 (1공정: 가공)
seq_no = 2, process_code = P003 (2공정: 검사)
seq_no = 3, process_code = P009 (3공정: 포장)
5. (선택) process_work_item + detail (체크리스트 템플릿)
routing_detail_id = 위의 item_routing_detail.id
7.2 현재 COMPANY_7 데이터 현황
등록된 공정 (15개):
| 공정코드 | 공정명 | 유형 |
|---|---|---|
| P002 | 가공 | PT001 |
| P003 | 검사 | PT003 |
| P005 | 치수검사 | PT004 |
| P006 | 테스트 | PT001 |
| P007 | 인쇄 | PT006 |
| P008 | 조립 | PT002 |
| P009 | 포장 | PT004 |
| PRC-001 ~ PRC-006 | 검수/가공/조립/검사/포장 | 다양 |
| PROC-001 | 확인 | 세척 |
등록된 라우팅 버전 (24건): 다양한 품목에 대해 1~3개 공정 조합
8. 데이터 예시: 전체 흐름 시뮬레이션
시나리오: 품목 R_FREE3_002를 500개 생산
Step 1: 작업지시 등록 (PC)
-- 자동 생성되는 행
INSERT INTO work_instruction (work_instruction_no, item_id, qty, status)
VALUES ('WI-20260320-001', 'a4e492a0-...', '500', 'waiting');
-- id = 'wi-new-001' (UUID 자동생성)
Step 2: 공정 생성 API 호출 (PC -> 서버)
POST /api/pop/production/create-work-processes
{ work_instruction_id: 'wi-new-001',
routing_version_id: '5cff0c1e-...' }
-- 서버가 자동 생성하는 행 (item_routing_detail 기반)
INSERT INTO work_order_process (wo_id, seq_no, process_code, process_name, status, plan_qty)
VALUES
('wi-new-001', '2', 'P002', '가공', 'acceptable', '500'), -- 1공정: 접수가능
('wi-new-001', '30', 'P006', '테스트', 'waiting', '500'); -- 2공정: 대기
Step 3: POP에서 작업자가 1공정 접수 (300개)
-- accept-process가 생성하는 분할 행
INSERT INTO work_order_process (wo_id, seq_no, process_code, status, input_qty,
parent_process_id, accepted_by)
VALUES ('wi-new-001', '2', 'P002', 'in_progress', '300',
'마스터행ID', '작업자A');
Step 4: POP에서 실적 저장 (생산 300개, 불량 10개)
-- save-result가 UPDATE하는 행
UPDATE work_order_process
SET total_production_qty = '300',
good_qty = '290', -- 서버 계산: 300 - 10
defect_qty = '10',
status = 'completed' -- 자동완료: 300 >= 300(input_qty)
WHERE id = '분할행ID';
-- 다음 공정 자동 활성화
UPDATE work_order_process
SET status = 'acceptable' -- waiting -> acceptable
WHERE wo_id = 'wi-new-001' AND seq_no = '30'
AND parent_process_id IS NULL;
Step 5: 2공정도 접수 -> 실적 -> 완료하면
-- 작업지시 자동 완료
UPDATE work_instruction
SET status = 'completed',
progress_status = 'completed',
completed_qty = '280' -- 마지막 공정 양품 합계
WHERE id = 'wi-new-001';
9. 주의사항 및 제약
9.1 필수 규칙
- create-work-processes는 1회만 호출 가능: 같은 작업지시에 대해 2번 호출하면 409 에러
- routing_version_id는 필수: 라우팅 없이는 공정을 생성할 수 없음
- 1공정만 즉시 접수가능: 나머지는 앞공정 양품 발생 후 자동 전환
- 수량은 모두 VARCHAR: 정수 변환 시 parseInt 필수
- 멀티테넌시: 모든 쿼리에 company_code 필터 필수
- 분할 행 구조: 접수 시 마스터 행에서 분할 행을 INSERT하는 방식. 마스터 행에는 직접 실적 등록 불가
9.2 현재 미활용 컬럼
| 컬럼 | 테이블 | 상태 |
|---|---|---|
routing |
work_instruction | 비어있음 (routing_version_id 저장 권장) |
equipment_id |
work_instruction | 등록 가능하나 POP 연동 미구현 |
item_id |
work_instruction | 일부 테스트 데이터에서 비어있음 |
9.3 자동 완료 판정 주의
- 재작업 카드가 있으면 해당 카드가 완료될 때까지 마스터 행이 완료되지 않음
- 특채(concession_qty)는 양품에 포함되지 않으나 다음 공정 전달량에는 합산됨
- 초과 생산은 경고만 하고 차단하지 않음 (현장 유연성)