From bbd4a63f5a0494aa9f30af2526ca523e8b68d0cc Mon Sep 17 00:00:00 2001 From: zio Date: Fri, 24 Jul 2026 00:41:11 +0900 Subject: [PATCH] feat(db): demo/testdata seed and CMS hero images (V68-V75) - V68 demo exhibitors expand, V69 auctions+contractor, V70 dock slots - V71 sponsorship fulfillment, V72 BI history, V73 live utility orders - V75 CMS content hero images (public site) Co-Authored-By: Claude Fable 5 --- .../migration/V68__demo_exhibitors_expand.sql | 170 ++++++++++++++++++ .../V69__demo_auctions_contractor.sql | 126 +++++++++++++ .../db/migration/V70__demo_dock_slots.sql | 80 +++++++++ .../V71__demo_sponsorship_fulfillment.sql | 75 ++++++++ .../db/migration/V72__demo_bi_history.sql | 96 ++++++++++ .../V73__demo_live_utility_orders.sql | 52 ++++++ .../V75__cms_content_hero_images.sql | 39 ++++ 7 files changed, 638 insertions(+) create mode 100644 src/backend/src/main/resources/db/migration/V68__demo_exhibitors_expand.sql create mode 100644 src/backend/src/main/resources/db/migration/V69__demo_auctions_contractor.sql create mode 100644 src/backend/src/main/resources/db/migration/V70__demo_dock_slots.sql create mode 100644 src/backend/src/main/resources/db/migration/V71__demo_sponsorship_fulfillment.sql create mode 100644 src/backend/src/main/resources/db/migration/V72__demo_bi_history.sql create mode 100644 src/backend/src/main/resources/db/migration/V73__demo_live_utility_orders.sql create mode 100644 src/backend/src/main/resources/db/migration/V75__cms_content_hero_images.sql diff --git a/src/backend/src/main/resources/db/migration/V68__demo_exhibitors_expand.sql b/src/backend/src/main/resources/db/migration/V68__demo_exhibitors_expand.sql new file mode 100644 index 0000000..2494f50 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V68__demo_exhibitors_expand.sql @@ -0,0 +1,170 @@ +-- ============================================================================ +-- V68 — 데모 참가업체 대량 보강 (e-2026-live) + 월별 부스/매출 추이·손익 소스 +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 목적(소유자 시연 지시 항목 1·6): +-- ① 참가업체 현황(대시보드 위젯 + 참가업체관리 SCR): e-2026-live 참가사 6 → 24로 확대, +-- 상태 분포(부스배정/계약/승인/입금/신청) + 업종 다양화. +-- ② 경영분석(M16) 월별 부스·매출 추이: AnalyticsMapper.findMonthlyTrend 는 booth.created_at 을 +-- 'YYYY-MM' 로 그룹 → 신규 부스 created_at 을 최근 12개월에 분산해 추이 차트를 채운다. +-- ③ 손익(P&L): 매출 = 판매면적(ST_Area)×요율(master_data RATE 2250) → 부스 증가로 임대 매출 상승. +-- ---------------------------------------------------------------------------- +-- 근거(실 조회 경로 역추적): +-- • ExhibitorMapper.findExhibitors: booth(assigned_company_name!=null) ← layout.event_id +-- + booth_sale(saleStatus) + design_plan 최신(designStatus) + invoice(invoiceStatus·outstanding) +-- + event_member/company(연락처). → 참가사 = 배정 부스. +-- • DashboardMapper.findExhibitors: booth + design_plan (대시보드 참가업체 현황 위젯). +-- • AnalyticsMapper.findMonthlyTrend/findAreaAndCount: booth ST_Area·created_at (per-event 추이·KPI·P&L). +-- 원칙: e-2026-live(=workspaces[0], start_date 최소) 스코프. tenant_id='KINTEX'. PII 더미. +-- 전부 순수 INSERT ... ON CONFLICT DO NOTHING (멱등·재실행 안전). 기존 booth-live-* 불변. +-- 부스는 기존 layout 'ly-live'(H1)에 순증. booth_no = L-109..L-126(기존 L-101..L-108 비충돌). +-- geom: 기존 부스(y 0..7) 아래 y=8+ 그리드에 6m×3m 타일 배치(면적 집계용 · 충돌 무해). +-- ============================================================================ + + +-- 1) 참가업체(전시 참가사) 마스터 순증 — booth.assigned_company_name 표시명과 정합. 연락처 조인용. +INSERT INTO company (id, registration_no, name, category, region, registered, phone) VALUES + ('co-ex-11','311-81-10011','(주)오토닉스로보', '로봇/자동화', '경기', true, '031-000-2011'), + ('co-ex-12','312-81-10012','한성정밀기계', '기계/장비', '경남', true, '055-000-2012'), + ('co-ex-13','313-81-10013','대성전자', '전기/전자', '인천', true, '032-000-2013'), + ('co-ex-14','314-81-10014','스마트팩토리솔루션', 'ICT/소프트웨어','서울', true, '02-0000-2014'), + ('co-ex-15','315-81-10015','코리아센서', '센서/계측', '대전', true, '042-000-2015'), + ('co-ex-16','316-81-10016','퓨처모빌리티', '모빌리티', '경기', true, '031-000-2016'), + ('co-ex-17','317-81-10017','그린에너지테크', '에너지/환경', '충남', true, '041-000-2017'), + ('co-ex-18','318-81-10018','나노소재랩', '소재/화학', '울산', true, '052-000-2018'), + ('co-ex-19','319-81-10019','비전AI시스템', 'AI/비전', '서울', true, '02-0000-2019'), + ('co-ex-20','320-81-10020','한국물류로보틱스', '물류/유통', '부산', true, '051-000-2020'), + ('co-ex-21','321-81-10021','메디컬디바이스코', '바이오/헬스', '서울', true, '02-0000-2021'), + ('co-ex-22','322-81-10022','클린테크환경', '에너지/환경', '경기', true, '031-000-2022'), + ('co-ex-23','323-81-10023','디지털트윈랩', 'ICT/소프트웨어','대구', true, '053-000-2023'), + ('co-ex-24','324-81-10024','정밀계측기술', '센서/계측', '경기', true, '031-000-2024'), + ('co-ex-25','325-81-10025','엣지컴퓨팅코리아', 'ICT/소프트웨어','서울', true, '02-0000-2025'), + ('co-ex-26','326-81-10026','스마트팜테크', '농업/식품', '전북', true, '063-000-2026'), + ('co-ex-27','327-81-10027','3D프린팅솔루션', '제조/자동화', '경기', true, '031-000-2027'), + ('co-ex-28','328-81-10028','차세대배터리', '에너지/환경', '충북', true, '043-000-2028') +ON CONFLICT (registration_no) DO NOTHING; + + +-- 2) 부스 18(POLYGON) — layout ly-live 순증. created_at 을 최근 12개월에 분산(월별 추이 소스). +-- booth_type·premium 다양화. assigned_company_name = 위 참가사(참가업체 목록/대시보드 위젯 채움). +INSERT INTO booth (id, layout_id, booth_no, booth_type, geom, size_w_m, size_d_m, height_m, + floor_load_t_per_m2, assigned_company_name, premium, created_at) VALUES + ('booth-live-09','ly-live','L-109','island', ST_GeomFromText('POLYGON((0 8,6 8,6 11,0 11,0 8))',0), 6,3,4.0,1.0,'(주)오토닉스로보', true, now()-interval '330 day'), + ('booth-live-10','ly-live','L-110','assembled', ST_GeomFromText('POLYGON((7 8,13 8,13 11,7 11,7 8))',0), 6,3,3.0,1.0,'한성정밀기계', false, now()-interval '300 day'), + ('booth-live-11','ly-live','L-111','independent', ST_GeomFromText('POLYGON((14 8,20 8,20 11,14 11,14 8))',0), 6,3,3.5,1.0,'대성전자', false, now()-interval '270 day'), + ('booth-live-12','ly-live','L-112','corner', ST_GeomFromText('POLYGON((21 8,27 8,27 11,21 11,21 8))',0), 6,3,3.5,1.0,'스마트팩토리솔루션', false, now()-interval '240 day'), + ('booth-live-13','ly-live','L-113','assembled', ST_GeomFromText('POLYGON((0 12,6 12,6 15,0 15,0 12))',0), 6,3,3.0,1.0,'코리아센서', false, now()-interval '210 day'), + ('booth-live-14','ly-live','L-114','island', ST_GeomFromText('POLYGON((7 12,13 12,13 15,7 15,7 12))',0), 6,3,4.0,1.0,'퓨처모빌리티', true, now()-interval '180 day'), + ('booth-live-15','ly-live','L-115','assembled', ST_GeomFromText('POLYGON((14 12,20 12,20 15,14 15,14 12))',0),6,3,3.0,1.0,'그린에너지테크', false, now()-interval '165 day'), + ('booth-live-16','ly-live','L-116','independent', ST_GeomFromText('POLYGON((21 12,27 12,27 15,21 15,21 12))',0),6,3,3.5,1.0,'나노소재랩', false, now()-interval '150 day'), + ('booth-live-17','ly-live','L-117','island', ST_GeomFromText('POLYGON((0 16,6 16,6 19,0 19,0 16))',0), 6,3,4.0,1.0,'비전AI시스템', true, now()-interval '120 day'), + ('booth-live-18','ly-live','L-118','corner', ST_GeomFromText('POLYGON((7 16,13 16,13 19,7 19,7 16))',0), 6,3,3.5,1.0,'한국물류로보틱스', false, now()-interval '100 day'), + ('booth-live-19','ly-live','L-119','assembled', ST_GeomFromText('POLYGON((14 16,20 16,20 19,14 19,14 16))',0),6,3,3.0,1.0,'메디컬디바이스코', false, now()-interval '90 day'), + ('booth-live-20','ly-live','L-120','assembled', ST_GeomFromText('POLYGON((21 16,27 16,27 19,21 19,21 16))',0),6,3,3.0,1.0,'클린테크환경', false, now()-interval '75 day'), + ('booth-live-21','ly-live','L-121','independent', ST_GeomFromText('POLYGON((0 20,6 20,6 23,0 23,0 20))',0), 6,3,3.5,1.0,'디지털트윈랩', false, now()-interval '60 day'), + ('booth-live-22','ly-live','L-122','assembled', ST_GeomFromText('POLYGON((7 20,13 20,13 23,7 23,7 20))',0), 6,3,3.0,1.0,'정밀계측기술', false, now()-interval '45 day'), + ('booth-live-23','ly-live','L-123','corner', ST_GeomFromText('POLYGON((14 20,20 20,20 23,14 23,14 20))',0),6,3,3.5,1.0,'엣지컴퓨팅코리아', false, now()-interval '30 day'), + ('booth-live-24','ly-live','L-124','assembled', ST_GeomFromText('POLYGON((21 20,27 20,27 23,21 23,21 20))',0),6,3,3.0,1.0,'스마트팜테크', false, now()-interval '20 day'), + ('booth-live-25','ly-live','L-125','island', ST_GeomFromText('POLYGON((0 24,6 24,6 27,0 27,0 24))',0), 6,3,4.0,1.0,'3D프린팅솔루션', true, now()-interval '10 day'), + ('booth-live-26','ly-live','L-126','independent', ST_GeomFromText('POLYGON((7 24,13 24,13 27,7 27,7 24))',0), 6,3,3.5,1.0,'차세대배터리', false, now()-interval '4 day') +ON CONFLICT (id) DO NOTHING; + + +-- 3) 판매 오버레이(booth_sale) — 계약(sold) 다수 + held/available 소수. UNIQUE(event_id,booth_id) 멱등. +INSERT INTO booth_sale (tenant_id, id, event_id, hall_id, booth_id, booth_no, status, unit_price, + area_m2, held_by, held_until, sold_to_company, sold_by, sold_at, + blocked_reason, created_by) VALUES + ('KINTEX','bs-live-09','e-2026-live','H1','booth-live-09','L-109','sold', 6534000,18,NULL,NULL,'(주)오토닉스로보', 'demo-organizer',now()-interval '320 day',NULL,'system-seed'), + ('KINTEX','bs-live-10','e-2026-live','H1','booth-live-10','L-110','sold', 4356000,18,NULL,NULL,'한성정밀기계', 'demo-organizer',now()-interval '290 day',NULL,'system-seed'), + ('KINTEX','bs-live-11','e-2026-live','H1','booth-live-11','L-111','sold', 4791600,18,NULL,NULL,'대성전자', 'demo-organizer',now()-interval '260 day',NULL,'system-seed'), + ('KINTEX','bs-live-12','e-2026-live','H1','booth-live-12','L-112','sold', 4791600,18,NULL,NULL,'스마트팩토리솔루션','demo-organizer',now()-interval '230 day',NULL,'system-seed'), + ('KINTEX','bs-live-13','e-2026-live','H1','booth-live-13','L-113','sold', 4356000,18,NULL,NULL,'코리아센서', 'demo-organizer',now()-interval '205 day',NULL,'system-seed'), + ('KINTEX','bs-live-14','e-2026-live','H1','booth-live-14','L-114','sold', 6534000,18,NULL,NULL,'퓨처모빌리티', 'demo-organizer',now()-interval '175 day',NULL,'system-seed'), + ('KINTEX','bs-live-15','e-2026-live','H1','booth-live-15','L-115','sold', 4356000,18,NULL,NULL,'그린에너지테크', 'demo-organizer',now()-interval '160 day',NULL,'system-seed'), + ('KINTEX','bs-live-16','e-2026-live','H1','booth-live-16','L-116','sold', 4791600,18,NULL,NULL,'나노소재랩', 'demo-organizer',now()-interval '145 day',NULL,'system-seed'), + ('KINTEX','bs-live-17','e-2026-live','H1','booth-live-17','L-117','sold', 6534000,18,NULL,NULL,'비전AI시스템', 'demo-organizer',now()-interval '115 day',NULL,'system-seed'), + ('KINTEX','bs-live-18','e-2026-live','H1','booth-live-18','L-118','sold', 4791600,18,NULL,NULL,'한국물류로보틱스', 'demo-organizer',now()-interval '95 day',NULL,'system-seed'), + ('KINTEX','bs-live-19','e-2026-live','H1','booth-live-19','L-119','sold', 4356000,18,NULL,NULL,'메디컬디바이스코', 'demo-organizer',now()-interval '85 day',NULL,'system-seed'), + ('KINTEX','bs-live-20','e-2026-live','H1','booth-live-20','L-120','sold', 4356000,18,NULL,NULL,'클린테크환경', 'demo-organizer',now()-interval '70 day',NULL,'system-seed'), + ('KINTEX','bs-live-21','e-2026-live','H1','booth-live-21','L-121','sold', 4791600,18,NULL,NULL,'디지털트윈랩', 'demo-organizer',now()-interval '55 day',NULL,'system-seed'), + ('KINTEX','bs-live-22','e-2026-live','H1','booth-live-22','L-122','sold', 4356000,18,NULL,NULL,'정밀계측기술', 'demo-organizer',now()-interval '40 day',NULL,'system-seed'), + ('KINTEX','bs-live-23','e-2026-live','H1','booth-live-23','L-123','held', NULL, 18,'demo-exhibitor',now()+interval '2 day',NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-live-24','e-2026-live','H1','booth-live-24','L-124','sold', 4356000,18,NULL,NULL,'스마트팜테크', 'demo-organizer',now()-interval '15 day',NULL,'system-seed'), + ('KINTEX','bs-live-25','e-2026-live','H1','booth-live-25','L-125','sold', 6534000,18,NULL,NULL,'3D프린팅솔루션', 'demo-organizer',now()-interval '8 day',NULL,'system-seed'), + ('KINTEX','bs-live-26','e-2026-live','H1','booth-live-26','L-126','held', NULL, 18,'demo-exhibitor',now()+interval '3 day',NULL,NULL,NULL,NULL,'system-seed') +ON CONFLICT (event_id, booth_id) DO NOTHING; + + +-- 4) 설계안(design_plan) — 승인/검토/초안 분포(참가업체 designStatus·대시보드 designApproved). +INSERT INTO design_plan (id, booth_id, version, status, spec) VALUES + ('dp-live-09','booth-live-09',1,'approved', '{"theme":"island-premium","height":4.0}'::jsonb), + ('dp-live-10','booth-live-10',1,'approved', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-11','booth-live-11',1,'approved', '{"theme":"independent","height":3.5}'::jsonb), + ('dp-live-12','booth-live-12',1,'review', '{"theme":"corner","height":3.5}'::jsonb), + ('dp-live-13','booth-live-13',1,'approved', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-14','booth-live-14',1,'approved', '{"theme":"island-premium","height":4.0}'::jsonb), + ('dp-live-15','booth-live-15',1,'review', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-16','booth-live-16',1,'approved', '{"theme":"independent","height":3.5}'::jsonb), + ('dp-live-17','booth-live-17',1,'approved', '{"theme":"island-premium","height":4.0}'::jsonb), + ('dp-live-18','booth-live-18',1,'draft', '{"theme":"corner","height":3.5}'::jsonb), + ('dp-live-19','booth-live-19',1,'review', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-20','booth-live-20',1,'approved', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-21','booth-live-21',1,'draft', '{"theme":"independent","height":3.5}'::jsonb), + ('dp-live-22','booth-live-22',1,'review', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-24','booth-live-24',1,'approved', '{"theme":"assembled-basic","height":3.0}'::jsonb), + ('dp-live-25','booth-live-25',1,'approved', '{"theme":"island-premium","height":4.0}'::jsonb) +ON CONFLICT (booth_id, version) DO NOTHING; + + +-- 5) 청구(invoice) 8건 — 입금(paid)/발행(invoiced)/연체(overdue)/대기(pending) 분포. +-- UNIQUE(event_id, exhibitor_name) 멱등. outstanding = total - paid_amount (참가업체 미수금 컬럼). +INSERT INTO invoice (id, event_id, exhibitor_id, exhibitor_name, invoice_no, category, source_ref, + subtotal, vat, total, paid_amount, status, due_date, issued_at, paid_at, + cancelled_at, cancel_reason, line_items, note, created_by) VALUES + ('inv-live-09','e-2026-live',NULL,'(주)오토닉스로보','LIVE-2026-0109','rental',NULL, + 6534000,653400,7187400,7187400,'paid', CURRENT_DATE - 3, now()-interval '40 day', now()-interval '12 day', NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 아일랜드 · L-109)","quantity":18,"unitPrice":363000,"amount":6534000}]'::jsonb,'완납.', 'system-seed'), + ('inv-live-10','e-2026-live',NULL,'한성정밀기계','LIVE-2026-0110','rental',NULL, + 4356000,435600,4791600,4791600,'paid', CURRENT_DATE - 2, now()-interval '35 day', now()-interval '9 day', NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 조립 · L-110)","quantity":18,"unitPrice":242000,"amount":4356000}]'::jsonb,'완납.', 'system-seed'), + ('inv-live-11','e-2026-live',NULL,'대성전자','LIVE-2026-0111','rental',NULL, + 4791600,479160,5270760,2108304,'invoiced', CURRENT_DATE + 6, now()-interval '30 day', NULL, NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 독립 · L-111)","quantity":18,"unitPrice":266200,"amount":4791600}]'::jsonb,'계약금 40% 수납.', 'system-seed'), + ('inv-live-14','e-2026-live',NULL,'퓨처모빌리티','LIVE-2026-0114','rental',NULL, + 6534000,653400,7187400,7187400,'paid', CURRENT_DATE - 1, now()-interval '20 day', now()-interval '5 day', NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 아일랜드 · L-114)","quantity":18,"unitPrice":363000,"amount":6534000}]'::jsonb,'완납.', 'system-seed'), + ('inv-live-16','e-2026-live',NULL,'나노소재랩','LIVE-2026-0116','rental',NULL, + 4791600,479160,5270760,0,'overdue', CURRENT_DATE - 4, now()-interval '25 day', NULL, NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 독립 · L-116)","quantity":18,"unitPrice":266200,"amount":4791600}]'::jsonb,'납부 기한 경과 — 독촉 대상.', 'system-seed'), + ('inv-live-17','e-2026-live',NULL,'비전AI시스템','LIVE-2026-0117','rental',NULL, + 6534000,653400,7187400,2874960,'invoiced', CURRENT_DATE + 9, now()-interval '15 day', NULL, NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 아일랜드 · L-117)","quantity":18,"unitPrice":363000,"amount":6534000}]'::jsonb,'계약금 40% 수납.', 'system-seed'), + ('inv-live-20','e-2026-live',NULL,'클린테크환경','LIVE-2026-0120','rental',NULL, + 4356000,435600,4791600,0,'pending', CURRENT_DATE + 12, NULL, NULL, NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 조립 · L-120)","quantity":18,"unitPrice":242000,"amount":4356000}]'::jsonb,'발행 대기.', 'system-seed'), + ('inv-live-25','e-2026-live',NULL,'3D프린팅솔루션','LIVE-2026-0125','rental',NULL, + 6534000,653400,7187400,7187400,'paid', CURRENT_DATE - 1, now()-interval '8 day', now()-interval '2 day', NULL,NULL, + '[{"category":"RENTAL","description":"부스 임대료 (18㎡ 아일랜드 · L-125)","quantity":18,"unitPrice":363000,"amount":6534000}]'::jsonb,'완납.', 'system-seed') +ON CONFLICT (id) DO NOTHING; + + +-- 6) 수납(invoice_payment) — 완납/부분수납 반영(정산 폐루프 정합). +INSERT INTO invoice_payment (id, invoice_id, amount, method, memo, recorded_by, recorded_at) VALUES + ('pay-live-09-1','inv-live-09', 7187400, 'transfer', '일시 완납', 'system-seed', now()-interval '12 day'), + ('pay-live-10-1','inv-live-10', 4791600, 'transfer', '일시 완납', 'system-seed', now()-interval '9 day'), + ('pay-live-11-1','inv-live-11', 2108304, 'transfer', '계약금 40%', 'system-seed', now()-interval '28 day'), + ('pay-live-14-1','inv-live-14', 7187400, 'transfer', '일시 완납', 'system-seed', now()-interval '5 day'), + ('pay-live-17-1','inv-live-17', 2874960, 'transfer', '계약금 40%', 'system-seed', now()-interval '14 day'), + ('pay-live-25-1','inv-live-25', 7187400, 'transfer', '일시 완납', 'system-seed', now()-interval '2 day') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 검증(수동): +-- -- 참가업체 수: SELECT count(*) FROM booth b JOIN layout l ON l.id=b.layout_id +-- -- WHERE l.event_id='e-2026-live' AND b.assigned_company_name IS NOT NULL; -- >=24 +-- -- 월별 추이 버킷: SELECT to_char(created_at,'YYYY-MM'), count(*) FROM booth b +-- -- JOIN layout l ON l.id=b.layout_id WHERE l.event_id='e-2026-live' +-- -- GROUP BY 1 ORDER BY 1; -- 다월 분포 +-- -- 입금(paid) 수: SELECT count(*) FROM invoice WHERE event_id='e-2026-live' AND status='paid'; +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V69__demo_auctions_contractor.sql b/src/backend/src/main/resources/db/migration/V69__demo_auctions_contractor.sql new file mode 100644 index 0000000..8ef8a5a --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V69__demo_auctions_contractor.sql @@ -0,0 +1,126 @@ +-- ============================================================================ +-- V69 — 공사·장치 옥션(M15) 대량 보강 + 공사업체 포털(수주/응찰/피드) 소스 +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 목적(소유자 시연 지시 항목 2·3): +-- ② 옥션 목록: 진행중/마감임박/낙찰완료 옥션 다수 + 각 옥션 응찰(견적) 2~5건 + 등록 공사업체. +-- ③ 공사업체 포털(SCR-38 ContractorDashboard): demo-contractor 소속 co-0001 기준 +-- 수주 부스(award) 5~10건 · 응찰 이력(bid) · 알림 피드 15건+. +-- ---------------------------------------------------------------------------- +-- 근거(실 조회 경로): +-- • AuctionMapper.listAuctions: auction (+ bid count/lowest · award/company 조인). 상태=서비스 파생 +-- (award 있으면 '정산중/낙찰', now()>deadline '마감', else '진행중'). +-- • AuctionService.contractorDashboard: findUserCompany(demo-contractor→co-0001) → +-- listMyAwardedBooths(수주 부스=award) + listMyBids(응찰) + 피드(수주당 1 + 내 rank==1 응찰당 1). +-- ★피드 15+ 조건: co-0001 이 다수 옥션에서 최저가(rank1) → 마감분은 award, 진행분은 rank1 로 피드 생성. +-- • 봉인 마스킹은 서비스가 처리 — 시드는 원천 bid/award 만 넣는다. +-- 원칙: e-2026-live 스코프. 순수 INSERT ON CONFLICT DO NOTHING. 기존 AUC-LIVE-01/02 불변. +-- 공사업체 풀 = co-0001..co-0006(registered=true, V6/V38). co-0001 항상 최저가(수주·rank1 피드). +-- ============================================================================ + + +-- 0) 공사업체 평판(company_reputation) — 발주자 뷰 rating/jobsDone/claimRate. 멱등. +INSERT INTO company_reputation (company_id, rating, jobs_done, claim_rate) VALUES + ('co-0001', 4.8, 132, 0.8), + ('co-0002', 4.5, 88, 1.5), + ('co-0003', 4.6, 104, 1.1), + ('co-0004', 4.2, 61, 2.3), + ('co-0005', 4.4, 73, 1.8), + ('co-0006', 4.3, 67, 2.0) +ON CONFLICT (company_id) DO NOTHING; + + +-- 1) 옥션 8건 — 마감(낙찰) 6 + 진행(마감임박 포함) 2. co-0001 최저가. +INSERT INTO auction (id, event_id, title, category, auction_type, award_criteria, + weight_price, weight_reputation, weight_delivery, round, deadline, + material_package_id, materials, accent, created_by) VALUES + -- 마감·낙찰(co-0001) -------------------------------------------------------- + ('AUC-LIVE-03','e-2026-live','L-109 아일랜드 부스 장치공사','전시디자인설치','reverse','comprehensive', + 60,25,15,1, now()-interval '5 day', NULL,'layout,design,boq','primary','demo-organizer'), + ('AUC-LIVE-04','e-2026-live','L-114 프리미엄 부스 목공·도장','전시디자인설치','reverse','comprehensive', + 55,25,20,1, now()-interval '4 day', NULL,'layout,design','success','demo-organizer'), + ('AUC-LIVE-05','e-2026-live','메인 로비 리깅·트러스 설치','리깅','reverse','comprehensive', + 50,30,20,1, now()-interval '3 day', NULL,'layout,boq','warning','demo-organizer'), + ('AUC-LIVE-06','e-2026-live','B구역 카펫·파이텍스 시공','카펫/파이텍스','reverse','lowest', + 70,20,10,1, now()-interval '6 day', NULL,'layout','muted','demo-organizer'), + ('AUC-LIVE-07','e-2026-live','전시홀 음향·영상 시스템 설치','영상/음향','reverse','comprehensive', + 55,25,20,1, now()-interval '2 day', NULL,'layout,boq','primary','demo-organizer'), + ('AUC-LIVE-08','e-2026-live','네트워크·전원 배선 인프라','네트워크','reverse','comprehensive', + 50,25,25,1, now()-interval '7 day', NULL,'layout,boq','success','demo-organizer'), + -- 진행중(마감임박) ---------------------------------------------------------- + ('AUC-LIVE-09','e-2026-live','C구역 조립부스 12기 일괄 시공','전시디자인설치','reverse','comprehensive', + 60,25,15,1, now()+interval '1 day', NULL,'layout,design,boq','warning','demo-organizer'), + ('AUC-LIVE-10','e-2026-live','특별관 조명·전기 증설공사','전기시설','reverse','comprehensive', + 55,25,20,1, now()+interval '4 day', NULL,'layout,boq','primary','demo-organizer') +ON CONFLICT (id) DO NOTHING; + + +-- 2) 초대(등록업체) — 각 옥션에 3~4 업체(co-0001 포함). +INSERT INTO auction_invite (id, auction_id, company_id) VALUES + ('ai-live-03-1','AUC-LIVE-03','co-0001'),('ai-live-03-2','AUC-LIVE-03','co-0002'),('ai-live-03-3','AUC-LIVE-03','co-0005'), + ('ai-live-04-1','AUC-LIVE-04','co-0001'),('ai-live-04-2','AUC-LIVE-04','co-0004'),('ai-live-04-3','AUC-LIVE-04','co-0002'), + ('ai-live-05-1','AUC-LIVE-05','co-0001'),('ai-live-05-2','AUC-LIVE-05','co-0002'),('ai-live-05-3','AUC-LIVE-05','co-0003'), + ('ai-live-06-1','AUC-LIVE-06','co-0001'),('ai-live-06-2','AUC-LIVE-06','co-0004'), + ('ai-live-07-1','AUC-LIVE-07','co-0001'),('ai-live-07-2','AUC-LIVE-07','co-0005'),('ai-live-07-3','AUC-LIVE-07','co-0006'), + ('ai-live-08-1','AUC-LIVE-08','co-0001'),('ai-live-08-2','AUC-LIVE-08','co-0006'),('ai-live-08-3','AUC-LIVE-08','co-0003'), + ('ai-live-09-1','AUC-LIVE-09','co-0001'),('ai-live-09-2','AUC-LIVE-09','co-0002'),('ai-live-09-3','AUC-LIVE-09','co-0005'),('ai-live-09-4','AUC-LIVE-09','co-0004'), + ('ai-live-10-1','AUC-LIVE-10','co-0001'),('ai-live-10-2','AUC-LIVE-10','co-0003'),('ai-live-10-3','AUC-LIVE-10','co-0006') +ON CONFLICT (auction_id, company_id) DO NOTHING; + + +-- 3) 응찰(bid) — (auction,company) 당 1행. co-0001 최저가(수주·rank1). 2~4 응찰. +INSERT INTO bid (id, auction_id, company_id, round, subtotal, vat, total, lead_days) VALUES + -- AUC-LIVE-03 + ('bid-live-03-1','AUC-LIVE-03','co-0001',1, 5200000, 520000, 5200000, 9), + ('bid-live-03-2','AUC-LIVE-03','co-0002',1, 5600000, 560000, 5600000, 8), + ('bid-live-03-3','AUC-LIVE-03','co-0005',1, 5450000, 545000, 5450000,10), + -- AUC-LIVE-04 + ('bid-live-04-1','AUC-LIVE-04','co-0001',1, 4700000, 470000, 4700000, 7), + ('bid-live-04-2','AUC-LIVE-04','co-0004',1, 5100000, 510000, 5100000, 9), + ('bid-live-04-3','AUC-LIVE-04','co-0002',1, 4950000, 495000, 4950000, 8), + -- AUC-LIVE-05 + ('bid-live-05-1','AUC-LIVE-05','co-0001',1, 8300000, 830000, 8300000,11), + ('bid-live-05-2','AUC-LIVE-05','co-0002',1, 8900000, 890000, 8900000,10), + ('bid-live-05-3','AUC-LIVE-05','co-0003',1, 8600000, 860000, 8600000,12), + -- AUC-LIVE-06 + ('bid-live-06-1','AUC-LIVE-06','co-0001',1, 3100000, 310000, 3100000, 5), + ('bid-live-06-2','AUC-LIVE-06','co-0004',1, 3350000, 335000, 3350000, 6), + -- AUC-LIVE-07 + ('bid-live-07-1','AUC-LIVE-07','co-0001',1, 6200000, 620000, 6200000, 9), + ('bid-live-07-2','AUC-LIVE-07','co-0005',1, 6700000, 670000, 6700000, 8), + ('bid-live-07-3','AUC-LIVE-07','co-0006',1, 6500000, 650000, 6500000,10), + -- AUC-LIVE-08 + ('bid-live-08-1','AUC-LIVE-08','co-0001',1, 7400000, 740000, 7400000,10), + ('bid-live-08-2','AUC-LIVE-08','co-0006',1, 7900000, 790000, 7900000, 9), + ('bid-live-08-3','AUC-LIVE-08','co-0003',1, 7650000, 765000, 7650000,11), + -- AUC-LIVE-09 (진행중 · co-0001 최저 → rank1 피드) + ('bid-live-09-1','AUC-LIVE-09','co-0001',1, 9100000, 910000, 9100000,12), + ('bid-live-09-2','AUC-LIVE-09','co-0002',1, 9700000, 970000, 9700000,11), + ('bid-live-09-3','AUC-LIVE-09','co-0005',1, 9450000, 945000, 9450000,13), + ('bid-live-09-4','AUC-LIVE-09','co-0004',1, 9900000, 990000, 9900000,10), + -- AUC-LIVE-10 (진행중 · co-0001 최저 → rank1 피드) + ('bid-live-10-1','AUC-LIVE-10','co-0001',1, 5800000, 580000, 5800000, 8), + ('bid-live-10-2','AUC-LIVE-10','co-0003',1, 6200000, 620000, 6200000, 9), + ('bid-live-10-3','AUC-LIVE-10','co-0006',1, 6050000, 605000, 6050000,10) +ON CONFLICT (auction_id, company_id) DO NOTHING; + + +-- 4) 낙찰(award) — 마감 6건 전부 co-0001(최저·종합 우수). ON CONFLICT (auction_id) 멱등. +INSERT INTO award (id, auction_id, bid_id, reason, awarded_by, awarded_at) VALUES + ('aw-live-03','AUC-LIVE-03','bid-live-03-1','종합평가 1위 — 최저가·납기 준수 이력 우수.','demo-organizer', now()-interval '4 day'), + ('aw-live-04','AUC-LIVE-04','bid-live-04-1','종합평가 1위 — 목공 품질·최저가.','demo-organizer', now()-interval '3 day'), + ('aw-live-05','AUC-LIVE-05','bid-live-05-1','종합평가 1위 — 리깅 안전 이력·최저가.','demo-organizer', now()-interval '2 day'), + ('aw-live-06','AUC-LIVE-06','bid-live-06-1','최저가 낙찰(lowest 기준).','demo-organizer', now()-interval '5 day'), + ('aw-live-07','AUC-LIVE-07','bid-live-07-1','종합평가 1위 — AV 시공 경험·최저가.','demo-organizer', now()-interval '1 day'), + ('aw-live-08','AUC-LIVE-08','bid-live-08-1','종합평가 1위 — 네트워크 인프라 전문·최저가.','demo-organizer', now()-interval '6 day') +ON CONFLICT (auction_id) DO NOTHING; + + +-- ============================================================================ +-- 검증(수동): +-- -- e-2026-live 옥션 수: SELECT count(*) FROM auction WHERE event_id='e-2026-live'; -- >=10 +-- -- co-0001 수주 부스: SELECT count(*) FROM award aw JOIN bid b ON b.id=aw.bid_id +-- -- WHERE b.company_id='co-0001'; -- >=7 (AUC-LIVE-01 포함) +-- -- co-0001 응찰: SELECT count(*) FROM bid WHERE company_id='co-0001'; -- >=9 +-- -- 피드 근사(수주 + co-0001 rank1 진행): 7 award + 9 rank1(co-0001 최저) ≈ 16 (>=15) +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V70__demo_dock_slots.sql b/src/backend/src/main/resources/db/migration/V70__demo_dock_slots.sql new file mode 100644 index 0000000..af096c9 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V70__demo_dock_slots.sql @@ -0,0 +1,80 @@ +-- ============================================================================ +-- V70 — 물류 허브 도크 + 반입/반출 예약 슬롯 (e-2026-live, 향후 2주) +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 근본 원인(소유자 시연 지시 항목 4 — 빈 화면): +-- LogisticsMapper.findDocks 는 dock ← hall_assignment(ha.event_id=eventId) 로 홀 도크를 찾는다. +-- 기존 도크(dock-h7-*)는 홀 H7 전용인데, e-2026-live 는 홀 H1(ha-live-h1)에 배정 → +-- e-2026-live 물류 허브 그리드에 도크가 0개 = 예약 슬롯 화면이 완전히 빈다. +-- 조치: 홀 H1 도크 6개 신설 + e-2026-live 반입/반출 예약을 향후 2주에 분산(가능/마감 혼재). +-- ---------------------------------------------------------------------------- +-- 근거(실 조회 경로): +-- • LogisticsMapper.findDocks(eventId): dock JOIN hall_assignment ha ON ha.hall_id=dock.hall_id +-- WHERE ha.event_id=#{eventId}. → H1 도크가 있어야 e-2026-live 그리드 렌더. +-- • findReservations(eventId,direction,date): dock_reservation 방향·일자 필터(그리드 점유). +-- • findDefaultDate(eventId,direction): min(reserve_date) → 조회 기본 일자(가장 이른 예약일). +-- 원칙: 순수 INSERT ON CONFLICT DO NOTHING. 도크는 UNIQUE(hall_id,dock_no) 멱등. +-- 예약 일자는 CURRENT_DATE 상대(재배포 시점 기준 항상 향후 2주). start_hour 8..19, span 2~3. +-- company_name 은 더미(공간/물류 업체명). tone: booked | priority(중량물 5t↑ 우선). +-- ============================================================================ + + +-- 1) 홀 H1 도크 6개 ------------------------------------------------------------ +INSERT INTO dock (id, hall_id, dock_no, label, heavy_priority) VALUES + ('dock-h1-1','H1',1,'도크 1', true), + ('dock-h1-2','H1',2,'도크 2', false), + ('dock-h1-3','H1',3,'도크 3', false), + ('dock-h1-4','H1',4,'도크 4', false), + ('dock-h1-5','H1',5,'도크 5', false), + ('dock-h1-6','H1',6,'도크 6', true) +ON CONFLICT (hall_id, dock_no) DO NOTHING; + + +-- 2) 반입(in) 예약 — 향후 2주 분산. 대표일 CURRENT_DATE+1 은 도크·시간대 다수 점유(가능/마감 혼재). +INSERT INTO dock_reservation + (id, event_id, dock_id, direction, reserve_date, start_hour, span, company_name, vehicle_no, vehicle_weight, item, forklift, tone) VALUES + -- 대표일(D+1) — 도크 1~5 부분 점유, 도크 6 및 후반 시간대는 비어 있음(가능 슬롯) + ('dr-live-in-01','e-2026-live','dock-h1-1','in', CURRENT_DATE + 1, 8, 2, '(주)오토닉스로보', '11가 1101', '5t', '아일랜드 부스 자재', true, 'booked'), + ('dr-live-in-02','e-2026-live','dock-h1-1','in', CURRENT_DATE + 1, 11, 2, NULL, NULL, '5t', '중량물 우선(5t↑)', false, 'priority'), + ('dr-live-in-03','e-2026-live','dock-h1-2','in', CURRENT_DATE + 1, 9, 3, '한성정밀기계', '22나 2202', '2.5t', '기계 장비', true, 'booked'), + ('dr-live-in-04','e-2026-live','dock-h1-3','in', CURRENT_DATE + 1, 10, 2, '대성전자', '33다 3303', '1t', '전시 소품', false, 'booked'), + ('dr-live-in-05','e-2026-live','dock-h1-4','in', CURRENT_DATE + 1, 13, 2, '스마트팩토리솔루션', '44라 4404', '3.5t', '조립식 부스', false, 'booked'), + ('dr-live-in-06','e-2026-live','dock-h1-5','in', CURRENT_DATE + 1, 14, 3, '퓨처모빌리티', '55마 5505', '5t', '차량 전시물', true, 'booked'), + -- D+3 + ('dr-live-in-07','e-2026-live','dock-h1-1','in', CURRENT_DATE + 3, 9, 2, '비전AI시스템', '66바 6606', '1t', '디스플레이 장비', false, 'booked'), + ('dr-live-in-08','e-2026-live','dock-h1-2','in', CURRENT_DATE + 3, 12, 2, '한국물류로보틱스', '77사 7707', '5t', 'AMR 로봇', true, 'booked'), + ('dr-live-in-09','e-2026-live','dock-h1-6','in', CURRENT_DATE + 3, 15, 2, NULL, NULL, '11t 이상', '중량물 우선(11t↑)', true, 'priority'), + -- D+5 + ('dr-live-in-10','e-2026-live','dock-h1-3','in', CURRENT_DATE + 5, 10, 3, '나노소재랩', '88아 8808', '2.5t', '소재 샘플·집기', false, 'booked'), + ('dr-live-in-11','e-2026-live','dock-h1-4','in', CURRENT_DATE + 5, 14, 2, '그린에너지테크', '99자 9909', '3.5t', '태양광 모듈', true, 'booked'), + -- D+7 + ('dr-live-in-12','e-2026-live','dock-h1-1','in', CURRENT_DATE + 7, 8, 2, '3D프린팅솔루션', '10차 1010', '1t', '3D 프린터', false, 'booked'), + ('dr-live-in-13','e-2026-live','dock-h1-5','in', CURRENT_DATE + 7, 11, 2, '차세대배터리', '12카 1212', '5t', 'ESS 배터리팩', true, 'booked') +ON CONFLICT (id) DO NOTHING; + + +-- 3) 반출(out) 예약 — 행사 종료 후 철거(향후 2주 후반). 가능/마감 혼재. +INSERT INTO dock_reservation + (id, event_id, dock_id, direction, reserve_date, start_hour, span, company_name, vehicle_no, vehicle_weight, item, forklift, tone) VALUES + -- 대표일(D+10) + ('dr-live-out-01','e-2026-live','dock-h1-1','out', CURRENT_DATE + 10, 14, 3, '(주)오토닉스로보', '11가 1101', '5t', '철거 자재', true, 'booked'), + ('dr-live-out-02','e-2026-live','dock-h1-2','out', CURRENT_DATE + 10, 15, 2, '한국물류로보틱스', '77사 7707', '5t', 'AMR 회수', true, 'booked'), + ('dr-live-out-03','e-2026-live','dock-h1-3','out', CURRENT_DATE + 10, 16, 2, NULL, NULL, '11t 이상', '중량물 우선(11t↑)', true, 'priority'), + ('dr-live-out-04','e-2026-live','dock-h1-4','out', CURRENT_DATE + 10, 13, 2, '퓨처모빌리티', '55마 5505', '5t', '차량 전시물 반출', true, 'booked'), + -- D+11 + ('dr-live-out-05','e-2026-live','dock-h1-1','out', CURRENT_DATE + 11, 10, 2, '한성정밀기계', '22나 2202', '2.5t', '기계 장비 회수', true, 'booked'), + ('dr-live-out-06','e-2026-live','dock-h1-5','out', CURRENT_DATE + 11, 17, 3, '차세대배터리', '12카 1212', '5t', 'ESS 반출', true, 'booked'), + -- D+12 + ('dr-live-out-07','e-2026-live','dock-h1-2','out', CURRENT_DATE + 12, 11, 2, '3D프린팅솔루션', '10차 1010', '1t', '3D 프린터 회수', false, 'booked') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 검증(수동): +-- -- H1 도크: SELECT count(*) FROM dock d JOIN hall_assignment ha ON ha.hall_id=d.hall_id +-- -- WHERE ha.event_id='e-2026-live'; -- 6 +-- -- 반입 기본일 예약: SELECT dock_id,start_hour,span FROM dock_reservation +-- -- WHERE event_id='e-2026-live' AND direction='in' AND reserve_date=CURRENT_DATE+1; +-- -- 기본 조회일: SELECT to_char(min(reserve_date),'YYYY-MM-DD') FROM dock_reservation +-- -- WHERE event_id='e-2026-live' AND direction='in'; -- CURRENT_DATE+1 +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V71__demo_sponsorship_fulfillment.sql b/src/backend/src/main/resources/db/migration/V71__demo_sponsorship_fulfillment.sql new file mode 100644 index 0000000..3b51113 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V71__demo_sponsorship_fulfillment.sql @@ -0,0 +1,75 @@ +-- ============================================================================ +-- V71 — 스폰서십 이행 현황(계약 항목별 이행률·일정) + 체결 일정 파이프라인 보강 +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 목적(소유자 시연 지시 항목 5): +-- ① (주)스마트오토메이션(ss-live-001, DIAMOND) 이행 현황을 계약 항목별 이행률·일정으로 상세화. +-- ② 스폰서십 체결 일정(pending 파이프라인) 스폰서 보강 → '스폰서 관리' 목록·팔로업 스토리. +-- ---------------------------------------------------------------------------- +-- 근거(실 조회/렌더 경로): +-- • MarketingMapper.findSponsors: sponsorship_sponsor(fulfillment::text) → 서비스 parseFulfillment +-- 은 jsonb 각 원소의 키 {id,label,done} 만 읽는다(★existing V47 시드는 {item,done} 라 +-- label=null → 이행 항목이 공백으로 렌더됨). 이 파일이 올바른 {id,label,done} 로 교정. +-- • SponsorshipPage 기본 선택 = sponsors[0](created_at 최소=ss-live-001) → 스마트오토메이션 이행 현황 노출. +-- • 이행률·일정 전용 컬럼은 DTO에 없으므로 label 텍스트에 병기(프론트 수정 없이 시연 가능). +-- 원칙: ss-live-001~003 fulfillment 교정은 고정값 멱등 UPDATE(데모 시드 데이터, 크롤 실데이터 아님). +-- 신규 스폰서/패키지는 순수 INSERT ON CONFLICT DO NOTHING. e-2026-live 스코프. 회사명=더미(민감 아님). +-- ============================================================================ + + +-- 1) (주)스마트오토메이션 이행 현황 — 8개 계약 항목(이행률·일정 병기, done 4/8 = 이행률 50%). +UPDATE sponsorship_sponsor + SET fulfillment = '[ + {"id":"f1","label":"메인 배너 노출 (게시 D-45 완료 · 이행률 100%)","done":true}, + {"id":"f2","label":"공식 도록 전면 광고 (입고 완료 · 이행률 100%)","done":true}, + {"id":"f3","label":"VIP 라운지 부스 설치 (설치 완료 · 이행률 100%)","done":true}, + {"id":"f8","label":"현장 디지털 사이니지 송출 (송출 중 · 이행률 100%)","done":true}, + {"id":"f4","label":"기조연설 세션 (개막 2일차 14:00 · 준비 60%)","done":false}, + {"id":"f7","label":"모바일 앱 스폰서 배너 (검수 중 · 이행률 80%)","done":false}, + {"id":"f5","label":"뉴스레터 로고 삽입 (발송 예정 D-3 · 이행률 40%)","done":false}, + {"id":"f6","label":"프레스룸 브랜딩 (자재 발주 · 이행률 30%)","done":false} + ]'::jsonb + WHERE id = 'ss-live-001'; + +-- 2) 나머지 계약 스폰서 이행 현황도 올바른 label 키로 교정(공백 렌더 방지). +UPDATE sponsorship_sponsor + SET fulfillment = '[ + {"id":"g1","label":"로비 배너 게시 (게시 완료 · 이행률 100%)","done":true}, + {"id":"g2","label":"세션 슬롯 1 배정 (2일차 11:00 · 확정)","done":true}, + {"id":"g3","label":"도록 반면 광고 (교정 진행 · 이행률 70%)","done":false} + ]'::jsonb + WHERE id = 'ss-live-002'; + +UPDATE sponsorship_sponsor + SET fulfillment = '[ + {"id":"s1","label":"디지털 사이니지 노출 (계약 검토 중 · 이행률 20%)","done":false}, + {"id":"s2","label":"도록 로고 게재 (로고 접수 대기 · 이행률 10%)","done":false} + ]'::jsonb + WHERE id = 'ss-live-003'; + + +-- 3) 체결 일정 파이프라인 — 협의/계약대기 스폰서 3건 추가(스폰서 관리 목록·팔로업). +INSERT INTO sponsorship_sponsor (id, event_id, package_id, name, tier_label, contract_status, fulfillment) VALUES + ('ss-live-004','e-2026-live','sp-live-gld','글로벌테크','GOLD','pending', + '[{"id":"p1","label":"제안서 발송 완료 (D-7)","done":true},{"id":"p2","label":"계약 조건 협의 중 (이행률 50%)","done":false}]'::jsonb), + ('ss-live-005','e-2026-live','sp-live-slv','퓨처모빌리티','SILVER','pending', + '[{"id":"p1","label":"1차 미팅 완료 (D-4)","done":true},{"id":"p2","label":"내부 예산 승인 대기","done":false}]'::jsonb), + ('ss-live-006','e-2026-live','sp-live-dia','비전AI시스템','DIAMOND','pending', + '[{"id":"p1","label":"관심 표명 접수","done":true},{"id":"p2","label":"패키지 커스터마이즈 협의 예정 (D-2)","done":false}]'::jsonb) +ON CONFLICT (id) DO NOTHING; + + +-- 4) 체결 일정(마감 임박) 표현 — 패키지 dday 차등(체결 일정 카드 '마감 임박' 스토리). 고정값 멱등. +UPDATE sponsorship_package SET dday = 2 WHERE id = 'sp-live-dia'; +UPDATE sponsorship_package SET dday = 5 WHERE id = 'sp-live-gld'; +UPDATE sponsorship_package SET dday = 9 WHERE id = 'sp-live-slv'; + + +-- ============================================================================ +-- 검증(수동): +-- -- 스마트오토메이션 이행 항목: SELECT jsonb_array_length(fulfillment) FROM sponsorship_sponsor +-- -- WHERE id='ss-live-001'; -- 8 +-- -- label 키 존재(공백 렌더 방지): SELECT fulfillment->0->>'label' FROM sponsorship_sponsor +-- -- WHERE id='ss-live-001'; -- '메인 배너 노출 ...' +-- -- 스폰서 수(파이프라인 포함): SELECT count(*) FROM sponsorship_sponsor WHERE event_id='e-2026-live'; -- >=6 +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V72__demo_bi_history.sql b/src/backend/src/main/resources/db/migration/V72__demo_bi_history.sql new file mode 100644 index 0000000..63781a1 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V72__demo_bi_history.sql @@ -0,0 +1,96 @@ +-- ============================================================================ +-- V72 — 경영분석 전역(행사 횡단) BI 히스토리 — 리텐션·홀 가동률·수요예측·행사 매출 비교 +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 목적(소유자 시연 지시 항목 6 — GlobalOverviewSection 4개 지표): +-- • 참가사 리텐션(재참가): 연도별 참가사 중 이전 연도 재참가 → 다연도 공유 참가사 필요. +-- • 홀 가동률 추이(월별): 최근 N개월 개최 행사-일수 → 여러 달에 걸친 행사 필요. +-- • 수요예측(연도별 개최 행사 수 추세): 2024·2025·2026 연도 버킷 → 연도 분산 행사 필요. +-- • 행사 간 매출 비교(면적×요율+유틸): 부스 배치 행사 랭킹 → 히스토리 행사에 부스 필요. +-- ---------------------------------------------------------------------------- +-- 근본 원인: 기존 데모 행사(e-2026-*·bd-e-*·smf)는 start_date 가 전부 CURRENT_DATE 상대(=2026년) +-- → EXTRACT(YEAR) 단일 버킷. 리텐션 '재참가'(이전 연도 존재)·연도별 추세가 성립하지 않는다. +-- 조치: 실제 2024·2025년 고정일 개최 행사 4건 + 부스(공유 참가사명)를 추가해 다연도 히스토리 형성. +-- ---------------------------------------------------------------------------- +-- 근거(AnalyticsMapper — 전부 tenant_id='KINTEX' 스코프, booth←layout←event 조인): +-- • findRetentionByYear / findRetentionSummary: booth.assigned_company_name × EXTRACT(YEAR e.start_date). +-- • findMonthlyEventDays(months): event.start_date 월별 (end-start+1) 합 → 가동률. +-- • findYearlyEventCounts: EXTRACT(YEAR e.start_date) 별 count → 수요예측 추세. +-- • findEventAreaRanking: sum(ST_Area(booth.geom)) 상위 8 → 매출 비교. +-- 원칙: 순수 INSERT ON CONFLICT DO NOTHING. status='closed'(과거·진행중 탭 미노출). +-- start_date 는 고정 과거일(2024/2025) — 재배포 무관 항상 해당 연도. 회사명=기존 참가사 재사용(리텐션 연결). +-- holl(H2..H7)에 배치(가동률 홀 스코프는 event.tenant_id 로 격리). 부스 6m×3m 타일. +-- ============================================================================ + + +-- 1) 히스토리 행사(2024×2 · 2025×2) — 과거 개최·종료(closed). ----------------------- +INSERT INTO event (id, name, start_date, end_date, status, tenant_id, category, hall_label, poster_url) VALUES + ('h-2024-smf', '2024 스마트제조·자동화전', DATE '2024-03-13', DATE '2024-03-16', 'closed', 'KINTEX', '전시', '제1전시장 홀2', NULL), + ('h-2024-rbt', '2024 국제로봇 & AI 위크', DATE '2024-09-25', DATE '2024-09-28', 'closed', 'KINTEX', '전시', '제1전시장 홀3', NULL), + ('h-2025-smf', '2025 스마트제조·자동화전', DATE '2025-03-12', DATE '2025-03-15', 'closed', 'KINTEX', '전시', '제1전시장 홀2', NULL), + ('h-2025-log', '2025 물류산업·공급망 대전', DATE '2025-10-15', DATE '2025-10-18', 'closed', 'KINTEX', '전시', '제2전시장 홀6', NULL) +ON CONFLICT (id) DO NOTHING; + + +-- 2) 배치(layout) — 행사당 1. ----------------------------------------------------- +INSERT INTO layout (id, event_id, hall_id, version, name, status) VALUES + ('h-ly-2024-smf', 'h-2024-smf', 'H2', 1, '2024 SMF 배치', 'confirmed'), + ('h-ly-2024-rbt', 'h-2024-rbt', 'H3', 1, '2024 로봇 배치', 'confirmed'), + ('h-ly-2025-smf', 'h-2025-smf', 'H2', 1, '2025 SMF 배치', 'confirmed'), + ('h-ly-2025-log', 'h-2025-log', 'H6', 1, '2025 물류 배치', 'confirmed') +ON CONFLICT (event_id, hall_id, version) DO NOTHING; + + +-- 3) 부스(booth) — 공유 참가사명으로 리텐션 연결. created_at = 개최 시기(현실성). +-- 핵심 재참가사: (주)스마트오토메이션(4개 히스토리 + 2026 = 5년 연속 참가), 델타로보틱스·글로벌테크 등. +INSERT INTO booth (id, layout_id, booth_no, booth_type, geom, size_w_m, size_d_m, height_m, + floor_load_t_per_m2, assigned_company_name, premium, created_at) VALUES + -- 2024 SMF + ('h-b-2024-smf-1','h-ly-2024-smf','24A-01','island', ST_GeomFromText('POLYGON((0 0,6 0,6 3,0 3,0 0))',0), 6,3,4.0,1.0,'(주)스마트오토메이션', true, TIMESTAMP '2024-02-01 10:00'), + ('h-b-2024-smf-2','h-ly-2024-smf','24A-02','independent',ST_GeomFromText('POLYGON((7 0,13 0,13 3,7 3,7 0))',0), 6,3,3.5,1.0,'델타로보틱스', false, TIMESTAMP '2024-02-03 10:00'), + ('h-b-2024-smf-3','h-ly-2024-smf','24A-03','assembled', ST_GeomFromText('POLYGON((14 0,20 0,20 3,14 3,14 0))',0), 6,3,3.0,1.0,'글로벌테크', false, TIMESTAMP '2024-02-05 10:00'), + ('h-b-2024-smf-4','h-ly-2024-smf','24A-04','corner', ST_GeomFromText('POLYGON((21 0,27 0,27 3,21 3,21 0))',0), 6,3,3.5,1.0,'미래제조연구소', false, TIMESTAMP '2024-02-06 10:00'), + ('h-b-2024-smf-5','h-ly-2024-smf','24A-05','assembled', ST_GeomFromText('POLYGON((0 4,6 4,6 7,0 7,0 4))',0), 6,3,3.0,1.0,'한국센서테크', false, TIMESTAMP '2024-02-07 10:00'), + ('h-b-2024-smf-6','h-ly-2024-smf','24A-06','independent',ST_GeomFromText('POLYGON((7 4,13 4,13 7,7 7,7 4))',0), 6,3,3.5,1.0,'(주)오토닉스로보', false, TIMESTAMP '2024-02-08 10:00'), + -- 2024 로봇 + ('h-b-2024-rbt-1','h-ly-2024-rbt','24R-01','island', ST_GeomFromText('POLYGON((0 0,6 0,6 3,0 3,0 0))',0), 6,3,4.0,1.0,'(주)스마트오토메이션', true, TIMESTAMP '2024-08-01 10:00'), + ('h-b-2024-rbt-2','h-ly-2024-rbt','24R-02','independent',ST_GeomFromText('POLYGON((7 0,13 0,13 3,7 3,7 0))',0), 6,3,3.5,1.0,'퓨처모빌리티', false, TIMESTAMP '2024-08-03 10:00'), + ('h-b-2024-rbt-3','h-ly-2024-rbt','24R-03','assembled', ST_GeomFromText('POLYGON((14 0,20 0,20 3,14 3,14 0))',0), 6,3,3.0,1.0,'비전AI시스템', false, TIMESTAMP '2024-08-05 10:00'), + ('h-b-2024-rbt-4','h-ly-2024-rbt','24R-04','corner', ST_GeomFromText('POLYGON((21 0,27 0,27 3,21 3,21 0))',0), 6,3,3.5,1.0,'글로벌테크', false, TIMESTAMP '2024-08-06 10:00'), + ('h-b-2024-rbt-5','h-ly-2024-rbt','24R-05','assembled', ST_GeomFromText('POLYGON((0 4,6 4,6 7,0 7,0 4))',0), 6,3,3.0,1.0,'델타로보틱스', false, TIMESTAMP '2024-08-07 10:00'), + ('h-b-2024-rbt-6','h-ly-2024-rbt','24R-06','assembled', ST_GeomFromText('POLYGON((7 4,13 4,13 7,7 7,7 4))',0), 6,3,3.0,1.0,'나노소재랩', false, TIMESTAMP '2024-08-08 10:00'), + -- 2025 SMF + ('h-b-2025-smf-1','h-ly-2025-smf','25A-01','island', ST_GeomFromText('POLYGON((0 0,6 0,6 3,0 3,0 0))',0), 6,3,4.0,1.0,'(주)스마트오토메이션', true, TIMESTAMP '2025-02-01 10:00'), + ('h-b-2025-smf-2','h-ly-2025-smf','25A-02','independent',ST_GeomFromText('POLYGON((7 0,13 0,13 3,7 3,7 0))',0), 6,3,3.5,1.0,'델타로보틱스', false, TIMESTAMP '2025-02-03 10:00'), + ('h-b-2025-smf-3','h-ly-2025-smf','25A-03','assembled', ST_GeomFromText('POLYGON((14 0,20 0,20 3,14 3,14 0))',0), 6,3,3.0,1.0,'미래제조연구소', false, TIMESTAMP '2025-02-05 10:00'), + ('h-b-2025-smf-4','h-ly-2025-smf','25A-04','corner', ST_GeomFromText('POLYGON((21 0,27 0,27 3,21 3,21 0))',0), 6,3,3.5,1.0,'퓨처모빌리티', false, TIMESTAMP '2025-02-06 10:00'), + ('h-b-2025-smf-5','h-ly-2025-smf','25A-05','assembled', ST_GeomFromText('POLYGON((0 4,6 4,6 7,0 7,0 4))',0), 6,3,3.0,1.0,'(주)오토닉스로보', false, TIMESTAMP '2025-02-07 10:00'), + ('h-b-2025-smf-6','h-ly-2025-smf','25A-06','independent',ST_GeomFromText('POLYGON((7 4,13 4,13 7,7 7,7 4))',0), 6,3,3.5,1.0,'한국물류로보틱스', false, TIMESTAMP '2025-02-08 10:00'), + -- 2025 물류 + ('h-b-2025-log-1','h-ly-2025-log','25L-01','island', ST_GeomFromText('POLYGON((0 0,6 0,6 3,0 3,0 0))',0), 6,3,4.0,1.0,'글로벌테크', true, TIMESTAMP '2025-09-01 10:00'), + ('h-b-2025-log-2','h-ly-2025-log','25L-02','independent',ST_GeomFromText('POLYGON((7 0,13 0,13 3,7 3,7 0))',0), 6,3,3.5,1.0,'비전AI시스템', false, TIMESTAMP '2025-09-03 10:00'), + ('h-b-2025-log-3','h-ly-2025-log','25L-03','assembled', ST_GeomFromText('POLYGON((14 0,20 0,20 3,14 3,14 0))',0), 6,3,3.0,1.0,'한국센서테크', false, TIMESTAMP '2025-09-05 10:00'), + ('h-b-2025-log-4','h-ly-2025-log','25L-04','corner', ST_GeomFromText('POLYGON((21 0,27 0,27 3,21 3,21 0))',0), 6,3,3.5,1.0,'(주)스마트오토메이션', false, TIMESTAMP '2025-09-06 10:00'), + ('h-b-2025-log-5','h-ly-2025-log','25L-05','assembled', ST_GeomFromText('POLYGON((0 4,6 4,6 7,0 7,0 4))',0), 6,3,3.0,1.0,'그린에너지테크', false, TIMESTAMP '2025-09-07 10:00'), + ('h-b-2025-log-6','h-ly-2025-log','25L-06','assembled', ST_GeomFromText('POLYGON((7 4,13 4,13 7,7 7,7 4))',0), 6,3,3.0,1.0,'델타로보틱스', false, TIMESTAMP '2025-09-08 10:00') +ON CONFLICT (id) DO NOTHING; + + +-- 4) 히스토리 유틸리티 매출(행사 간 매출 비교 다양화) — 소액 유틸 오더 1~2건/행사. ----------- +INSERT INTO utility_order (id, event_id, booth_id, status, quote, supply_timing) VALUES + ('h-uo-2024-smf','h-2024-smf','h-b-2024-smf-1','approved','{"total":"3200000","items":["전기 15kW","네트워크"]}'::jsonb,'상시'), + ('h-uo-2024-rbt','h-2024-rbt','h-b-2024-rbt-1','approved','{"total":"2800000","items":["전기 10kW"]}'::jsonb,'상시'), + ('h-uo-2025-smf','h-2025-smf','h-b-2025-smf-1','approved','{"total":"3600000","items":["전기 20kW","급배수"]}'::jsonb,'상시'), + ('h-uo-2025-log','h-2025-log','h-b-2025-log-1','approved','{"total":"3100000","items":["전기 15kW"]}'::jsonb,'상시') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 검증(수동): +-- -- 연도별 참가사/재참가: (AnalyticsMapper.findRetentionByYear 로직) +-- -- 2025·2026 에 returningCompanies>0 기대(스마트오토메이션 등 다연도 참가). +-- -- 연도 버킷: SELECT EXTRACT(YEAR FROM start_date)::int y, count(*) FROM event +-- -- WHERE tenant_id='KINTEX' AND start_date IS NOT NULL GROUP BY 1 ORDER BY 1; -- 2024·2025·2026 +-- -- 매출 비교 랭킹: SELECT l.event_id, sum(ST_Area(b.geom)) FROM booth b JOIN layout l ON l.id=b.layout_id +-- -- JOIN event e ON e.id=l.event_id WHERE e.tenant_id='KINTEX' GROUP BY 1 ORDER BY 2 DESC LIMIT 8; +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V73__demo_live_utility_orders.sql b/src/backend/src/main/resources/db/migration/V73__demo_live_utility_orders.sql new file mode 100644 index 0000000..91f6ad3 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V73__demo_live_utility_orders.sql @@ -0,0 +1,52 @@ +-- ============================================================================ +-- V73 — e-2026-live 유틸리티 신청(utility_order) 보강 — 유틸리티 매출·손익 P&L 채움 +-- 담당: kintex-testdata-dev · 작성: 2026-07-23 +-- ---------------------------------------------------------------------------- +-- 목적(소유자 시연 지시 항목 6 보강): +-- 경영분석(M16) 유틸리티 매출 KPI·손익 P&L '유틸리티' 행이 e-2026-live 에서 ₩0 이었던 이유는 +-- 해당 행사에 utility_order 시드가 전무했기 때문(전 데모 행사 통틀어 유틸리티 주문 없음). +-- → e-2026-live 부스에 유틸리티 신청 12건 추가 → 유틸리티 매출·P&L·대시보드 '유틸리티 신청' KPI 채움. +-- ---------------------------------------------------------------------------- +-- 근거(실 조회): +-- • AnalyticsMapper.findUtilityRevenue(eventId): sum((quote->>'total')::numeric) — total 은 +-- 숫자 형태 문자열만 집계(정규식 ^[0-9]+(\.[0-9]+)?$). → quote.total 을 순수 숫자 문자열로. +-- • DashboardMapper.findKpiCounts: (SELECT count(*) FROM utility_order WHERE event_id) AS utilityOrders. +-- • M4 유틸리티 화면: utility_order(event_id, booth_id, status, quote) 목록. +-- 원칙: 순수 INSERT ON CONFLICT DO NOTHING. e-2026-live 스코프. booth_id = 기존 booth-live-*(V39/V68). +-- wiring(MultiLineString)·location_diagram_url 은 선택 컬럼(생략 = NULL). status: approved/submitted 혼재. +-- ============================================================================ + +INSERT INTO utility_order (id, event_id, booth_id, status, quote, supply_timing) VALUES + ('uo-live-01','e-2026-live','booth-live-01','approved', + '{"total":"2400000","items":["전기 20kW 단독","네트워크 1G 전용","급배수"]}'::jsonb,'상시 (개막 전 공급)'), + ('uo-live-02','e-2026-live','booth-live-02','approved', + '{"total":"1650000","items":["전기 15kW","네트워크 1G"]}'::jsonb,'상시'), + ('uo-live-03','e-2026-live','booth-live-03','approved', + '{"total":"980000","items":["전기 10kW"]}'::jsonb,'상시'), + ('uo-live-04','e-2026-live','booth-live-04','submitted', + '{"total":"1200000","items":["전기 12kW","네트워크 100M"]}'::jsonb,'개막 1일 전'), + ('uo-live-09','e-2026-live','booth-live-09','approved', + '{"total":"2100000","items":["전기 18kW","압축공기","네트워크 1G"]}'::jsonb,'상시'), + ('uo-live-11','e-2026-live','booth-live-11','approved', + '{"total":"1450000","items":["전기 15kW","네트워크 1G"]}'::jsonb,'상시'), + ('uo-live-14','e-2026-live','booth-live-14','approved', + '{"total":"2650000","items":["전기 25kW 단독","급배수","네트워크 1G 전용"]}'::jsonb,'상시 (차량 전시)'), + ('uo-live-16','e-2026-live','booth-live-16','submitted', + '{"total":"1100000","items":["전기 12kW"]}'::jsonb,'개막 2일 전'), + ('uo-live-17','e-2026-live','booth-live-17','approved', + '{"total":"1900000","items":["전기 18kW","네트워크 1G 전용"]}'::jsonb,'상시'), + ('uo-live-20','e-2026-live','booth-live-20','submitted', + '{"total":"860000","items":["전기 8kW","급배수"]}'::jsonb,'개막 1일 전'), + ('uo-live-25','e-2026-live','booth-live-25','approved', + '{"total":"2300000","items":["전기 20kW","압축공기","네트워크 1G"]}'::jsonb,'상시 (3D 프린팅)'), + ('uo-live-06','e-2026-live','booth-live-06','approved', + '{"total":"1350000","items":["전기 15kW","네트워크 1G"]}'::jsonb,'상시') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 검증(수동): +-- -- 유틸리티 매출: SELECT sum((quote->>'total')::numeric) FROM utility_order +-- -- WHERE event_id='e-2026-live' AND quote->>'total' ~ '^[0-9]+(\.[0-9]+)?$'; -- ~20,000,000+ +-- -- 대시보드 유틸리티 신청 수: SELECT count(*) FROM utility_order WHERE event_id='e-2026-live'; -- 12 +-- ============================================================================ diff --git a/src/backend/src/main/resources/db/migration/V75__cms_content_hero_images.sql b/src/backend/src/main/resources/db/migration/V75__cms_content_hero_images.sql new file mode 100644 index 0000000..d6050c8 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V75__cms_content_hero_images.sql @@ -0,0 +1,39 @@ +-- V75__cms_content_hero_images.sql +-- 목적: CMS 콘텐츠(cms_content)에 대표 이미지(hero/썸네일) 연결 — 데모 시연용. +-- 기존엔 이미지 컬럼이 없고 프론트 미디어 라이브러리가 플레이스홀더 아이콘만 표시했다. +-- → hero_url 컬럼 신설 + 크롤 자산(빌드 내장 정적자산) 백필/시드. +-- 원천: kintex.com 공개 홍보 포스터·시설 전경(V46 크롤 자산 재사용 — 재크롤 없음). +-- /media/hero/hero-*.jpg(시설 전경), /media/posters/kx-*.jpg(행사 포스터). +-- 멱등: ADD COLUMN IF NOT EXISTS · 백필은 hero_url IS NULL 조건(기존 값 클로버 금지) · INSERT ON CONFLICT DO NOTHING. +-- 스코프: tenant 컬럼 없는 cms_content(전역 콘텐츠). 행사스코프 신규 행은 e-2026-live 정렬. + +-- ── 1) 대표 이미지 컬럼 ─────────────────────────────────────────────────────── +ALTER TABLE cms_content ADD COLUMN IF NOT EXISTS hero_url varchar(500); + +-- ── 2) 기존 콘텐츠 백필(COALESCE 방식 — hero_url 미설정 행만) ────────────────── +-- V19 전역 시드(event_id NULL) +UPDATE cms_content SET hero_url = '/media/hero/hero-1.jpg' WHERE id = 'cms-home' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/hero/hero-3.jpg' WHERE id = 'cms-notice' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/hero/hero-2.jpg' WHERE id = 'cms-about' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/posters/kx-468958-1.jpg' WHERE id = 'cms-speaker' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/hero/hero-4.jpg' WHERE id = 'cms-faq' AND hero_url IS NULL; + +-- V39 데모 폐루프 시드(e-2026-live / e-2026-live2) +UPDATE cms_content SET hero_url = '/media/hero/hero-5.jpg' WHERE id = 'cms-v39-nt1' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/posters/kx-469060-1.jpg' WHERE id = 'cms-v39-nt2' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/posters/kx-469082-1.jpg' WHERE id = 'cms-v39-nt4' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/posters/kx-469112-1.jpg' WHERE id = 'cms-v39-nt6' AND hero_url IS NULL; +UPDATE cms_content SET hero_url = '/media/posters/kx-468981-1.jpg' WHERE id = 'cms-v39-pg1' AND hero_url IS NULL; + +-- ── 3) 이미지 중심 신규 콘텐츠(e-2026-live 스코프, 게시 상태) ────────────────── +INSERT INTO cms_content (id, event_id, content_type, title, body, status, lang, signage, mailing, author_name, hero_url, published_at) +VALUES + ('cms-live-gallery', 'e-2026-live', 'PAGE', + '전시장 시설 안내 — KINTEX 제1·2전시장', + '10만㎡ 규모의 무주(無柱) 대공간 전시홀과 국제회의장을 소개합니다. 홀별 평면도·동선·편의시설은 관람 안내에서 확인하세요.', + 'published', 'ko', true, false, '주최 사무국', '/media/hero/hero-1.jpg', now() - interval '3 day'), + ('cms-live-highlight', 'e-2026-live', 'POST', + '개막 현장 하이라이트 — 주요 부스 스케치', + '개막일 주요 참가업체 부스와 키노트 현장을 사진으로 전합니다. 스마트팩토리·로보틱스·AI 자동화 존이 큰 관심을 받았습니다.', + 'published', 'ko', false, true, '주최 사무국', '/media/posters/kx-469129-6.jpg', now() - interval '18 hour') +ON CONFLICT (id) DO NOTHING;