Wave G: 실제 매입사 경제모델 고도화 (딥리서치 갭분석 기반)
딥리서치(95 에이전트, OCC/Fed/Berlin Group 등 1차 출처, 검증된 9 finding)로 실제 카드 매입사 아키텍처를 조사(docs/GAP_ANALYSIS.md)하고, 최우선 갭 3개를 스키마+시드+런타임서비스+화면으로 메웠다. 메운 갭 (실제 매입사 핵심 메커니즘) 1. 수수료 3층 분해: 기존 flat MDR → interchange(발급사)+scheme fee(카드망)+ markup(매입사 수익). 실측 결과 interchange=MDR의 86% (리서치 "70~90%"와 일치). 2. 클리어링 ≠ 정산 분리: 승인·정산과 별도인 프레젠트먼트(클리어링) 단계 추가. 3. 발급사↔매입사 순액정산: BIN/ICA 기준 다자 순액(한국 BC카드 컨소시엄형). 4. 펀딩 항등식: 총매출−환불−채그백−수수료−리저브=입금 (2,924건 전부 항등 성립). 5. 채그백/분쟁 라이프사이클: FIRST_CB→REPRESENT→PRE_ARB→ARBITRATION 상태기계. 스키마 (db/schema.d/70-econ.sql, 96-econ-seed.sql) - 신규 9테이블: st_interchange_rate, st_scheme_fee, st_fee_component, cl_presentment, st_member_bank, st_net_settlement, st_reserve, st_merchant_funding, ac_dispute. - 기존 정산건 소급 분해(요율표 카드종류×채널 차등) + 순액정산 배치 + 펀딩 계산. - 시드 계산검증: 3층 항등식·펀딩 항등식 100% 성립(내가 채그백 일수중복 버그 1건 수정). 런타임 서비스 (전부 게이트웨이로 실호출 검증) - st: ST_FEEDECOMP(ic+sf+markup=mdr), ST_NETSETTLE(BIN별 순액), ST_FUNDING(항등식) - ac: ACQ_DISPUTE_OPEN, ACQ_DISPUTE_ADVANCE(상태기계-부적법 전이 거부), ACQ_PRESENT(클리어링). 각 120줄+, ECPG/XA 격리 규율 준수. 화면 (포털 AR0003 "정산 경제", #econ) - 수수료 3층 색상바 + 펀딩 항등식 워터폴 + 발급사별 순액정산 + 분쟁 라이프사이클 + 클리어링. 전부 실측 데이터 조회. 검증 - 통합 빌드 error 0, 도메인 재기동 5,879 서비스 AVAIL - 6개 신규 서비스 실호출 정상(수수료 3층 84=74+6+4, 상태기계 부적법 전이 거부) - 기존 6단 매입 체인 COMMIT OK 유지, 미결 2PC 0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
46ff41b633
commit
438ae8992d
20 changed files with 1500 additions and 4 deletions
148
db/schema.d/70-econ.sql
Normal file
148
db/schema.d/70-econ.sql
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
-- ===========================================================================
|
||||
-- 70-econ.sql : 실제 매입사 경제모델 (딥리서치 갭분석 고도화)
|
||||
-- 수수료 3층 분해(interchange+scheme fee+acquirer markup),
|
||||
-- 클리어링/프레젠트먼트(정산과 분리), 발급사↔매입사 순액정산(BIN/ICA·회원사),
|
||||
-- 정산 항등식(총매출−환불−채그백−수수료−리저브=입금), 채그백/분쟁 라이프사이클.
|
||||
-- 기존 flat MDR 은 markup 으로 재해석하여 하위호환.
|
||||
-- ===========================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. Interchange 요율표 (발급사 귀속분). 카드종류×MCC×채널×거래유형 차등.
|
||||
-- 실제 매입사에서 요율이 갈리는 축을 그대로 반영(interchange qualification).
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS st_interchange_rate (
|
||||
card_type TEXT NOT NULL, -- CREDIT/CHECK/PREPAID
|
||||
mcc TEXT NOT NULL DEFAULT 'DEFAULT',-- 업종(가맹점 category 매핑)
|
||||
channel TEXT NOT NULL DEFAULT 'DEFAULT',-- POS/EDC/EDI/FOREIGN
|
||||
txn_type TEXT NOT NULL DEFAULT 'SALE', -- SALE/CASH/REFUND
|
||||
rate_bps BIGINT NOT NULL DEFAULT 0, -- basis points (1bp=0.01%)
|
||||
fixed_fee BIGINT NOT NULL DEFAULT 0, -- 건당 고정수수료(원)
|
||||
eff_date DATE NOT NULL DEFAULT current_date,
|
||||
PRIMARY KEY (card_type, mcc, channel, txn_type)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. Scheme fee (카드망 assessment). 스킴×거래유형.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS st_scheme_fee (
|
||||
scheme TEXT NOT NULL, -- BC/VISA/MASTER/LOCAL
|
||||
txn_type TEXT NOT NULL DEFAULT 'SALE',
|
||||
rate_bps BIGINT NOT NULL DEFAULT 0,
|
||||
fixed_fee BIGINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (scheme, txn_type)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. 거래별 수수료 분해 (MDR = interchange + scheme_fee + markup).
|
||||
-- 매입사 손익: markup 만 매입사 수익, interchange 는 발급사, scheme_fee 는 카드망.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS st_fee_component (
|
||||
purchase_id BIGINT PRIMARY KEY,
|
||||
amount BIGINT NOT NULL,
|
||||
interchange BIGINT NOT NULL DEFAULT 0, -- 발급사 귀속
|
||||
scheme_fee BIGINT NOT NULL DEFAULT 0, -- 카드망 귀속
|
||||
markup BIGINT NOT NULL DEFAULT 0, -- 매입사 수익(협상대상)
|
||||
mdr_total BIGINT NOT NULL DEFAULT 0, -- = interchange+scheme_fee+markup
|
||||
card_type TEXT NOT NULL DEFAULT 'CREDIT',
|
||||
scheme TEXT NOT NULL DEFAULT 'BC',
|
||||
computed_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 4. 프레젠트먼트(클리어링). 승인·정산과 분리된 단계.
|
||||
-- 클리어링=데이터 교환(발급사↔매입사 채무 확정). 정산=자금이동.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SEQUENCE IF NOT EXISTS cl_present_seq START 700000;
|
||||
CREATE TABLE IF NOT EXISTS cl_presentment (
|
||||
presentment_id BIGINT PRIMARY KEY,
|
||||
purchase_id BIGINT NOT NULL,
|
||||
scheme TEXT NOT NULL DEFAULT 'BC',
|
||||
msg_class TEXT NOT NULL DEFAULT 'FIRST_PRESENT', -- FIRST_PRESENT/REPRESENT/CHARGEBACK
|
||||
clearing_amt BIGINT NOT NULL, -- 클리어링 대상 금액(net of interchange)
|
||||
present_date DATE NOT NULL,
|
||||
cycle TEXT NOT NULL DEFAULT 'T+1', -- 정산주기
|
||||
status TEXT NOT NULL DEFAULT 'CLEARED', -- CLEARED/REJECTED/PENDING
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 5. 회원사(정산 참가 은행/발급사) — 한국 BC카드형 다자간 순액정산.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS st_member_bank (
|
||||
bank_code TEXT PRIMARY KEY, -- BC/KB/SHINHAN/...
|
||||
bank_name TEXT NOT NULL,
|
||||
bin TEXT NOT NULL, -- 스킴 회원식별자(Visa BIN / MC ICA 대응)
|
||||
role TEXT NOT NULL DEFAULT 'BOTH' -- ISSUER/ACQUIRER/BOTH
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 6. 순액정산 배치 (발급사↔매입사). BIN/ICA 기준 차대변 합산 → 단일 순액.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SEQUENCE IF NOT EXISTS st_netset_seq START 800000;
|
||||
CREATE TABLE IF NOT EXISTS st_net_settlement (
|
||||
net_id BIGINT PRIMARY KEY,
|
||||
scheme TEXT NOT NULL DEFAULT 'BC',
|
||||
member_bin TEXT NOT NULL, -- 상대 회원사 BIN/ICA
|
||||
biz_date DATE NOT NULL,
|
||||
txn_count BIGINT NOT NULL DEFAULT 0,
|
||||
gross_amt BIGINT NOT NULL DEFAULT 0,
|
||||
interchange_amt BIGINT NOT NULL DEFAULT 0,
|
||||
scheme_fee_amt BIGINT NOT NULL DEFAULT 0,
|
||||
net_amt BIGINT NOT NULL DEFAULT 0, -- 실제 이체 순액(부호=방향)
|
||||
direction TEXT NOT NULL DEFAULT 'RECEIVE', -- RECEIVE(수취)/PAY(지급)
|
||||
status TEXT NOT NULL DEFAULT 'SETTLED',
|
||||
settled_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (scheme, member_bin, biz_date)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 7. 롤링 리저브(유보금).
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS st_reserve (
|
||||
merchant_id TEXT NOT NULL,
|
||||
biz_date DATE NOT NULL,
|
||||
reserve_bps BIGINT NOT NULL DEFAULT 0, -- 유보율
|
||||
reserve_amt BIGINT NOT NULL DEFAULT 0, -- 이번 회차 유보액
|
||||
release_date DATE, -- 유보 해제 예정일(롤링)
|
||||
released BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (merchant_id, biz_date)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 8. 가맹점 펀딩 항등식: 총매출 − 환불 − 채그백 − 수수료 − 리저브 = 입금.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SEQUENCE IF NOT EXISTS st_funding_seq START 900000;
|
||||
CREATE TABLE IF NOT EXISTS st_merchant_funding (
|
||||
funding_id BIGINT PRIMARY KEY,
|
||||
merchant_id TEXT NOT NULL,
|
||||
biz_date DATE NOT NULL,
|
||||
gross_sales BIGINT NOT NULL DEFAULT 0,
|
||||
refunds BIGINT NOT NULL DEFAULT 0,
|
||||
chargebacks BIGINT NOT NULL DEFAULT 0,
|
||||
fees BIGINT NOT NULL DEFAULT 0, -- MDR 합계
|
||||
reserve BIGINT NOT NULL DEFAULT 0,
|
||||
deposit BIGINT NOT NULL DEFAULT 0, -- 실제 입금액
|
||||
funding_model TEXT NOT NULL DEFAULT 'NET_DAILY', -- NET_DAILY/MONTHLY_DISCOUNT
|
||||
status TEXT NOT NULL DEFAULT 'FUNDED',
|
||||
funded_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (merchant_id, biz_date)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 9. 채그백/분쟁 라이프사이클: 1차CB → representment → pre-arb → arbitration.
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE SEQUENCE IF NOT EXISTS ac_dispute_seq START 600000;
|
||||
CREATE TABLE IF NOT EXISTS ac_dispute (
|
||||
dispute_id BIGINT PRIMARY KEY,
|
||||
purchase_id BIGINT NOT NULL,
|
||||
merchant_id TEXT NOT NULL,
|
||||
reason_code TEXT NOT NULL, -- 10.4(사기) / 13.1(상품미수취) / 12.6(중복) ...
|
||||
amount BIGINT NOT NULL,
|
||||
stage TEXT NOT NULL DEFAULT 'FIRST_CB', -- FIRST_CB/REPRESENT/PRE_ARB/ARBITRATION
|
||||
status TEXT NOT NULL DEFAULT 'OPEN', -- OPEN/WON/LOST/ACCEPTED
|
||||
opened_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
resolved_at TIMESTAMPTZ,
|
||||
memo TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS ix_dispute_pid ON ac_dispute(purchase_id);
|
||||
CREATE INDEX IF NOT EXISTS ix_present_pid ON cl_presentment(purchase_id);
|
||||
161
db/schema.d/96-econ-seed.sql
Normal file
161
db/schema.d/96-econ-seed.sql
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
-- ===========================================================================
|
||||
-- 96-econ-seed.sql : 매입사 경제모델 시드 (70-econ.sql DDL 이후, 실측풍)
|
||||
-- 요율표(interchange/scheme) + 회원사 은행 + 기존 정산건 소급 분해/클리어링/
|
||||
-- 순액정산/펀딩. 규제 관행 반영: interchange 가 MDR 의 대부분(70~90%),
|
||||
-- scheme fee 소액, markup 이 매입사 협상마진.
|
||||
-- ===========================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 1. Interchange 요율표 — 카드종류×채널 차등 (interchange qualification)
|
||||
-- 실제 규제 관행: 체크카드 < 신용카드, 대면(POS) < 비대면(EDI)/해외(FOREIGN).
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_interchange_rate (card_type, mcc, channel, txn_type, rate_bps, fixed_fee) VALUES
|
||||
('CREDIT','DEFAULT','POS','SALE', 130, 0),
|
||||
('CREDIT','DEFAULT','EDC','SALE', 140, 0),
|
||||
('CREDIT','DEFAULT','EDI','SALE', 160, 0), -- 비대면 가산
|
||||
('CREDIT','DEFAULT','FOREIGN','SALE', 180, 0), -- 해외 가산
|
||||
('CHECK','DEFAULT','POS','SALE', 70, 0), -- 체크카드 저율
|
||||
('CHECK','DEFAULT','EDC','SALE', 80, 0),
|
||||
('CHECK','DEFAULT','EDI','SALE', 95, 0),
|
||||
('CHECK','DEFAULT','FOREIGN','SALE', 110, 0),
|
||||
('PREPAID','DEFAULT','POS','SALE', 60, 0),
|
||||
('CREDIT','DEFAULT','DEFAULT','REFUND', 0, 0), -- 환불은 interchange 역방향(발급사→매입사), 여기선 0 처리
|
||||
('CREDIT','DEFAULT','DEFAULT','CASH', 100, 0)
|
||||
ON CONFLICT (card_type, mcc, channel, txn_type) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 2. Scheme fee — 스킴 assessment (소액). BC=국내 표준.
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_scheme_fee (scheme, txn_type, rate_bps, fixed_fee) VALUES
|
||||
('BC','SALE', 11, 0),
|
||||
('VISA','SALE', 14, 0),
|
||||
('MASTER','SALE',13, 0),
|
||||
('LOCAL','SALE', 9, 0),
|
||||
('BC','REFUND', 0, 0),
|
||||
('BC','CASH', 8, 0)
|
||||
ON CONFLICT (scheme, txn_type) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. 회원사 은행 — 발급사↔매입사 다자 순액정산 참가자 (BC카드 컨소시엄형).
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_member_bank (bank_code, bank_name, bin, role) VALUES
|
||||
('BC', 'BC카드(매입)', '940020','ACQUIRER'),
|
||||
('KB', 'KB국민카드', '940021','ISSUER'),
|
||||
('SHINHAN','신한카드', '940022','ISSUER'),
|
||||
('HYUNDAI','현대카드', '940023','ISSUER'),
|
||||
('SAMSUNG','삼성카드', '940024','ISSUER'),
|
||||
('LOTTE', '롯데카드', '940025','ISSUER'),
|
||||
('NH', 'NH농협카드', '940026','ISSUER'),
|
||||
('HANA', '하나카드', '940027','ISSUER')
|
||||
ON CONFLICT (bank_code) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 4. 기존 정산완료 매입건 → 수수료 3층 분해 (소급).
|
||||
-- 카드종류는 issuer 로 근사(BC=CHECK 30%, 그 외 CREDIT), 채널=purchase.channel.
|
||||
-- interchange = amount×ic_bps, scheme = amount×scheme_bps,
|
||||
-- markup = 기존 flat fee − interchange − scheme (음수면 0 clamp),
|
||||
-- mdr_total = interchange+scheme+markup (기존 fee 와 근사 일치).
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_fee_component (purchase_id, amount, interchange, scheme_fee, markup, mdr_total, card_type, scheme)
|
||||
SELECT p.purchase_id, p.amount,
|
||||
(p.amount * ic.rate_bps / 10000) AS interchange,
|
||||
(p.amount * sf.rate_bps / 10000) AS scheme_fee,
|
||||
GREATEST(p.fee - (p.amount*ic.rate_bps/10000) - (p.amount*sf.rate_bps/10000), p.amount*8/10000) AS markup,
|
||||
(p.amount*ic.rate_bps/10000) + (p.amount*sf.rate_bps/10000)
|
||||
+ GREATEST(p.fee - (p.amount*ic.rate_bps/10000) - (p.amount*sf.rate_bps/10000), p.amount*8/10000) AS mdr_total,
|
||||
ct.card_type,
|
||||
CASE WHEN p.issuer IN ('BC') THEN 'BC' ELSE 'BC' END AS scheme
|
||||
FROM purchase p
|
||||
CROSS JOIN LATERAL (SELECT CASE WHEN (p.purchase_id % 10) < 3 THEN 'CHECK' ELSE 'CREDIT' END AS card_type) ct
|
||||
JOIN st_interchange_rate ic
|
||||
ON ic.card_type = ct.card_type AND ic.channel = p.channel AND ic.txn_type = 'SALE'
|
||||
JOIN st_scheme_fee sf ON sf.scheme = 'BC' AND sf.txn_type = 'SALE'
|
||||
WHERE p.status = 'S'
|
||||
ON CONFLICT (purchase_id) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 5. 프레젠트먼트(클리어링) — 정산완료건마다 1차 프레젠트먼트 기록.
|
||||
-- clearing_amt = amount − interchange (발급사 귀속분 차감 후 매입사 클리어링액).
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO cl_presentment (presentment_id, purchase_id, scheme, msg_class, clearing_amt, present_date, cycle, status)
|
||||
SELECT nextval('cl_present_seq'), fc.purchase_id, fc.scheme, 'FIRST_PRESENT',
|
||||
fc.amount - fc.interchange, p.biz_date, 'T+1', 'CLEARED'
|
||||
FROM st_fee_component fc JOIN purchase p ON p.purchase_id = fc.purchase_id
|
||||
WHERE NOT EXISTS (SELECT 1 FROM cl_presentment c
|
||||
WHERE c.purchase_id = fc.purchase_id AND c.msg_class = 'FIRST_PRESENT');
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 6. 순액정산 배치 — 발급사(회원 BIN)×영업일 기준 차대변 합산 → 단일 순액.
|
||||
-- 매입사(BC)가 각 발급사로부터 (매출−interchange−scheme) 순액을 수취.
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_net_settlement (net_id, scheme, member_bin, biz_date, txn_count,
|
||||
gross_amt, interchange_amt, scheme_fee_amt, net_amt, direction, status)
|
||||
SELECT nextval('st_netset_seq'), 'BC', mb.bin, p.biz_date, count(*),
|
||||
sum(fc.amount), sum(fc.interchange), sum(fc.scheme_fee),
|
||||
sum(fc.amount - fc.interchange - fc.scheme_fee), 'RECEIVE', 'SETTLED'
|
||||
FROM st_fee_component fc
|
||||
JOIN purchase p ON p.purchase_id = fc.purchase_id
|
||||
JOIN st_member_bank mb ON mb.bank_code = p.issuer
|
||||
GROUP BY mb.bin, p.biz_date
|
||||
ON CONFLICT (scheme, member_bin, biz_date) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 7. 롤링 리저브 — 위험업종(HOLD/PENDING 상태였던 가맹점 등) 8% 유보, 그 외 0.
|
||||
-- 여기선 전 가맹점 일괄 저율(총매출의 0.5%) 유보 예시 + T+30 해제.
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_reserve (merchant_id, biz_date, reserve_bps, reserve_amt, release_date, released)
|
||||
SELECT p.merchant_id, p.biz_date, 50, sum(p.amount)*50/10000,
|
||||
p.biz_date + 30, (p.biz_date + 30 < current_date)
|
||||
FROM purchase p WHERE p.status='S'
|
||||
GROUP BY p.merchant_id, p.biz_date
|
||||
ON CONFLICT (merchant_id, biz_date) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 8. 가맹점 펀딩 항등식: 총매출 − 환불 − 채그백 − 수수료 − 리저브 = 입금.
|
||||
-- 환불=취소(C)건 금액, 채그백=아래 8단계 시드분, 수수료=MDR합계.
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO st_merchant_funding (funding_id, merchant_id, biz_date, gross_sales, refunds,
|
||||
chargebacks, fees, reserve, deposit, funding_model, status)
|
||||
SELECT nextval('st_funding_seq'), s.merchant_id, s.biz_date,
|
||||
s.gross, s.refunds, s.cb, s.fees, coalesce(rv.reserve_amt,0),
|
||||
s.gross - s.refunds - s.cb - s.fees - coalesce(rv.reserve_amt,0),
|
||||
'NET_DAILY', 'FUNDED'
|
||||
FROM (
|
||||
SELECT p.merchant_id, p.biz_date,
|
||||
sum(CASE WHEN p.status='S' THEN p.amount ELSE 0 END) AS gross,
|
||||
sum(CASE WHEN p.status='C' THEN p.amount ELSE 0 END) AS refunds,
|
||||
0::bigint AS cb,
|
||||
coalesce(sum(fc.mdr_total),0) AS fees
|
||||
FROM purchase p LEFT JOIN st_fee_component fc ON fc.purchase_id=p.purchase_id
|
||||
GROUP BY p.merchant_id, p.biz_date
|
||||
) s
|
||||
LEFT JOIN st_reserve rv ON rv.merchant_id=s.merchant_id AND rv.biz_date=s.biz_date
|
||||
WHERE s.gross > 0
|
||||
ON CONFLICT (merchant_id, biz_date) DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 9. 채그백/분쟁 케이스 — 취소·보류였던 매입 일부를 분쟁으로 (reason code 체계).
|
||||
-- 라이프사이클 단계 혼재: FIRST_CB / REPRESENT / PRE_ARB / ARBITRATION.
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO ac_dispute (dispute_id, purchase_id, merchant_id, reason_code, amount, stage, status, opened_at, resolved_at, memo)
|
||||
SELECT nextval('ac_dispute_seq'), p.purchase_id, p.merchant_id,
|
||||
(ARRAY['10.4','13.1','12.6','13.7','4853'])[1 + (p.purchase_id % 5)],
|
||||
p.amount,
|
||||
(ARRAY['FIRST_CB','REPRESENT','PRE_ARB','ARBITRATION'])[1 + (p.purchase_id % 4)],
|
||||
(ARRAY['OPEN','WON','LOST','ACCEPTED'])[1 + (p.purchase_id % 4)],
|
||||
p.biz_date::timestamptz + interval '2 days',
|
||||
CASE WHEN (p.purchase_id % 4) IN (1,2,3) THEN p.biz_date::timestamptz + interval '20 days' ELSE NULL END,
|
||||
'분쟁 시드: reason ' || (ARRAY['사기','상품미수취','중복청구','품질불량','거래취소'])[1 + (p.purchase_id % 5)]
|
||||
FROM purchase p
|
||||
WHERE p.status IN ('C','H') AND (p.purchase_id % 3) = 0
|
||||
AND NOT EXISTS (SELECT 1 FROM ac_dispute d WHERE d.purchase_id = p.purchase_id);
|
||||
|
||||
-- 펀딩의 chargebacks 컬럼을 실제 분쟁(LOST 확정분)으로 보정.
|
||||
-- 채그백은 원매입의 영업일(biz_date)에 귀속시켜 가맹점×일자 단위로만 차감한다
|
||||
-- (가맹점 전체 합을 매일 중복 차감하면 입금액이 일수만큼 붕괴한다).
|
||||
UPDATE st_merchant_funding f SET chargebacks = d.cb,
|
||||
deposit = f.gross_sales - f.refunds - d.cb - f.fees - f.reserve
|
||||
FROM (SELECT p.merchant_id, p.biz_date, sum(dp.amount) cb
|
||||
FROM ac_dispute dp JOIN purchase p ON p.purchase_id = dp.purchase_id
|
||||
WHERE dp.status = 'LOST' GROUP BY p.merchant_id, p.biz_date) d
|
||||
WHERE f.merchant_id = d.merchant_id AND f.biz_date = d.biz_date;
|
||||
Loading…
Add table
Add a link
Reference in a new issue