MD-13 · 상품 관리 › 공급사 상품 관리 › 재고 마감 · 그룹5 · PLD-1032
MD-13 재고 마감 — 요일별·특정날짜 수량 제한 스케줄
기획·개발 문서 (그룹5). 공급사 물량 부족 같은 일시적 수급 이슈 때 히어로(공급사 상품) × 센터 × 요일/특정날짜의 최대 주문 수량을 미리 걸어두는 독립 화면. 마감시각은 전 항목 16:00 고정. 상시(무기한) 제한은 기존 수량 제한 기능의 영역이라 범위 밖.
seller_product.order_limit, seller_product_center_limit)는 건드리지 않는다.
변경 이력: 초기안=기존 수량제한에 요일 탭 → 확정안=독립 스케줄 화면(요일별·특정날짜) · 라이브 프로토 https://md-g5-13-app.pages.dev/
한눈 결론
seller_product.hero_product_code. 그룹 단위 아님(그룹의 42%가 히어로 2개 이상 — 개발DB 기준 참고치). 주별 없음(모호해서 폐기).order_limit·seller_product_center_limit) 영역 — 상시면 상품 제외·공급처 확보가 맞다. MD-15(마케팅 한정판매)와 별개. 화면은 설정 전용(확정·잔여·오버 표시 없음).개요 — 왜 스케줄인가, 어디까지인가
일시적 수급 이슈에 날짜·요일 축으로 대응한다. 상시 제한과 마케팅 한정판매는 이 화면이 아니다.
공급사 물량이 갑자기 부족해지면 특정 상품(히어로)의 주문을 센터별·날짜별로 막아야 한다. 지금 있는 수량 제한은 상시(무기한)뿐이라 날짜·요일 축이 없고, 며칠만 막으려 해도 걸었다가 풀어야 한다. MD-13은 이 빈칸을 채운다 — 요일별 또는 특정 날짜(오늘~+3개월)에만 적용되는 제한 수량을 미리 등록한다.
seller_product_not_in_center)하거나 공급처를 확보하는 것이 맞다. MD-13은 일시적 제한만 다룬다. 마케팅 목적의 노출·한정판매는 MD-15.기존 상시 제한 vs MD-13 (실측 기준)
| 구분 | 기존 수량 제한 (상시) | MD-13 재고 마감 (스케줄) |
|---|---|---|
| 데이터 | seller_product.order_limit(히어로 전체, int, 기본 0) · seller_product_center_limit(히어로×센터, limit_count) — 개발DB 실측 | 신규 hero_qty_schedule (§06·07) |
| 시간 축 | 없음(무기한) | 요일별 / 특정날짜(오늘~+3개월) |
| 용도 | 계속 제한할 상품 → 상품 제외·공급처 확보가 정답 | 공급사 물량 부족 등 일시적 수급 이슈 |
| 화면 | 기존 수량 제한 화면 (변경 없음) | 신규 재고 마감 3뷰 |
| 관계 | 서로 독립. 주문 시점 검사는 둘 다 통과해야 한다(기존 상시 검사 로직은 그대로, 스케줄 검사가 추가됨). | |
정의 / 정책
단위 · 방식 · 값 · 마감시각 · 화면 성격 · 권한.
| 항목 | 정책 | 상태 |
|---|---|---|
| 제한 단위 | 히어로(공급사 상품) × 센터. 센터는 센터 관리 목록(스테이지 어드민 /mfcCenterManage 기준 60곳)에서 검색·다중 선택, 또는 전 센터 공통. 그룹 단위는 그룹의 42%가 히어로 2개 이상(개발DB 참고치)이라 어느 공급사 물량인지 모호 → 히어로 단위. | 확정 |
| 스케줄 방식 | 요일별(월~일 다중 선택, 요일마다 다른 제한 수량 가능) 또는 특정날짜(오늘~+3개월 이내). 주별 없음 — 목요일에 걸면 "이번 주"가 언제인지 모호해 폐기. 3개월 상한은 무한정 예약 방지. | 확정 |
| 값 | 제한 수량 = 해당 히어로×센터×요일/날짜에 받을 최대 주문 수량. 정수 1 이상(0·빈값 불가). | 확정 |
| 마감시각 | 전 항목 16:00 고정. 표·목록·캘린더에 고정 표시만 하고 입력 UI 없음. 센터·요일별 편차 없음. | 확정 |
| 화면 성격 | 설정 전용. 확정(현재 주문 수량)·잔여·오버·상태 뱃지·시뮬레이션을 표시하지 않는다 — 반품/취소 재계산 복잡성을 화면에서 걷어냄. 초과 방지·복구는 백엔드(§05). | 확정 |
| 상시 제한 | MD-13 범위 아님. 기존 order_limit·seller_product_center_limit 그대로. | 확정 |
| MD-15 | 재고·수급(MD-13)과 마케팅 노출·한정판매(MD-15)는 별개 기능. | 확정 |
| 상품 선택 UI | 기존 어드민 "상품 선택" 모달 재사용, 단일 선택(라디오). 한 설정 = 한 히어로. | 확정 |
| 공급사 수정 권한 | 1차는 MD 전용(기본 끄기). 켜면 공급사는 자기 상품(seller_id 일치)만 — 서버측 가드 필수. 허용 범위·시기는 논의사항(§05 D-3). | 결정필요 |
화면 흐름 — 3뷰 (라이브 프로토)
왼쪽이 프로토, 오른쪽 번호가 각 요소 설명. 프로토 안 우측 주석 레일은 개발 범위 메모.
3뷰 요약
| 뷰 | 역할 | 구성 |
|---|---|---|
| 1. 목록(첫 진입) | "지금 어디에 제한을 걸어뒀나"에 답한다. 읽기 전용. | 검색·센터 필터 · 표(상품/센터/방식·기간/제한 수량/마감시각/관리) · [+ 신규 등록] [📅 캘린더 보기] |
| 2. 신규 / 수정 | 한 히어로의 스케줄 항목 하나를 만든다/고친다. | ① 상품 선택(단일) → ② 마감 방식(요일별/특정날짜) → ③ 적용 범위(센터별/공통) + 제한 수량 → [취소][저장] |
| 3. 캘린더 | 특정 날에 무슨 제한이 겹치는지 확인. | 월 이동 · 날짜별 뱃지 · 날짜 클릭 상세 |
등록 시나리오
- 진입 — 상품 관리 › 공급사 상품 관리 › 재고 마감. 목록이 뜬다. 우측 상단 [+ 신규 등록].
- ① 상품 — [+ 상품 선택] → 기존 상품 선택 모달에서 히어로 검색 → 라디오 1개 → [추가].
- ② 방식 — 요일별이면 요일 다중 선택, 특정 날짜면 캘린더에서 날짜 선택(오늘~+3개월).
- ③ 범위·수량 — 센터별: [+ 센터 추가]로 센터를 고르고 행마다 제한 수량. 공통: 제한 수량 1개.
- 저장 — 검증 통과 → 목록으로 복귀, 토스트. 같은 히어로×센터가 이미 있으면 중복 모달 → [기존 설정 열기].
- 확인 — 목록에서 검색/필터, 또는 캘린더 보기에서 날짜별 확인.
<title>은 아직 "프로토 v14"로 표기돼 있다 — 배포 갱신 확인 필요. (2) 프로토 우측 주석 레일에 "상시 제한 🟠 미정"이 남아 있으나 본 문서에서는 범위 밖으로 정리했다(§08). (3) 폼 상단 [엑셀 업로드] 버튼은 토스트만 뜨는 자리표시자 — 본 문서 범위(화면 입력)에 없고, 필요하면 별도 차수. (4) 요일별에서 프로토는 한 번에 한 요일의 센터표를 펼쳐 편집하며, 목업 저장은 마지막 활성 요일만 기록한다 — 프로토 한계이고, 실제는 선택한 모든 요일이 각자의 제한 수량으로 저장된다.규칙 · 검증
중복 판정, 저장 검증, 수정·삭제, 만료. 프로토 validate()·findDup()과 대조.
중복 판정 — 히어로 × 센터
| 상황 | 판정 | 처리 |
|---|---|---|
| 신규가 센터별, 기존이 센터별 | 같은 히어로코드 + 센터가 1곳이라도 겹치면 중복 | 저장 차단 → "이미 등록된 마감이 있습니다" 모달(기존 항목의 방식·기간·범위·제한 수량 표시) → [기존 설정 열기]로 편집 진입. 방식·범위가 달라도 그 항목에서 전환. |
| 신규가 전 센터 공통 | 그 히어로의 어떤 기존 항목과도 충돌(공통은 모든 센터를 덮음) | |
| 기존이 전 센터 공통 | 그 히어로의 어떤 센터별 신규와도 충돌 | |
| 같은 히어로, 겹치지 않는 센터 집합 | 중복 아님 | 별도 항목으로 등록 가능(예: A·B 센터 항목과 C 센터 항목). |
항목은 한 가지 방식(요일별 또는 특정날짜)만 가진다. 편집에서 방식을 바꾸면 기존 요일/날짜 행은 새 행으로 교체된다. 이 규칙 덕분에 주문 시점에 (히어로, 센터, 날짜)에 매칭되는 스케줄 행은 최대 1개다 — 우선순위 규칙이 필요 없다(§05).
저장 검증 — 미충족 시 차단 + 가이드 문구
| 조건 | 규칙 | 가이드 문구(프로토) |
|---|---|---|
| 상품 | 히어로 1개 선택 필수 | "상품(공급사)을 선택하세요" |
| 요일별 | 요일 1개 이상 | "요일을 1개 이상 선택하세요" |
| 특정날짜 | 날짜 필수 + 오늘~+3개월 이내 | "날짜를 선택하세요" / "날짜를 3개월 이내로 선택하세요" |
| 센터별 | 센터 1곳 이상 + 각 행 제한 수량 정수 1 이상 | "센터를 1곳 이상 추가하세요" / "제한 수량을 입력하세요 (1 이상) — 센터명" |
| 전 센터 공통 | 제한 수량 정수 1 이상 | "제한 수량을 입력하세요 (1 이상)" |
동작: 배너에 미충족 항목을 전부 나열하고 첫 오류로 스크롤·포커스, 필드에 빨간 테두리(입력 중 실시간 해제). 방식·범위 토글을 바꾸면 에러 상태 초기화.
수정 · 삭제 · 만료 (구현 메모)
| 상황 | 처리 | 근거 |
|---|---|---|
| 수정 저장 | 수정 중 상품·센터를 바꿀 수 있으므로 수정 저장에도 중복 검사를 건다(자기 항목은 제외). | 프로토는 신규 저장에서만 findDup()을 호출 — 실측. 구현 시 보완. |
| 삭제 | 목록 [삭제] = 항목 전체(모든 요일/날짜·센터 행) 삭제. 확인 다이얼로그는 기존 어드민 관례를 따른다. | 프로토는 즉시 삭제 + 토스트. 설정 데이터라 이력 요구 없음 → 물리 삭제 권장(§07). |
| 지난 특정날짜 | 날짜가 지나면 주문 검사에는 자연히 매칭되지 않는다. 목록은 오늘 이후 항목만 기본 표시하고 지난 항목은 필터로 보는 것을 제안. | 제안. 프로토엔 없음 — 목록 노이즈 방지 목적. |
| 공급사 휴무 요일 | 요일별 선택기에서 잠금(🔒 휴무)으로 표시 — 선택 불가. | 프로토 OPEN_DAY 하드코딩. 실제 운영요일 출처(공급사 설정)는 구현 시 연결. |
백엔드 — 주문 시점 검사와 개발 논의
화면은 제한 수량을 저장만 한다. 초과 방지·복구는 여기.
주문 시점 검사 흐름
- 매칭 — 주문 라인(히어로 H, 센터 C, 기준일 D·요일 w)에 대해
hero_qty_schedule에서use_yn='Y'이고 (center_code = C또는NULL=공통) 이며 (DATE·target_date = D) 또는 (DOW·dow = w)인 행을 찾는다. §04 중복 규칙상 최대 1행. - 없으면 통과 — 기존 상시 제한 검사(
order_limit·seller_product_center_limit)는 별개로 그대로 수행. - 현재 집계 —
member_order_details에서 (H, C, D)의 유효 주문 수량 합 = Σ(quantity−cancel_quantity). 유효 상태 집합은 D-1. - 판정 — 집계 + 이번 주문 수량 >
limit_qty→ 주문 불가(초과 시 처리의 기본값. 변형은 D-2). - 자동 복구 — 카운터를 따로 두지 않고 매번 주문 데이터를 집계하므로, 취소·반품(
cancel_quantity·CANCEL_COMPLETE)은 다음 검사에서 저절로 빠진다. MD가 손댈 것 없음.
SELECT … FOR UPDATE 또는 (H, C, D) 키 advisory lock으로 직렬화.
인덱스 — 집계 쿼리용 member_order_details (hero_product_code, center_code, <기준일>) 인덱스가 현재 없다(개발DB 실측: (member_id, hero)·(member_order_id, seller_id, confirm_date)만 존재). 추가 필요.
개발 논의 — 화면 미정 아님, 주문 로직 정책
order_status에 VIRTUAL_WAIT(입금 대기)·VIRTUAL_EXPIRY(가상계좌 만료)가 있어 가상계좌 주문은 결제 전 상태로 존재한다 → 집계에 넣을지(선점) 뺄지(입금 후 반영). (b) 스케줄의 '날짜/요일'이 주문의 어느 날짜에 대응하는지 — 주문 접수일(16:00 마감 컷) / 발주 확정일(confirm_date) / 도착일(arrival_date).CANCEL_COMPLETE·VIRTUAL_EXPIRY 제외 전부(입금 대기 포함 = 선점). (b) 기준일 = 발주 확정일 confirm_date, 16:00 = 그날 발주 마감 컷. 주문 라인에 close_hour 컬럼이 이미 있으나 의미는 코드 미확인.seller_product.seller_id가 본인인 히어로만 — 목록·저장 모두 서버측 필터. 권한 플래그는 기존 공급사 설정/권한 체계에 얹는다(신규 테이블 없음).데이터 모델 (ERD)
신규 1 · 참조 3 · 유지 2. 참조·유지 테이블의 컬럼은 개발DB 스키마 실측(2026-09-03).
order_limit은 그대로(상시).center_code varchar(20)로 참조하므로 스케줄도 center_code로.order_status = BEFORE·PREPARE·STORAGE·DELIVERY·COMPLETE·CANCEL_COMPLETE·VIRTUAL_WAIT·VIRTUAL_EXPIRY(실측).seller_product_member_limit(히어로별 limit_count, 회원당 제한으로 추정)·close_hour의 의미는 코드로 확인하지 않았다. 신규 테이블의 이름·컬럼은 초안이다.DDL 초안 + 조회 예시
Postgres. 개발DB는 15.12(실측) — 운영·스테이지 버전은 미확인.
-- 🆕 요일별·특정날짜 제한 수량 스케줄 (1행 = 히어로 × 센터 × 요일 1개 또는 날짜 1개) CREATE TABLE hero_qty_schedule ( id bigserial PRIMARY KEY, item_id bigint NOT NULL, -- 같은 등록(목록 1행)에서 만든 행 묶음 hero_product_code varchar(100) NOT NULL REFERENCES seller_product(hero_product_code), center_code varchar(20) NULL REFERENCES center(center_code), -- NULL = 전 센터 공통 schedule_type varchar(4) NOT NULL CHECK (schedule_type IN ('DOW','DATE')), dow smallint NULL CHECK (dow BETWEEN 0 AND 6), -- 0=월 … 6=일 (프로토와 동일) target_date date NULL, -- 오늘~+3개월은 서비스 검증 limit_qty integer NOT NULL CHECK (limit_qty >= 1), deadline_time time NOT NULL DEFAULT '16:00', -- 고정. 입력 UI 없음 use_yn char(1) NOT NULL DEFAULT 'Y', reg_id varchar(100), reg_dt timestamp NOT NULL DEFAULT now(), upd_id varchar(100), upd_dt timestamp, CHECK ((schedule_type = 'DOW' AND dow IS NOT NULL AND target_date IS NULL) OR (schedule_type = 'DATE' AND target_date IS NOT NULL AND dow IS NULL)) ); -- 행 단위 유일성: 같은 히어로×센터×요일(또는 날짜)에 활성 행 1개. NULL(공통)도 같은 값으로 취급 → PG15+ CREATE UNIQUE INDEX ux_hqs_slot ON hero_qty_schedule (hero_product_code, center_code, schedule_type, dow, target_date) NULLS NOT DISTINCT WHERE use_yn = 'Y'; -- PG15 미만이면: (hero_product_code, coalesce(center_code,'ALL'), schedule_type, coalesce(dow,-1), coalesce(target_date,'0001-01-01')) 로 대체 CREATE INDEX ix_hqs_lookup ON hero_qty_schedule (hero_product_code, center_code) WHERE use_yn = 'Y'; CREATE INDEX ix_hqs_item ON hero_qty_schedule (item_id); -- 기존 상시 제한은 그대로: seller_product.order_limit · seller_product_center_limit (변경 없음)
주문 시점 조회 예시 (D-1 가정: 기준일 = confirm_date)
-- 1) 매칭 스케줄 (최대 1행 — §04 중복 규칙) SELECT limit_qty FROM hero_qty_schedule WHERE hero_product_code = :hero AND use_yn = 'Y' AND (center_code = :center OR center_code IS NULL) AND ((schedule_type = 'DATE' AND target_date = :d) OR (schedule_type = 'DOW' AND dow = (EXTRACT(isodow FROM :d::date) - 1))) -- isodow 1=월 → 0=월 FOR UPDATE; -- 동시 주문 직렬화 -- 2) 현재 집계 (상태 집합은 D-1 결정에 따름) SELECT coalesce(sum(quantity - cancel_quantity), 0) AS used FROM member_order_details WHERE hero_product_code = :hero AND center_code = :center AND confirm_date = :d AND order_status_id NOT IN ('CANCEL_COMPLETE', 'VIRTUAL_EXPIRY'); -- 3) used + :qty > limit_qty → 주문 불가 (D-2 기본값 = 차단)
- item_id는 목록의 '항목'을 식별한다(같은 등록에서 생긴 요일/날짜×센터 행 묶음). 헤더/디테일 2테이블로 나누는 것과 동치이며, 초안은 단일 테이블 +
item_id로 단순하게 간다. - 삭제는 물리 삭제를 권장한다(설정 데이터, 이력 요구 없음).
use_yn은 일시 중지 용도가 생길 때만 의미가 있고, 유니크 인덱스는use_yn='Y'조건이라 재등록과 충돌하지 않는다. - 하나의 항목은 한 방식(DOW 또는 DATE). 편집에서 방식을 바꾸면 그
item_id의 행을 지우고 다시 넣는다. - 중복 규칙(§04)이 서비스 계층에서 지켜지면 매칭 행은 최대 1개다. 규칙을 완화할 경우에만 우선순위(특정날짜 > 요일, 센터별 > 공통)를 추가한다.
미정 · 논의 현황 — 화면 미정 없음
이전 차수에서 열려 있던 항목이 어떻게 닫혔는지. 남은 것은 §05 개발 논의뿐.
| 이전 미정 | 정리 | 상태 |
|---|---|---|
| 마감시각 | 전 항목 16:00 고정. 센터·요일 편차 없음, 입력 UI 없음. | 확정 |
| 확정 정의 | 화면 밖. 백엔드 개발 논의 D-1로 이동. | 결정필요 |
| 오버 처리 | 화면 밖. 백엔드 개발 논의 D-2로 이동(기본 = 차단·유지). | 결정필요 |
| 상시 제한 | MD-13 범위 아님. 기존 수량 제한(order_limit·seller_product_center_limit) 영역 — 상시면 상품 제외·공급처 확보. | 확정 |
| 상품 픽커 단일/다중 | 단일(라디오). 한 설정 = 한 히어로. 기존 어드민 모달 재사용. | 확정 |
| 주별 방식 | 폐기. 요일별·특정날짜만. | 확정 |
| 공급사 수정 권한 | 1차 MD 전용. 허용 범위·시기는 D-3. | 결정필요 |
| DDL 확정 | D-1(기준일 컬럼)과 운영 PG 버전 확인 뒤 확정. | 의존 |
<title>의 "v14" 표기는 이 문서 기준으로 갱신이 필요하다. 문서가 프로토보다 앞선 상태.산출물 · 다음 단계
| 산출물 | 위치 |
|---|---|
| 클릭 프로토 v15 | https://md-g5-13-app.pages.dev/ (3뷰 · 우측 개발범위 주석 · 소스 archive_live/md-g5-13-app/index.html) |
| 기획·개발 문서 | 이 문서 (rev 2026-09-03) |
| 티켓 | PLD-1032 |
- 개발 논의 2건 결정 — D-1 확정 시점(상태 집합 + 기준일 컬럼) · D-2 초과 시 처리(차단·유지 기본값 확인). D-3 권한은 1차 제외 여부만.
- DDL 확정 — 운영·스테이지 PG 버전 확인(
NULLS NOT DISTINCT가능 여부) →hero_qty_schedule생성. 기존 상시 제한 테이블은 손대지 않음. - 주문 시점 검사 — 매칭→집계→판정, 동시성 직렬화,
member_order_details집계 인덱스 추가. 취소/반품 복구는 별도 로직 없음(집계 방식). - 화면 구현 — 목록·신규/수정·캘린더 3뷰. 상품 선택은 기존 어드민 모달 호출(단일 선택), 센터 검색 모달은
center.use_flag기준. 수정 저장에도 중복 검사. - 프로토 정리 — 주석 레일 "상시 제한 미정" 삭제·타이틀 v15·[엑셀 업로드] 자리표시자 제거 또는 별도 차수 표기.
실측 출처: 개발DB 스키마(admin-db MCP, 구조 확인용) · 라이브 프로토 코드(md-g5-13-app.pages.dev) · 센터 수는 스테이지 어드민 /mfcCenterManage
변경 이력: 초기안=기존 수량제한에 요일 탭 → 확정안=독립 스케줄 화면(요일별·특정날짜)