상품등록과 재고관리
공통 품번을 발급하고, 상품별 현재고와 입출고·변경 이력을 확인하는 기반.
개발 전달용 상세 명세 v1.0 · 하나의 서비스 / 단계별 구현 설계
C-1 / DEVELOPMENT SPECIFICATION
01서비스 개요·범위·연결
전사에서 같은 상품을 같은 품번으로 식별하고, 현재고와 이력을 확인할 기반을 만든다.
본 문서
상품 검색·발번·상품 상세·재고 조정·변경 이력. 요청 전 사용 가능.
다음 단계
C-2가 상품을 참조해 입출고를 처리하고, C-3이 포장·청구무게 기준을 읽는다.
이 문서는 새 서비스의 개발 명세다. 시트의 실제 열 주소를 그대로 웹 필드 위치로 간주하지 않는다.
C-1 / DEVELOPMENT SPECIFICATION
02사용자·권한·시나리오
| 역할 | 행동 | 목적 |
|---|---|---|
| 요청자 | 기존 품번 검색→없으면 상품 등록·발번 | 같은 상품의 재등록과 혼용 방지 |
| 물류 담당자 | 물류 운영정보·기초 재고 확인 및 수정 | 공통 코드·3PL WMS·현재고 정합성 |
| 어드민 | 물류 기능+운영 기준·계정 | C-4 관리와 연결 |
C-1 / DEVELOPMENT SPECIFICATION
03기능 요구사항
| 요구 ID | 개발 지시 | 검수 기준 |
|---|---|---|
| C1-R01 | 상품명·품번·프로젝트·3PL로 검색한다. | 등록 최신순, 검색 조건 유지 |
| C1-R02 | 최초5행·행 추가로 필요한 상품만 발번한다. | 완전 빈 행 제외, 이름/분류 일부만 입력한 행 차단 |
| C1-R03 | 자사300000·타사500000부터 순번을 부여한다. | 클라이언트 다음값 제안+서버 UNIQUE 재검사 |
| C1-R04 | 프로젝트 접두사와 발번 순서를 보존한다. | [프로젝트]_상품이름 / 배치 내 입력 순서·배치 최신순 |
| C1-R05 | 현재고 null·0·양수를 구분한다. | - 개/입고전,0/품절,양수/정상 |
| C1-R06 | 상품 상세에서 바코드·속성·3PL·이력을 제공한다. | 바코드 없으면-,3PL·프로젝트 강조 |
| C1-R07 | 물류팀만 바코드·속성·보관처·재고를 변경한다. | 변경 전후·작성자·시간·사유 영구 보존 |
| C1-R08 | 재고 조정과 입출고 완료를 원장에 반영한다. | 현재고·원장이 일치,미확인을0으로 자동 대체하지 않음 |
| C1-R09 | 상품 수불에서 원 요청으로 이동한다. | request_line_id→request_id 연결 |
C-1 / DEVELOPMENT SPECIFICATION
04인벤토리 목록·검색·정렬
상품명·품번·프로젝트·보관3PL 검색
| 상품이름 | 품번 | 프로젝트 | 보관3PL | 현재 재고 | 상태 |
|---|---|---|---|---|---|
| [예시프로젝트]_상품A | 300000 | 예시프로젝트 | 다보내 | - 개 | 입고전 |
| [예시프로젝트]_상품B | 300001 | 예시프로젝트 | 패박 | 0 | 품절 |
| [예시프로젝트]_상품C | 300002 | 예시프로젝트 | 다보내 | 25 | 정상 |
| 요소 | 상호작용·규칙 |
|---|---|
| 검색 | 상품명·sku_number·프로젝트·3PL 부분 일치. 검색 실패와 결과0건을 구분한다. |
| 등록 순서 | 서로 다른 배치는 created_at 최신순. 같은 배치는 입력한 순번 순으로 표시해 등록 결과를 비교한다. |
| 재고 표시 | 0은 품절,미확인은 입고전으로 구분. 입고전은 확인 여부를 뜻하며 미래 입고 일정의 존재를 보장하지 않는다. |
| 행 클릭 | 상품 상세 열기. 목록 검색어·스크롤 위치를 유지하고 닫으면 복귀한다. |
| 상태 색 | 정상 녹색·품절 빨강·입고전 노랑. 텍스트를 함께 표시한다. |
C-1 / DEVELOPMENT SPECIFICATION
05발번 폼·필드·유효성
신청자로그인 이름 자동 표시
소유권자사 / 타사
프로젝트예시프로젝트
| 상품이름 | 바코드(선택) | 상품 분류 |
|---|---|---|
| 상품A | - | 상품(완제품사입) |
| 상품B | - | 제품(Knowmerce 제작) |
* 앨범 발번 같은 경우 따로 요청해주세요.
| 필드 | 필수·잠금 | 검증 |
|---|---|---|
| 신청자 | 자동·읽기 전용 | 인증 계정이 서버에서 재설정 |
| 소유권 | 필수 | 자사/타사 드롭다운 |
| 프로젝트 | 필수 | 앞뒤 공백 제거,빈값 차단 |
| 상품이름 | 사용하는 행 필수 | 기존 상품과 비슷하면 검색 권장,동일 이름의 자동 중복 판정은 별도 확인 |
| 상품 분류 | 사용하는 행 필수 | 상품(완제품사입)/제품(Knowmerce 제작)/증정(포카·지류·증정품)/대행(Knowmerce 비용 제외) |
| 바코드 | 선택 | 문자열로 보존. 선행 0 삭제 금지 |
5행을 모두 채울 필요는 없다. 상품이름과 상품 분류가 모두 있는1행 이상이면 발번한다. 상품이름만 있는 미완성 행이 섞이면 전체 저장하지 않고 해당 행을 안내한다.
C-1 / DEVELOPMENT SPECIFICATION
06발번 처리·순번 충돌·복사
완료 팝업: “발번이 완료되었습니다! 입출고 요청을 원하실 경우, 복사버튼을 눌러 해당 시트의 첫행에 붙여넣기 해주세요!” — 웹에서는 ‘입출고 요청 첫행’이라는 설명을 함께 표시한다.
프론트 순번 계산만으로 중복을 막을 수 없다. 사용자 요청대로 순번 테이블은 두지 않되 서버 UNIQUE 검증과 배치 재시도로 무결성을 지킨다.
C-1 / DEVELOPMENT SPECIFICATION
07상품 상세·정보 수정·변경 이력
프로젝트: 예시프로젝트 · 보관3PL: 다보내
품번300000
바코드-
상품 속성상품(완제품사입)
현재 재고미확인
| 시간 | 구분 | 이전→변경 | 처리자·사유 |
|---|---|---|---|
| 예시시간 | 바코드 수정 | - → 0001234 | 물류 담당자 / WMS 기준 보완 |
| 예시시간 | 기초 재고 확정 | 미확인 → 25 | 물류 담당자 / 재고 확인 |
바코드·상품 속성·보관3PL·현재 재고 수정은 물류 담당자/어드민만 가능하고 반드시 이력을 남긴다. 일반 요청자는 조회만 한다. 상품명·품번·소유권의 일반 수정 UI는 이 범위에 포함하지 않는다.
C-1 / DEVELOPMENT SPECIFICATION
08재고·수불·NULL 처리 정책
| 상황 | 처리 |
|---|---|
| 신규 발번 | inventory_balances.quantity=NULL. 수불0건이어도0개로 단정하지 않음. |
| 기초 재고 확정 | 확인 수량과 사유 저장. 실제 수량을 반영한 기초 원장으로 잔액 정합성 확보. |
| 재고 조정 | 기존 확인값과 차이를 inventory_movements.quantity_delta에 저장. 변화량과 현재고 갱신을 함께 처리. |
| 운영정보 변경 | quantity_delta=0,change_payload_json에 이전/이후 값. 현재고의NULL/확인시점을 바꾸지 않음. |
| 입출고 완료 | C-2 실제 수량으로 원장·현재고 동시 갱신. 요청만으로 차감하지 않음. |
| 0실적 | 실제 처리0을 명시하되 물류 이동은 생성하지 않는 안. 과거 미확인 재고를0으로 확정하지 않음. |
| 3PL 이동 | 수량이 있는 보관처를 바꿀 때 단순 필드 변경으로 이동시키지 않음. 출고/입고 또는 확인된 이관 처리 기준 필요. |
한 SKU의 다중3PL 보관은 product_warehouses로 표현 가능하지만, 현재 기본 UX는 한 요청 한3PL을 제안한다. 다른 창고 이동과 다중 보관의 운영 절차는 확인 필요다.
C-1 / DEVELOPMENT SPECIFICATION
09데이터 관계·필드 사전
product_projects
| 필드/제약 | 타입 | 논리 정의 |
|---|---|---|
| id | TEXT | PRIMARY KEY NOT NULL |
| name | TEXT | NOT NULL |
| created_at | TEXT | NOT NULL |
products
| 필드/제약 | 타입 | 논리 정의 |
|---|---|---|
| id | TEXT | PRIMARY KEY NOT NULL |
| sku_number | TEXT | NOT NULL |
| project_id | TEXT | NOT NULL REFERENCES product_projects(id) ON DELETE RESTRICT |
| name | TEXT | NOT NULL |
| ownership | TEXT | NOT NULL |
| category | TEXT | NOT NULL |
| barcode | TEXT | |
| pack_capacity | INTEGER | |
| charge_weight_g | INTEGER | |
| is_gift | INTEGER | NOT NULL |
| created_by | TEXT | NOT NULL REFERENCES actors(id) ON DELETE RESTRICT |
| created_at | TEXT | NOT NULL |
| UNIQUE | (sku_number) | |
| CHECK | (pack_capacity | IS NULL OR pack_capacity > 0) |
| CHECK | (charge_weight_g | IS NULL OR charge_weight_g > 0) |
product_warehouses
| 필드/제약 | 타입 | 논리 정의 |
|---|---|---|
| id | TEXT | PRIMARY KEY NOT NULL |
| product_id | TEXT | NOT NULL REFERENCES products(id) ON DELETE RESTRICT |
| warehouse_id | TEXT | NOT NULL REFERENCES warehouses(id) ON DELETE RESTRICT |
| wms_sku | TEXT | |
| UNIQUE | (product_id, | warehouse_id) |
| UNIQUE | (warehouse_id, | wms_sku) |
inventory_balances
| 필드/제약 | 타입 | 논리 정의 |
|---|---|---|
| product_warehouse_id | TEXT | PRIMARY KEY NOT NULL REFERENCES product_warehouses(id) ON DELETE RESTRICT |
| quantity | INTEGER | |
| verified_at | TEXT | |
| updated_at | TEXT | NOT NULL |
| CHECK | (quantity | IS NULL OR quantity >= 0) |
inventory_movements
| 필드/제약 | 타입 | 논리 정의 |
|---|---|---|
| id | TEXT | PRIMARY KEY NOT NULL |
| product_warehouse_id | TEXT | NOT NULL REFERENCES product_warehouses(id) ON DELETE RESTRICT |
| request_line_id | TEXT | REFERENCES request_lines(id) ON DELETE RESTRICT |
| actor_id | TEXT | NOT NULL REFERENCES actors(id) ON DELETE RESTRICT |
| movement_type | TEXT | NOT NULL |
| quantity_delta | INTEGER | NOT NULL |
| reason | TEXT | NOT NULL |
| created_at | TEXT | NOT NULL |
추가 설계 제안: change_payload_json(nullable)을 추가해 바코드·속성·보관처 변경의 전후값을 보존한다. 상품정보 변경은 quantity_delta=0으로 기록하고, 미확인 현재고를 0으로 확정하지 않는다.
보관처·WMS 코드는 product_warehouses에, 현재고는 inventory_balances에 둔다. 품번 필드는 sku가 아닌 sku_number를 사용한다. barcode_snapshot은 요청명세에 추가하지 않는다.
C-1 / DEVELOPMENT SPECIFICATION
10API·유효성·예외
| 제안 API | 처리 | 실패·복구 |
|---|---|---|
| GET /products?q=… | 검색·3PL·현재고 조회 | 오류 시 기존 목록 유지,재시도 |
| POST /products/batch | 소유권·프로젝트·상품N행+제안 품번 | 400행 오류 /409품번중복 / 전체 미저장 |
| GET /products/:id | 정보·재고·수불·변경이력 조회 | 404/403 구분 |
| PATCH /products/:id/operational | 바코드·속성·3PL+사유 | 403권한 /400필수값 / 기존값 유지 |
| POST /inventory/adjustments | product_warehouse_id·확인수량·사유 | 재고/원장 원자 처리 실패 시 모두 롤백 |
| 예외 | 메시지·동작 |
|---|---|
| 미등록 검색 | 결과 없음→발번 안내. 통신실패를미등록으로표시하지않음. |
| 불완전 행 | “N행의 상품이름과 상품 분류를 확인해주세요.” |
| 수량 오류 | 0이상의 정수만허용. 빈값은 미확인으로 구분하되 확정재고를 임의로미확인처리하는정책은확인 필요. |
| 서버 실패 | 발번 성공 팝업 금지,사용자입력 유지 |
C-1 / DEVELOPMENT SPECIFICATION
11예시 체험 · 재고 표시
표시 규칙을 직접 확인
- 개 · 입고전
이 예시는 표시 규칙만 실행한다. 실제 재고 저장은 하지 않는다.
C-1 / DEVELOPMENT SPECIFICATION
12인수 테스트·인계·확인 필요
| 테스트 ID | 연결 요구 | 시나리오 | 기대 결과 |
|---|---|---|---|
| C1-T01 | C1-R01 | 프로젝트명 부분 검색 | 관련 상품만 최신 배치순으로 표시 |
| C1-T02 | C1-R02 | 상품2행+빈3행 발번 | 2개만 생성,품번2개 복사 |
| C1-T03 | C1-R02 | 이름만 입력된행 포함 | 해당행 안내,모든행 미저장 |
| C1-T04 | C1-R03 | 두 창에서 같은 다음 품번 제출 | 한배치만성공,다른배치는입력 유지/재조회 |
| C1-T05 | C1-R04 | 프로젝트P·상품Q 발번 | [P]_Q,등록배치 입력순서 유지 |
| C1-T06 | C1-R05 | 재고NULL/0/25 각각조회 | 입고전/품절/정상구분 |
| C1-T07 | C1-R06 | 바코드없는상품조회 | - 표시,프로젝트와3PL강조 |
| C1-T08 | C1-R07 | 요청자 API직접수정 | 403,DB불변 |
| C1-T09 | C1-R07 | 물류 담당자 바코드수정 | 전후값·사유·처리자·시간 기록 |
| C1-T10 | C1-R08 | 재고확정과저장실패 | 원장/잔액 둘다미변경 |
| C1-T11 | C1-R09 | 수불항목의요청선택 | 같은 요청상세로이동 |
기존 시트의 실제 품번 형식과 초기 마이그레이션 범위를 먼저 확인한다. 테스트용 데이터는 실상품을 덮어쓰지 않고 예시 프로젝트로 준비한다.