MD-15 · 고객별 일회성 수량제한

고객별 일회성 수량제한 (같은 코드·별도 노출)

정상판매 라이브를 유지한 채 같은 히어로코드에 일회성·기간·업장별 한정수량 노출을 추가하고, 결제완료 기준으로 소진을 카운팅한다.

🔴 결정 대기 상품관리 일회성·선착순 결제완료 카운팅
➕ 기능 추가
무엇 — 정상판매 라이브를 유지한 채 같은 히어로코드에 일회성·기간·업장별 한정수량 노출을 추가하고, 결제완료 기준으로 소진을 카운팅한다.📍 위치: 상품관리 › 수량 제한 관리

핵심 결정

카운팅 기준
결제완료만 카운트(입금대기 제외), 한도 초과분은 최종 발주 취소
노출 방식
같은 히어로코드를 정상가 라이브 + 일회성 노출로 별도 진열(선착순·샘플링)
제한 축
업장별 횟수·수량 + 전체 한정 풀 + 기간(effective~due)
재고 연동
재고운영 코드는 가용 재고 범위 내에서만 소진 허용
선행 의존
선행A 일회성 특가 가격표와 통합 검토 — 결정 필요
01

화면 — 먼저 보기

이 티켓이 실제로 어떤 화면이 되는지부터

🚧 [결정 대기] 본 화면을 독립 운영할지, 선행A(일회성 특가) 가격표에 일회성·기간·한정수량 축으로 흡수할지 미확정 — 스키마는 흡수 가능하도록 설계했다.
현행 화면 · 실제 캡처
현행 「고객 노출/제한」 — 일회성 수량제한 추가
현행 「고객 노출/제한」 — 일회성 수량제한 추가
변경안 · 이렇게 바뀜
상품관리 › 수량 제한 관리기능 추가
유형 ▾상태 ▾🔍 히어로코드·상품명 검색일회성 제한 등록소진 현황 CSV
히어로코드상품명제한 유형 🆕적용 기간 🆕업장별 횟수/수량 🆕일회성 특가 🆕소진/한정 🆕상태 🆕
HR-0032891국산 대파 1kg일회성07.22~07.311회 · 50개5,900 (정상 7,900)1,240 / 3,000진행중
HR-0011045무항생제 계란 30구일회성07.15~07.201회 · 20개6,500 (정상 8,900)2,000 / 2,000소진(close)
HR-0044120깐마늘 500g상시3개/회진행중

▲ 수량 제한 관리 목록 — 바뀌는 컬럼 🆕 강조(실 데이터 예시)

1
제한 조건 등록 — 어드민이 히어로코드를 검색해 '일회성 제한 등록'을 연다. 기간·업장별 횟수/수량·한정 풀·일회성 특가·재고연동 여부를 입력한다.
2
앱 별도 노출 — 정상가 라이브는 그대로 유지되고, 같은 코드에 일회성 조건(선착순·샘플링)이 별도로 추가 노출된다.
3
결제완료 카운팅 — 업장이 결제완료하면 소진 원장에 기록된다. 입금대기 주문은 카운트하지 않는다.
4
초과·소진 가드 — 업장 한도 초과분은 최종 발주 확정 단계에서 취소되고, 한정 풀·가용 재고가 소진되면 노출을 close 한다.
5
만료·전환 처리 — 기간 만료 시 EXPIRED로 종료하고, 상시↔일회성 전환 시 누적 개수 처리 규칙(이월/초기화)을 적용한다.
6
소진 현황 모니터링 — 어드민이 업장별 소진·잔여 풀·close 상태를 목록과 원장 상세에서 확인한다.
02

정책 / 정의

용어를 못 박고, 규칙을 명확히

용어 정의
용어정의
상시 수량제한기간·유형 구분 없이 업장별 최대 구매 개수만 제한하는 현행 기능(seller_product_member_limit, PK=히어로코드·limit_count만 보유).
일회성 수량제한기간·한정수량·업장별 횟수 축을 갖는 프로모션성 제한(신규). 같은 코드에 조건부로 추가 노출.
별도 노출같은 히어로코드를 정상가 라이브와 분리해 일회성 조건(선착순·샘플링)으로 추가 진열하는 방식.
결제완료 카운팅입금대기는 세지 않고 결제완료 시점에만 소진 수량을 원장에 반영하는 규칙.
한정 풀(pool)전체 선착순 한정 수량. 소진되면 일회성 노출을 close(종료).
업장식당(사장님) 단위. member_id(varchar20)로 식별하며 업장별 횟수·수량 한도의 기준.
최종 발주 취소동시성 등으로 한도를 초과해 결제된 분을 발주 확정 단계에서 되돌리는 보정 처리.
정책 (규칙)
#규칙비고
1정상판매 라이브는 유지하고 일회성 노출을 같은 히어로코드에 추가한다.두 노출 공존 가능(정상 7,900 / 일회성 5,900). 정상가 진열에는 영향 없음.
2소진 카운팅은 결제완료 기준이며 입금대기 주문은 카운트하지 않는다.결제 취소·환불 시 해당 소진분을 원복(가정: cancel_flag 처리).
3업장별 한도(횟수·수량) 초과 결제는 최종 발주 확정 단계에서 취소한다.동시성으로 초과가 발생할 수 있어 발주 취소로 보정(가정: 자동 취소 + 업장 알림).
4재고운영 코드는 가용 재고 범위 내에서만 일회성 소진을 허용한다.재고가 한정 풀보다 우선. 재고 소진 시 풀 잔량과 무관하게 close.
5일회성 소진(횟수·수량 도달) 후 동일 업장의 재구매를 차단한다.ledger의 업장별 누적 카운트로 판정. 정상가 노출로는 계속 구매 가능.
6기간(effective~due) 만료 시 자동 EXPIRED 처리하고 노출을 종료한다.가정: 일 배치 + 조회 시점 실시간 가드 병행.
7상시↔일회성 전환 시 기존 누적 개수 처리 규칙을 적용한다.결정 필요 — 이월/초기화 중 택1. 기본안: 초기화하되 이력은 원장에 보존.
8한정 풀 소진 시 일회성 노출을 자동 close 한다.현행 상시 테이블엔 풀 개념이 없어 신규 테이블에서 관리.
9선행A(일회성 특가)와 통합 시 특가·기간·한정수량 축을 그쪽으로 이관한다.결정 대기. DDL은 promo_price를 보유해 흡수/독립 모두 대비.
03

ERD

데이터 구조 · 관계 · DDL

seller_product_member_limit READ
hero_product_codePK varchar(20)
limit_countinteger
created_byvarchar(20)
created_attimestamp
현행 상시 고객별 수량제한. 기간·유형·풀 없이 히어로코드당 개수만 처리(이번 기능이 이 한계를 확장).
seller_product_onetime_limit 신규
idPK bigserial
hero_product_codeFK varchar(20)
center_codevarchar(20)
per_member_order_countinteger
per_member_qty_limitinteger
total_qty_poolinteger
promo_priceinteger
stock_bound_flagboolean
effective_datedate
due_datedate
statusvarchar(10)
use_flagboolean
created_byvarchar(20)
created_attimestamp
updated_byvarchar(20)
updated_attimestamp
일회성 수량제한 노출 설정. 기간·업장별 횟수/수량·한정 풀·일회성 특가·재고연동 보유.
seller_product_limit_ledger 신규
idPK bigserial
onetime_limit_idFK bigint
member_idvarchar(20)
member_order_idvarchar(16)
counted_qtyinteger
counted_attimestamp
cancel_flagboolean
created_attimestamp
소진 원장(결제완료 기준). 업장별 누적·한정 풀 소진·재구매 차단·초과 취소 판정의 근거.
sample_manage READ
idPK integer
hero_product_codevarchar(100)
order_limitinteger
effective_datedate
due_datedate
use_flagboolean
기간·한정수량·업장 노출 패턴의 기존 선례(샘플링). 신규 스키마 설계 참고용.
seller_product_onetime_limit.hero_product_code → seller_product_member_limit.hero_product_code (동일 코드에 상시·일회성 공존)
seller_product_limit_ledger.onetime_limit_id → seller_product_onetime_limit.id (N:1, 결제완료 소진)
seller_product_limit_ledger.member_id → member.member_id (업장별 누적 카운트·재구매 차단)
seller_product_onetime_limit.hero_product_code → seller_product.hero_product_code (상품 마스터)
-- ============================================================
-- MD-15 고객별 일회성 수량제한
-- 현행 seller_product_member_limit(상시·개수만)의 한계를 확장:
-- 기간 / 업장별 횟수·수량 / 한정 풀 / 일회성 특가 / 재고연동을 신규 테이블로 관리
-- ============================================================

-- 1) 일회성 수량제한 노출 설정
CREATE TABLE seller_product_onetime_limit (
    id                      BIGSERIAL   PRIMARY KEY,                 -- 일회성 제한 ID
    hero_product_code       VARCHAR(20) NOT NULL,                    -- 대상 히어로코드(정상 라이브와 동일 코드)
    center_code             VARCHAR(20),                             -- 재고운영 시 대상 센터(성동광진 등, NULL=전체)
    per_member_order_count  INTEGER     NOT NULL DEFAULT 1,          -- 업장별 허용 횟수(예: 1회)
    per_member_qty_limit    INTEGER     NOT NULL,                    -- 업장별 최대 수량(예: 50개)
    total_qty_pool          INTEGER,                                 -- 전체 선착순 한정 풀(NULL=풀 무제한)
    promo_price             INTEGER,                                 -- 일회성 특가(NULL=가격 변동 없음, 선행A 통합 대비)
    stock_bound_flag        BOOLEAN     NOT NULL DEFAULT FALSE,      -- 재고운영 코드 여부(TRUE=가용 재고 내에서만 소진)
    effective_date          DATE        NOT NULL,                    -- 적용 시작일
    due_date                DATE        NOT NULL,                    -- 적용 종료일(경과 시 EXPIRED)
    status                  VARCHAR(10) NOT NULL DEFAULT 'OPEN',     -- OPEN / CLOSE(풀·재고 소진) / EXPIRED(기간 만료)
    use_flag                BOOLEAN     NOT NULL DEFAULT TRUE,       -- 사용 여부
    created_by              VARCHAR(20) NOT NULL,                    -- 등록자
    created_at              TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 등록 시각
    updated_by              VARCHAR(20),                             -- 수정자
    updated_at              TIMESTAMP                                -- 수정 시각
);
COMMENT ON TABLE seller_product_onetime_limit IS 'MD-15 일회성 수량제한 노출 설정(같은 코드 별도 노출·선착순/샘플링)';
CREATE INDEX ix_onetime_limit_code_status ON seller_product_onetime_limit (hero_product_code, status);
-- 같은 코드·센터·기간이 겹치는 활성 일회성 노출 중복 방지(운영 가드)
CREATE UNIQUE INDEX uq_onetime_limit_active
    ON seller_product_onetime_limit (hero_product_code, COALESCE(center_code, ''), effective_date, due_date)
    WHERE use_flag = TRUE;

-- 2) 소진 원장(결제완료 기준)
CREATE TABLE seller_product_limit_ledger (
    id                BIGSERIAL   PRIMARY KEY,                       -- 원장 ID
    onetime_limit_id  BIGINT      NOT NULL
                       REFERENCES seller_product_onetime_limit(id),  -- 대상 일회성 제한
    member_id         VARCHAR(20) NOT NULL,                         -- 업장(식당)
    member_order_id   VARCHAR(16) NOT NULL,                         -- 주문번호(결제완료 주문)
    counted_qty       INTEGER     NOT NULL,                         -- 소진 수량
    counted_at        TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP,-- 결제완료 카운팅 시각(입금대기는 미기록)
    cancel_flag       BOOLEAN     NOT NULL DEFAULT FALSE,           -- 취소(한도초과 발주취소/환불)로 소진 원복 여부
    created_at        TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE seller_product_limit_ledger IS 'MD-15 일회성 수량제한 소진 원장 — 업장별 누적·풀 소진·재구매 차단 근거';
-- 업장별 유효 소진 집계 가속(재구매 차단·한도 판정)
CREATE INDEX ix_ledger_limit_member ON seller_product_limit_ledger (onetime_limit_id, member_id) WHERE cancel_flag = FALSE;
04

화면 상세 — 세부 표·규칙

목록 외 품목표·모달·규칙 등 세부 화면

일회성 제한 등록 모달
항목입력 / 규칙
적용 기간effective_date ~ due_date (필수, 만료 시 자동 EXPIRED)
업장별 제한횟수 1회 · 수량 50개 (초과 결제 시 최종 발주 취소)
한정 풀·재고전체 3,000개 / 재고운영 코드는 가용재고 내 (소진 시 close)
일회성 특가5,900원 (정상가와 별도 노출·선택 입력)
저장 시 seller_product_onetime_limit 1행 생성. 정상가 라이브 진열에는 영향 없음.
소진 원장 (업장별 상세)
업장(member_id)주문번호소진 수량카운팅 시각상태
seller_882301ORD240722009125007.22 09:14완료(한도도달)
seller_774120ORD240722009452007.22 10:02완료
seller_882301ORD240722011803007.22 15:40취소(한도초과·발주취소)
결제완료만 집계(cancel_flag=FALSE). 입금대기·한도초과 취소분은 소진에서 제외 표시.