refs #729: seed RDS carrier performance demo
This commit is contained in:
@@ -68,6 +68,7 @@ DDS 변형의 능력 (멀티테넌트, OAuth2 federated identity, MAC 모드,
|
|||||||
| VPD 백오피스 화면 | `src/main/resources/templates/` | Thymeleaf 서버 렌더링 화면 |
|
| VPD 백오피스 화면 | `src/main/resources/templates/` | Thymeleaf 서버 렌더링 화면 |
|
||||||
| VPD 백오피스 CSS/JS | `src/main/resources/static/` | 화면 동작과 스타일 |
|
| VPD 백오피스 CSS/JS | `src/main/resources/static/` | 화면 동작과 스타일 |
|
||||||
| VPD/ASO/FGA/ORDS/Select AI SQL | `sql/adb/` | ADB 적용·검증 SQL 스크립트 |
|
| VPD/ASO/FGA/ORDS/Select AI SQL | `sql/adb/` | ADB 적용·검증 SQL 스크립트 |
|
||||||
|
| 원격 원장 seed/검증 SQL | `sql/source/` | PostgreSQL·MySQL 가상 원장과 HMM 선사 실적 데이터 |
|
||||||
| DDS 백오피스 | `dds-backoffice/` | VPD와 분리된 DDS 전용 Spring Boot 데모 |
|
| DDS 백오피스 | `dds-backoffice/` | VPD와 분리된 DDS 전용 Spring Boot 데모 |
|
||||||
| Streamlit 외피 / PoC4 MCP AI Console | `poc4_active_source_20260714/` | ReAct-style로 MCP tool을 호출하는 PoC4 데모 소스 snapshot |
|
| Streamlit 외피 / PoC4 MCP AI Console | `poc4_active_source_20260714/` | ReAct-style로 MCP tool을 호출하는 PoC4 데모 소스 snapshot |
|
||||||
| Streamlit 외피 메인 화면 | `poc4_active_source_20260714/apps/poc4/mcp_discovery_ui.py` | MCP discovery, tool routing, ReAct-style agent loop, FGA evidence 표시 |
|
| Streamlit 외피 메인 화면 | `poc4_active_source_20260714/apps/poc4/mcp_discovery_ui.py` | MCP discovery, tool routing, ReAct-style agent loop, FGA evidence 표시 |
|
||||||
@@ -97,6 +98,7 @@ Git 기준은 다음과 같다.
|
|||||||
| 계층 | 객체 | 역할 |
|
| 계층 | 객체 | 역할 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 원격 | `public.customers` (PG), `ecommerce_poc.customers` (MySQL) | 원본 데이터 |
|
| 원격 | `public.customers` (PG), `ecommerce_poc.customers` (MySQL) | 원본 데이터 |
|
||||||
|
| 원격 HMM 데모 | `hmm_demo.carriers`, `hmm_demo.carrier_monthly_performance` (PG) | 가상 선사 기준정보와 최근 18개월 월간 KPI |
|
||||||
| ADB - 연결 | `RDS_POSTGRES_LINK`, `RDS_LINK` | `DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK` 로 만든 heterogeneous DB Link |
|
| ADB - 연결 | `RDS_POSTGRES_LINK`, `RDS_LINK` | `DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK` 로 만든 heterogeneous DB Link |
|
||||||
| ADB - 매핑 | `app_customer`, `app_user`, `app_group`, `user_group`, `db_source`, `permission` | 누가 어느 소스의 어느 region 을 볼 수 있는지 |
|
| ADB - 매핑 | `app_customer`, `app_user`, `app_group`, `user_group`, `db_source`, `permission` | 누가 어느 소스의 어느 region 을 볼 수 있는지 |
|
||||||
| ADB - 컨텍스트 | `vpd_ctx` (Secure Application Context) + `ctx_pkg` | 로그인 시 권한을 세션 컨텍스트로 로딩 |
|
| ADB - 컨텍스트 | `vpd_ctx` (Secure Application Context) + `ctx_pkg` | 로그인 시 권한을 세션 컨텍스트로 로딩 |
|
||||||
@@ -261,6 +263,8 @@ CREATE DATA GRANT admin.alice_apac_grant
|
|||||||
├── sql/
|
├── sql/
|
||||||
│ ├── source/
|
│ ├── source/
|
||||||
│ │ ├── postgres_setup.sql # 원격 PG: customers + 12 rows
|
│ │ ├── postgres_setup.sql # 원격 PG: customers + 12 rows
|
||||||
|
│ │ ├── postgres_hmm_carrier_performance.sql # 원격 PG: HMM 가상 선사 8개 + 월간 KPI 144 rows
|
||||||
|
│ │ ├── postgres_hmm_carrier_performance_verify.sql # HMM 선사 실적 건수·패턴·제약·TLS·권한 검증
|
||||||
│ │ └── mysql_setup.sql # 원격 MySQL: customers + 12 rows
|
│ │ └── mysql_setup.sql # 원격 MySQL: customers + 12 rows
|
||||||
│ └── adb/
|
│ └── adb/
|
||||||
│ ├── 00_cleanup.sql # 멱등 teardown
|
│ ├── 00_cleanup.sql # 멱등 teardown
|
||||||
|
|||||||
139
docs/design/729-rds-carrier-performance-demo/README.md
Normal file
139
docs/design/729-rds-carrier-performance-demo/README.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# HMM RDS PostgreSQL 가상 선사 실적 데이터
|
||||||
|
|
||||||
|
- Redmine: #729
|
||||||
|
- 적용 브랜치: `hmm-backoffice`
|
||||||
|
- 원격 원장: AWS RDS for PostgreSQL
|
||||||
|
- 대상 스키마: `hmm_demo`
|
||||||
|
- 기준월 범위: 2025-02-01 ~ 2026-07-01
|
||||||
|
|
||||||
|
## 1. 배경
|
||||||
|
|
||||||
|
HMM 데모는 Oracle ADB의 직원·조직·권한 데이터와 AWS RDS PostgreSQL의 선사 실적을
|
||||||
|
federation으로 결합한다. 사용자는 ADB에서 발급한 토큰으로 식별하고, 팀원은 자신에게
|
||||||
|
배정된 선사만, 팀장은 팀원에게 배정된 선사 전체를 조회하는 흐름을 보여준다.
|
||||||
|
|
||||||
|
이번 단계에서는 federation 연결 전에 RDS에 재현 가능한 가상 선사 실적 원장을 만든다.
|
||||||
|
실제 회사나 실제 재무 실적처럼 오인되지 않도록 모든 선사명과 수치는 데모 전용으로
|
||||||
|
생성한다.
|
||||||
|
|
||||||
|
## 2. 시스템별 책임
|
||||||
|
|
||||||
|
| 시스템 | 보관 정보 | 접근 제어 책임 |
|
||||||
|
|---|---|---|
|
||||||
|
| RDS PostgreSQL | 선사 기본정보, 선사별 월간 KPI | 전용 스키마와 조회 전용 역할 |
|
||||||
|
| Oracle ADB | 직원, 팀, 담당 선사 배정, 사용자 토큰 | VPD와 사용자 세션 context |
|
||||||
|
| Select AI/MCP | 자연어 질문, 보안 View 조회 | ADB에서 허용한 View만 사용 |
|
||||||
|
|
||||||
|
직원 사번이나 팀 정보는 RDS에 복제하지 않는다. RDS 데이터에는 선사 코드만 두고, 직원과
|
||||||
|
선사의 배정 관계는 후속 ADB 단계에서 `HMM_CARRIER_ASSIGNMENTS`로 관리한다.
|
||||||
|
|
||||||
|
## 3. 데이터 모델
|
||||||
|
|
||||||
|
### 3.1 `hmm_demo.carriers`
|
||||||
|
|
||||||
|
가상 선사 기준정보다.
|
||||||
|
|
||||||
|
| 컬럼 | 형식 | 설명 |
|
||||||
|
|---|---|---|
|
||||||
|
| `carrier_code` | `varchar(10)` | 가상 선사 식별 코드, PK |
|
||||||
|
| `carrier_name` | `varchar(120)` | 가상 선사명, UNIQUE |
|
||||||
|
| `country_code` | `char(2)` | ISO 형식의 데모 국가 코드 |
|
||||||
|
| `alliance_name` | `varchar(80)` | 가상 협력 네트워크 |
|
||||||
|
| `service_region` | `varchar(40)` | 주력 운항 권역 |
|
||||||
|
| `performance_tier` | `varchar(10)` | `CORE`, `GROWTH`, `WATCH` |
|
||||||
|
| `active` | `boolean` | 사용 여부 |
|
||||||
|
| `created_at` | `timestamptz` | 최초 생성 시각 |
|
||||||
|
|
||||||
|
### 3.2 `hmm_demo.carrier_monthly_performance`
|
||||||
|
|
||||||
|
선사별 월간 실적 fact다. 한 선사·한 기준월에 한 행만 허용한다.
|
||||||
|
|
||||||
|
| 컬럼 | 형식 | 설명 |
|
||||||
|
|---|---|---|
|
||||||
|
| `carrier_code` | `varchar(10)` | 선사 코드, FK |
|
||||||
|
| `performance_month` | `date` | 월의 첫째 날 |
|
||||||
|
| `contracted_teu` | `integer` | 계약 물동량 |
|
||||||
|
| `shipped_teu` | `integer` | 실제 운송 물동량 |
|
||||||
|
| `revenue_usd` | `numeric(16,2)` | 매출 |
|
||||||
|
| `gross_margin_usd` | `numeric(16,2)` | 매출총이익, 위험 패턴은 음수 허용 |
|
||||||
|
| `schedule_reliability_pct` | `numeric(5,2)` | 정시 운항률 |
|
||||||
|
| `vessel_utilization_pct` | `numeric(5,2)` | 선복 활용률 |
|
||||||
|
| `claim_rate_pct` | `numeric(5,2)` | 클레임 비율 |
|
||||||
|
| `yoy_growth_pct` | `numeric(7,2)` | 전년 동월 대비 성장률 |
|
||||||
|
| `risk_level` | `varchar(10)` | `GREEN`, `AMBER`, `RED` |
|
||||||
|
| `updated_at` | `timestamptz` | 적재 시각 |
|
||||||
|
|
||||||
|
PK는 `(carrier_code, performance_month)`다. 퍼센트 값은 0~100, 물동량과 매출은 0 이상을
|
||||||
|
CHECK 제약으로 보장한다. 월별 조회와 위험 선사 조회에 각각 인덱스를 둔다.
|
||||||
|
|
||||||
|
### 3.3 `hmm_demo.carrier_performance_latest_v`
|
||||||
|
|
||||||
|
가장 최근 기준월의 선사명과 KPI를 한 번에 조회하는 View다. 후속 federation 점검과
|
||||||
|
백오피스 미리보기에서 사용한다.
|
||||||
|
|
||||||
|
## 4. 가상 데이터
|
||||||
|
|
||||||
|
8개 가상 선사와 18개월 실적 144행을 만든다.
|
||||||
|
|
||||||
|
| 코드 | 가상 선사 | 의도한 데모 패턴 |
|
||||||
|
|---|---|---|
|
||||||
|
| `C001` | Bluewave Maritime | 높은 정시율과 지속 성장 |
|
||||||
|
| `C002` | Pacific Star Lines | 안정적 실적 |
|
||||||
|
| `C003` | Korea Ocean Link | 정시율과 클레임률 회복 |
|
||||||
|
| `C004` | Nordic Seaways | 계절성 변동 |
|
||||||
|
| `C005` | Orient Bridge Shipping | 점진적 물동량·마진 하락 |
|
||||||
|
| `C006` | Atlantic Merchant Line | 정시율 저하와 클레임 증가 |
|
||||||
|
| `C007` | Global Horizon Cargo | 빠른 성장 |
|
||||||
|
| `C008` | Southern Cross Marine | 지속적인 고위험 패턴 |
|
||||||
|
|
||||||
|
모든 수치는 프로파일 상수와 월 순번으로 계산한다. 난수를 사용하지 않으므로 어느 환경에서
|
||||||
|
다시 실행해도 같은 결과가 만들어진다.
|
||||||
|
|
||||||
|
## 5. 재실행과 변경 규칙
|
||||||
|
|
||||||
|
- `CREATE SCHEMA/TABLE IF NOT EXISTS`를 사용한다.
|
||||||
|
- 기준정보와 실적은 PK 기준 `ON CONFLICT DO UPDATE`로 현행화한다.
|
||||||
|
- 스크립트가 소유하지 않은 행은 삭제하지 않는다.
|
||||||
|
- 전체 실행은 하나의 transaction으로 처리한다.
|
||||||
|
- 오류가 발생하면 `ON_ERROR_STOP`과 transaction rollback으로 부분 적재를 방지한다.
|
||||||
|
- 비밀번호, endpoint, CA 파일 경로는 SQL에 넣지 않는다.
|
||||||
|
|
||||||
|
## 6. 보안
|
||||||
|
|
||||||
|
- `hmm_federation_reader`는 `NOLOGIN` 그룹 역할로 만든다.
|
||||||
|
- 해당 역할에는 `hmm_demo`의 `USAGE`와 테이블/View `SELECT`만 부여한다.
|
||||||
|
- ADB database link용 LOGIN 역할과 비밀번호는 federation 단계에서 별도로 생성하고
|
||||||
|
`hmm_federation_reader` 역할만 상속시킨다.
|
||||||
|
- DDL/DML 권한과 `public` 스키마 변경 권한은 federation 역할에 부여하지 않는다.
|
||||||
|
- RDS 연결은 AWS global CA bundle과 `sslmode=verify-full`로 검증한다.
|
||||||
|
|
||||||
|
## 7. 적재 순서
|
||||||
|
|
||||||
|
1. RDS TLS와 현재 계정의 CREATE 권한을 확인한다.
|
||||||
|
2. `sql/source/postgres_hmm_carrier_performance.sql`을 실행한다.
|
||||||
|
3. `sql/source/postgres_hmm_carrier_performance_verify.sql`을 실행한다.
|
||||||
|
4. 재실행 후에도 동일한 선사 8개와 실적 144행인지 확인한다.
|
||||||
|
5. 후속 작업에서 ADB credential과 PostgreSQL database link를 만든다.
|
||||||
|
|
||||||
|
## 8. 검증 기준
|
||||||
|
|
||||||
|
- 선사 수: `8`
|
||||||
|
- 월간 실적: `144`
|
||||||
|
- 선사별 월 수: 모두 `18`
|
||||||
|
- 기간: `2025-02-01` ~ `2026-07-01`
|
||||||
|
- 최신월 위험 분포에 `GREEN`, `AMBER`, `RED`가 모두 존재
|
||||||
|
- `C001`의 최신 매출이 최초 매출보다 증가
|
||||||
|
- `C005`, `C006`, `C008`의 최신 매출이 최초 매출보다 감소
|
||||||
|
- 존재하지 않는 선사 코드, 잘못된 퍼센트, 월 첫째 날이 아닌 날짜 입력 거부
|
||||||
|
- `hmm_federation_reader`에 `SELECT`만 부여
|
||||||
|
- TLS 1.2 이상으로 실제 조회 성공
|
||||||
|
|
||||||
|
## 9. 제외 범위
|
||||||
|
|
||||||
|
- ADB의 `HMM_CARRIER_ASSIGNMENTS` 생성과 직원별 배정
|
||||||
|
- ADB PostgreSQL database link 생성
|
||||||
|
- ADB 보안 View와 VPD 정책
|
||||||
|
- Select AI profile 및 MCP tool 변경
|
||||||
|
- 실제 선사명이나 실제 경영 실적 적재
|
||||||
|
|
||||||
|
이 항목들은 RDS 가상 원장이 검증된 뒤 별도 단계로 진행한다.
|
||||||
300
sql/source/postgres_hmm_carrier_performance.sql
Normal file
300
sql/source/postgres_hmm_carrier_performance.sql
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- HMM demo carrier performance source data for PostgreSQL.
|
||||||
|
--
|
||||||
|
-- Target: AWS RDS for PostgreSQL, database postgres
|
||||||
|
-- Schema: hmm_demo
|
||||||
|
-- Redmine: #729
|
||||||
|
--
|
||||||
|
-- This script is idempotent. It owns only C001..C008 and their
|
||||||
|
-- 2025-02 through 2026-07 monthly demo rows. It never stores an
|
||||||
|
-- RDS endpoint, password, or certificate path.
|
||||||
|
--
|
||||||
|
-- Example:
|
||||||
|
-- PGPASSWORD="$PG_PASSWORD" psql \
|
||||||
|
-- "host=$PG_HOST port=5432 dbname=postgres user=$PG_USER \
|
||||||
|
-- sslmode=verify-full sslrootcert=$PG_SSL_ROOT_CERT" \
|
||||||
|
-- -X -f sql/source/postgres_hmm_carrier_performance.sql
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
\echo === HMM carrier performance demo: begin ===
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE SCHEMA IF NOT EXISTS hmm_demo AUTHORIZATION postgres;
|
||||||
|
COMMENT ON SCHEMA hmm_demo IS
|
||||||
|
'HMM federation demonstration data. All carrier names and KPI values are fictional.';
|
||||||
|
|
||||||
|
REVOKE CREATE ON SCHEMA hmm_demo FROM PUBLIC;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS hmm_demo.carriers (
|
||||||
|
carrier_code VARCHAR(10) PRIMARY KEY,
|
||||||
|
carrier_name VARCHAR(120) NOT NULL UNIQUE,
|
||||||
|
country_code CHAR(2) NOT NULL CHECK (country_code ~ '^[A-Z]{2}$'),
|
||||||
|
alliance_name VARCHAR(80),
|
||||||
|
service_region VARCHAR(40) NOT NULL,
|
||||||
|
performance_tier VARCHAR(10) NOT NULL
|
||||||
|
CHECK (performance_tier IN ('CORE', 'GROWTH', 'WATCH')),
|
||||||
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON TABLE hmm_demo.carriers IS
|
||||||
|
'Fictional carrier master data for the HMM ADB and PostgreSQL federation demo.';
|
||||||
|
COMMENT ON COLUMN hmm_demo.carriers.carrier_code IS 'Fictional carrier identifier.';
|
||||||
|
COMMENT ON COLUMN hmm_demo.carriers.performance_tier IS
|
||||||
|
'Demo portfolio tier: CORE, GROWTH, or WATCH.';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS hmm_demo.carrier_monthly_performance (
|
||||||
|
carrier_code VARCHAR(10) NOT NULL
|
||||||
|
REFERENCES hmm_demo.carriers (carrier_code),
|
||||||
|
performance_month DATE NOT NULL
|
||||||
|
CHECK (performance_month = date_trunc('month', performance_month)::DATE),
|
||||||
|
contracted_teu INTEGER NOT NULL CHECK (contracted_teu >= 0),
|
||||||
|
shipped_teu INTEGER NOT NULL CHECK (shipped_teu >= 0),
|
||||||
|
revenue_usd NUMERIC(16,2) NOT NULL CHECK (revenue_usd >= 0),
|
||||||
|
gross_margin_usd NUMERIC(16,2) NOT NULL,
|
||||||
|
schedule_reliability_pct NUMERIC(5,2) NOT NULL
|
||||||
|
CHECK (schedule_reliability_pct BETWEEN 0 AND 100),
|
||||||
|
vessel_utilization_pct NUMERIC(5,2) NOT NULL
|
||||||
|
CHECK (vessel_utilization_pct BETWEEN 0 AND 100),
|
||||||
|
claim_rate_pct NUMERIC(5,2) NOT NULL
|
||||||
|
CHECK (claim_rate_pct BETWEEN 0 AND 100),
|
||||||
|
yoy_growth_pct NUMERIC(7,2) NOT NULL,
|
||||||
|
risk_level VARCHAR(10) NOT NULL
|
||||||
|
CHECK (risk_level IN ('GREEN', 'AMBER', 'RED')),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL,
|
||||||
|
PRIMARY KEY (carrier_code, performance_month)
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON TABLE hmm_demo.carrier_monthly_performance IS
|
||||||
|
'Deterministic fictional monthly carrier KPIs for 2025-02 through 2026-07.';
|
||||||
|
COMMENT ON COLUMN hmm_demo.carrier_monthly_performance.performance_month IS
|
||||||
|
'First calendar day of the KPI month.';
|
||||||
|
COMMENT ON COLUMN hmm_demo.carrier_monthly_performance.risk_level IS
|
||||||
|
'Derived demo risk level based on margin, reliability, and claim rate.';
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_carrier_perf_month
|
||||||
|
ON hmm_demo.carrier_monthly_performance (performance_month, carrier_code);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_carrier_perf_risk
|
||||||
|
ON hmm_demo.carrier_monthly_performance (risk_level, performance_month);
|
||||||
|
|
||||||
|
INSERT INTO hmm_demo.carriers (
|
||||||
|
carrier_code,
|
||||||
|
carrier_name,
|
||||||
|
country_code,
|
||||||
|
alliance_name,
|
||||||
|
service_region,
|
||||||
|
performance_tier,
|
||||||
|
active
|
||||||
|
) VALUES
|
||||||
|
('C001', 'Bluewave Maritime', 'SG', 'North Pacific Network', 'ASIA-PACIFIC', 'CORE', TRUE),
|
||||||
|
('C002', 'Pacific Star Lines', 'JP', 'East Ocean Connect', 'ASIA-PACIFIC', 'CORE', TRUE),
|
||||||
|
('C003', 'Korea Ocean Link', 'KR', 'East Ocean Connect', 'ASIA-PACIFIC', 'GROWTH', TRUE),
|
||||||
|
('C004', 'Nordic Seaways', 'DK', 'Northern Trade Group', 'EUROPE', 'CORE', TRUE),
|
||||||
|
('C005', 'Orient Bridge Shipping', 'TW', 'North Pacific Network', 'ASIA-PACIFIC', 'WATCH', TRUE),
|
||||||
|
('C006', 'Atlantic Merchant Line', 'DE', 'Atlantic Cargo Forum', 'EUROPE-AMERICAS', 'WATCH', TRUE),
|
||||||
|
('C007', 'Global Horizon Cargo', 'US', 'Atlantic Cargo Forum', 'AMERICAS', 'GROWTH', TRUE),
|
||||||
|
('C008', 'Southern Cross Marine', 'FR', 'Southern Ocean Group', 'OCEANIA', 'WATCH', TRUE)
|
||||||
|
ON CONFLICT (carrier_code) DO UPDATE SET
|
||||||
|
carrier_name = EXCLUDED.carrier_name,
|
||||||
|
country_code = EXCLUDED.country_code,
|
||||||
|
alliance_name = EXCLUDED.alliance_name,
|
||||||
|
service_region = EXCLUDED.service_region,
|
||||||
|
performance_tier = EXCLUDED.performance_tier,
|
||||||
|
active = EXCLUDED.active;
|
||||||
|
|
||||||
|
WITH month_series AS (
|
||||||
|
SELECT
|
||||||
|
month_index,
|
||||||
|
(DATE '2025-02-01' + make_interval(months => month_index))::DATE AS performance_month,
|
||||||
|
CASE month_index % 6
|
||||||
|
WHEN 0 THEN -1
|
||||||
|
WHEN 1 THEN 0
|
||||||
|
WHEN 2 THEN 1
|
||||||
|
WHEN 3 THEN 2
|
||||||
|
WHEN 4 THEN 1
|
||||||
|
ELSE -1
|
||||||
|
END::NUMERIC AS seasonal_factor
|
||||||
|
FROM generate_series(0, 17) AS series(month_index)
|
||||||
|
),
|
||||||
|
profiles (
|
||||||
|
carrier_code,
|
||||||
|
base_teu,
|
||||||
|
monthly_teu_step,
|
||||||
|
seasonal_teu,
|
||||||
|
utilization_base,
|
||||||
|
utilization_step,
|
||||||
|
revenue_per_teu,
|
||||||
|
revenue_step,
|
||||||
|
margin_pct_base,
|
||||||
|
margin_pct_step,
|
||||||
|
reliability_base,
|
||||||
|
reliability_step,
|
||||||
|
claim_rate_base,
|
||||||
|
claim_rate_step,
|
||||||
|
yoy_growth_base,
|
||||||
|
yoy_growth_step
|
||||||
|
) AS (
|
||||||
|
VALUES
|
||||||
|
('C001', 1800::NUMERIC, 25::NUMERIC, 80::NUMERIC, 91.5::NUMERIC, 0.10::NUMERIC, 1850::NUMERIC, 4::NUMERIC, 15.0::NUMERIC, 0.10::NUMERIC, 95.0::NUMERIC, 0.05::NUMERIC, 0.35::NUMERIC, -0.005::NUMERIC, 8.0::NUMERIC, 0.25::NUMERIC),
|
||||||
|
('C002', 1500::NUMERIC, 5::NUMERIC, 60::NUMERIC, 88.5::NUMERIC, 0.02::NUMERIC, 1780::NUMERIC, 3::NUMERIC, 12.0::NUMERIC, 0.00::NUMERIC, 92.5::NUMERIC, 0.00::NUMERIC, 0.45::NUMERIC, 0.005::NUMERIC, 3.0::NUMERIC, 0.05::NUMERIC),
|
||||||
|
('C003', 1050::NUMERIC, 15::NUMERIC, 50::NUMERIC, 83.0::NUMERIC, 0.20::NUMERIC, 1920::NUMERIC, 2::NUMERIC, 8.0::NUMERIC, 0.15::NUMERIC, 88.5::NUMERIC, 0.25::NUMERIC, 1.20::NUMERIC, -0.040::NUMERIC, -4.0::NUMERIC, 0.60::NUMERIC),
|
||||||
|
('C004', 1350::NUMERIC, 0::NUMERIC, 180::NUMERIC, 86.0::NUMERIC, 0.00::NUMERIC, 1810::NUMERIC, 3::NUMERIC, 10.0::NUMERIC, 0.00::NUMERIC, 93.0::NUMERIC, 0.00::NUMERIC, 0.55::NUMERIC, 0.010::NUMERIC, 1.0::NUMERIC, 0.10::NUMERIC),
|
||||||
|
('C005', 1300::NUMERIC, -20::NUMERIC, 70::NUMERIC, 88.0::NUMERIC, -0.10::NUMERIC, 1850::NUMERIC, -2::NUMERIC, 8.0::NUMERIC, -0.20::NUMERIC, 91.0::NUMERIC, -0.15::NUMERIC, 0.80::NUMERIC, 0.030::NUMERIC, -2.0::NUMERIC, -0.50::NUMERIC),
|
||||||
|
('C006', 1250::NUMERIC, -10::NUMERIC, 90::NUMERIC, 84.0::NUMERIC, -0.12::NUMERIC, 1800::NUMERIC, -3::NUMERIC, 6.0::NUMERIC, -0.15::NUMERIC, 87.0::NUMERIC, -0.25::NUMERIC, 1.50::NUMERIC, 0.050::NUMERIC, -5.0::NUMERIC, -0.70::NUMERIC),
|
||||||
|
('C007', 800::NUMERIC, 30::NUMERIC, 100::NUMERIC, 82.0::NUMERIC, 0.25::NUMERIC, 2050::NUMERIC, 5::NUMERIC, 9.0::NUMERIC, 0.18::NUMERIC, 90.5::NUMERIC, 0.15::NUMERIC, 0.70::NUMERIC, -0.020::NUMERIC, 12.0::NUMERIC, 0.50::NUMERIC),
|
||||||
|
('C008', 1150::NUMERIC, -25::NUMERIC, 60::NUMERIC, 80.0::NUMERIC, -0.15::NUMERIC, 1750::NUMERIC, -4::NUMERIC, 3.0::NUMERIC, -0.20::NUMERIC, 85.0::NUMERIC, -0.30::NUMERIC, 2.00::NUMERIC, 0.080::NUMERIC, -8.0::NUMERIC, -0.80::NUMERIC)
|
||||||
|
),
|
||||||
|
base_metrics AS (
|
||||||
|
SELECT
|
||||||
|
p.carrier_code,
|
||||||
|
m.performance_month,
|
||||||
|
ROUND(
|
||||||
|
p.base_teu
|
||||||
|
+ p.monthly_teu_step * m.month_index
|
||||||
|
+ p.seasonal_teu * m.seasonal_factor
|
||||||
|
)::INTEGER AS contracted_teu,
|
||||||
|
LEAST(
|
||||||
|
98.0::NUMERIC,
|
||||||
|
GREATEST(
|
||||||
|
60.0::NUMERIC,
|
||||||
|
p.utilization_base
|
||||||
|
+ p.utilization_step * m.month_index
|
||||||
|
+ m.seasonal_factor * 0.50
|
||||||
|
)
|
||||||
|
) AS utilization_pct,
|
||||||
|
p.revenue_per_teu + p.revenue_step * m.month_index AS unit_revenue,
|
||||||
|
p.margin_pct_base + p.margin_pct_step * m.month_index AS margin_pct,
|
||||||
|
LEAST(
|
||||||
|
99.5::NUMERIC,
|
||||||
|
GREATEST(
|
||||||
|
60.0::NUMERIC,
|
||||||
|
p.reliability_base
|
||||||
|
+ p.reliability_step * m.month_index
|
||||||
|
+ m.seasonal_factor * 0.20
|
||||||
|
)
|
||||||
|
) AS reliability_pct,
|
||||||
|
LEAST(
|
||||||
|
100.0::NUMERIC,
|
||||||
|
GREATEST(
|
||||||
|
0.0::NUMERIC,
|
||||||
|
p.claim_rate_base + p.claim_rate_step * m.month_index
|
||||||
|
)
|
||||||
|
) AS claim_pct,
|
||||||
|
p.yoy_growth_base + p.yoy_growth_step * m.month_index AS yoy_pct
|
||||||
|
FROM profiles p
|
||||||
|
CROSS JOIN month_series m
|
||||||
|
),
|
||||||
|
volume_metrics AS (
|
||||||
|
SELECT
|
||||||
|
b.*,
|
||||||
|
ROUND(b.contracted_teu * b.utilization_pct / 100.0)::INTEGER AS shipped_teu
|
||||||
|
FROM base_metrics b
|
||||||
|
),
|
||||||
|
financial_metrics AS (
|
||||||
|
SELECT
|
||||||
|
v.*,
|
||||||
|
ROUND(v.shipped_teu * v.unit_revenue, 2) AS revenue_usd
|
||||||
|
FROM volume_metrics v
|
||||||
|
),
|
||||||
|
final_metrics AS (
|
||||||
|
SELECT
|
||||||
|
f.*,
|
||||||
|
ROUND(f.revenue_usd * f.margin_pct / 100.0, 2) AS gross_margin_usd
|
||||||
|
FROM financial_metrics f
|
||||||
|
)
|
||||||
|
INSERT INTO hmm_demo.carrier_monthly_performance (
|
||||||
|
carrier_code,
|
||||||
|
performance_month,
|
||||||
|
contracted_teu,
|
||||||
|
shipped_teu,
|
||||||
|
revenue_usd,
|
||||||
|
gross_margin_usd,
|
||||||
|
schedule_reliability_pct,
|
||||||
|
vessel_utilization_pct,
|
||||||
|
claim_rate_pct,
|
||||||
|
yoy_growth_pct,
|
||||||
|
risk_level,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
f.carrier_code,
|
||||||
|
f.performance_month,
|
||||||
|
f.contracted_teu,
|
||||||
|
f.shipped_teu,
|
||||||
|
f.revenue_usd,
|
||||||
|
f.gross_margin_usd,
|
||||||
|
ROUND(f.reliability_pct, 2),
|
||||||
|
ROUND(f.utilization_pct, 2),
|
||||||
|
ROUND(f.claim_pct, 2),
|
||||||
|
ROUND(f.yoy_pct, 2),
|
||||||
|
CASE
|
||||||
|
WHEN f.gross_margin_usd < 0
|
||||||
|
OR f.reliability_pct < 87
|
||||||
|
OR f.claim_pct >= 2 THEN 'RED'
|
||||||
|
WHEN f.margin_pct < 7
|
||||||
|
OR f.reliability_pct < 92
|
||||||
|
OR f.claim_pct >= 1 THEN 'AMBER'
|
||||||
|
ELSE 'GREEN'
|
||||||
|
END,
|
||||||
|
TIMESTAMPTZ '2026-07-24 00:00:00+00'
|
||||||
|
FROM final_metrics f
|
||||||
|
ON CONFLICT (carrier_code, performance_month) DO UPDATE SET
|
||||||
|
contracted_teu = EXCLUDED.contracted_teu,
|
||||||
|
shipped_teu = EXCLUDED.shipped_teu,
|
||||||
|
revenue_usd = EXCLUDED.revenue_usd,
|
||||||
|
gross_margin_usd = EXCLUDED.gross_margin_usd,
|
||||||
|
schedule_reliability_pct = EXCLUDED.schedule_reliability_pct,
|
||||||
|
vessel_utilization_pct = EXCLUDED.vessel_utilization_pct,
|
||||||
|
claim_rate_pct = EXCLUDED.claim_rate_pct,
|
||||||
|
yoy_growth_pct = EXCLUDED.yoy_growth_pct,
|
||||||
|
risk_level = EXCLUDED.risk_level,
|
||||||
|
updated_at = EXCLUDED.updated_at;
|
||||||
|
|
||||||
|
CREATE OR REPLACE VIEW hmm_demo.carrier_performance_latest_v AS
|
||||||
|
SELECT
|
||||||
|
c.carrier_code,
|
||||||
|
c.carrier_name,
|
||||||
|
c.country_code,
|
||||||
|
c.alliance_name,
|
||||||
|
c.service_region,
|
||||||
|
c.performance_tier,
|
||||||
|
p.performance_month,
|
||||||
|
p.contracted_teu,
|
||||||
|
p.shipped_teu,
|
||||||
|
p.revenue_usd,
|
||||||
|
p.gross_margin_usd,
|
||||||
|
p.schedule_reliability_pct,
|
||||||
|
p.vessel_utilization_pct,
|
||||||
|
p.claim_rate_pct,
|
||||||
|
p.yoy_growth_pct,
|
||||||
|
p.risk_level
|
||||||
|
FROM hmm_demo.carriers c
|
||||||
|
JOIN hmm_demo.carrier_monthly_performance p
|
||||||
|
ON p.carrier_code = c.carrier_code
|
||||||
|
WHERE p.performance_month = (
|
||||||
|
SELECT MAX(latest.performance_month)
|
||||||
|
FROM hmm_demo.carrier_monthly_performance latest
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMENT ON VIEW hmm_demo.carrier_performance_latest_v IS
|
||||||
|
'Latest fictional monthly KPI for each active demo carrier.';
|
||||||
|
|
||||||
|
DO $role$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'hmm_federation_reader') THEN
|
||||||
|
CREATE ROLE hmm_federation_reader NOLOGIN;
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$role$;
|
||||||
|
|
||||||
|
GRANT USAGE ON SCHEMA hmm_demo TO hmm_federation_reader;
|
||||||
|
GRANT SELECT ON ALL TABLES IN SCHEMA hmm_demo TO hmm_federation_reader;
|
||||||
|
ALTER DEFAULT PRIVILEGES IN SCHEMA hmm_demo
|
||||||
|
GRANT SELECT ON TABLES TO hmm_federation_reader;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
\echo === HMM carrier performance demo: complete ===
|
||||||
|
\echo Next: run sql/source/postgres_hmm_carrier_performance_verify.sql
|
||||||
324
sql/source/postgres_hmm_carrier_performance_verify.sql
Normal file
324
sql/source/postgres_hmm_carrier_performance_verify.sql
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Verification for HMM demo carrier performance data.
|
||||||
|
-- Redmine: #729
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP on
|
||||||
|
\pset pager off
|
||||||
|
\echo === HMM carrier performance demo: verification begin ===
|
||||||
|
|
||||||
|
DO $verify$
|
||||||
|
DECLARE
|
||||||
|
carrier_count INTEGER;
|
||||||
|
performance_count INTEGER;
|
||||||
|
invalid_month_count INTEGER;
|
||||||
|
latest_month DATE;
|
||||||
|
earliest_month DATE;
|
||||||
|
wrong_series_count INTEGER;
|
||||||
|
latest_risk_count INTEGER;
|
||||||
|
wrong_trend_count INTEGER;
|
||||||
|
reader_can_login BOOLEAN;
|
||||||
|
BEGIN
|
||||||
|
SELECT COUNT(*)
|
||||||
|
INTO carrier_count
|
||||||
|
FROM hmm_demo.carriers
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008';
|
||||||
|
|
||||||
|
SELECT COUNT(*), MIN(performance_month), MAX(performance_month)
|
||||||
|
INTO performance_count, earliest_month, latest_month
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
AND performance_month BETWEEN DATE '2025-02-01' AND DATE '2026-07-01';
|
||||||
|
|
||||||
|
SELECT COUNT(*)
|
||||||
|
INTO invalid_month_count
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE performance_month <> date_trunc('month', performance_month)::DATE;
|
||||||
|
|
||||||
|
SELECT COUNT(*)
|
||||||
|
INTO wrong_series_count
|
||||||
|
FROM (
|
||||||
|
SELECT carrier_code, COUNT(*) AS month_count
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
AND performance_month BETWEEN DATE '2025-02-01' AND DATE '2026-07-01'
|
||||||
|
GROUP BY carrier_code
|
||||||
|
HAVING COUNT(*) <> 18
|
||||||
|
) wrong_series;
|
||||||
|
|
||||||
|
SELECT COUNT(DISTINCT risk_level)
|
||||||
|
INTO latest_risk_count
|
||||||
|
FROM hmm_demo.carrier_performance_latest_v;
|
||||||
|
|
||||||
|
WITH boundaries AS (
|
||||||
|
SELECT
|
||||||
|
carrier_code,
|
||||||
|
MAX(revenue_usd) FILTER (WHERE performance_month = DATE '2025-02-01')
|
||||||
|
AS first_revenue,
|
||||||
|
MAX(revenue_usd) FILTER (WHERE performance_month = DATE '2026-07-01')
|
||||||
|
AS latest_revenue
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
GROUP BY carrier_code
|
||||||
|
)
|
||||||
|
SELECT COUNT(*)
|
||||||
|
INTO wrong_trend_count
|
||||||
|
FROM boundaries
|
||||||
|
WHERE (carrier_code IN ('C001', 'C002', 'C003', 'C004', 'C007')
|
||||||
|
AND latest_revenue <= first_revenue)
|
||||||
|
OR (carrier_code IN ('C005', 'C006', 'C008')
|
||||||
|
AND latest_revenue >= first_revenue);
|
||||||
|
|
||||||
|
SELECT rolcanlogin
|
||||||
|
INTO reader_can_login
|
||||||
|
FROM pg_roles
|
||||||
|
WHERE rolname = 'hmm_federation_reader';
|
||||||
|
|
||||||
|
IF carrier_count <> 8 THEN
|
||||||
|
RAISE EXCEPTION 'Expected 8 carriers, found %', carrier_count;
|
||||||
|
END IF;
|
||||||
|
IF performance_count <> 144 THEN
|
||||||
|
RAISE EXCEPTION 'Expected 144 monthly performance rows, found %', performance_count;
|
||||||
|
END IF;
|
||||||
|
IF earliest_month <> DATE '2025-02-01' OR latest_month <> DATE '2026-07-01' THEN
|
||||||
|
RAISE EXCEPTION 'Unexpected period: % through %', earliest_month, latest_month;
|
||||||
|
END IF;
|
||||||
|
IF invalid_month_count <> 0 OR wrong_series_count <> 0 THEN
|
||||||
|
RAISE EXCEPTION
|
||||||
|
'Invalid monthly series: invalid dates %, wrong carrier series %',
|
||||||
|
invalid_month_count,
|
||||||
|
wrong_series_count;
|
||||||
|
END IF;
|
||||||
|
IF latest_risk_count <> 3 THEN
|
||||||
|
RAISE EXCEPTION 'Expected GREEN, AMBER, RED latest risks, found % levels',
|
||||||
|
latest_risk_count;
|
||||||
|
END IF;
|
||||||
|
IF wrong_trend_count <> 0 THEN
|
||||||
|
RAISE EXCEPTION 'Unexpected first-to-latest trend for % carriers', wrong_trend_count;
|
||||||
|
END IF;
|
||||||
|
IF reader_can_login IS DISTINCT FROM FALSE THEN
|
||||||
|
RAISE EXCEPTION 'hmm_federation_reader must remain a NOLOGIN role';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NOT has_schema_privilege('hmm_federation_reader', 'hmm_demo', 'USAGE') THEN
|
||||||
|
RAISE EXCEPTION 'hmm_federation_reader lacks schema USAGE';
|
||||||
|
END IF;
|
||||||
|
IF has_schema_privilege('hmm_federation_reader', 'hmm_demo', 'CREATE') THEN
|
||||||
|
RAISE EXCEPTION 'hmm_federation_reader unexpectedly has schema CREATE';
|
||||||
|
END IF;
|
||||||
|
IF NOT has_table_privilege(
|
||||||
|
'hmm_federation_reader',
|
||||||
|
'hmm_demo.carrier_monthly_performance',
|
||||||
|
'SELECT'
|
||||||
|
) THEN
|
||||||
|
RAISE EXCEPTION 'hmm_federation_reader lacks SELECT';
|
||||||
|
END IF;
|
||||||
|
IF has_table_privilege(
|
||||||
|
'hmm_federation_reader',
|
||||||
|
'hmm_demo.carrier_monthly_performance',
|
||||||
|
'INSERT'
|
||||||
|
) THEN
|
||||||
|
RAISE EXCEPTION 'hmm_federation_reader unexpectedly has INSERT';
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$verify$;
|
||||||
|
|
||||||
|
DO $constraint_tests$
|
||||||
|
BEGIN
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO hmm_demo.carrier_monthly_performance (
|
||||||
|
carrier_code,
|
||||||
|
performance_month,
|
||||||
|
contracted_teu,
|
||||||
|
shipped_teu,
|
||||||
|
revenue_usd,
|
||||||
|
gross_margin_usd,
|
||||||
|
schedule_reliability_pct,
|
||||||
|
vessel_utilization_pct,
|
||||||
|
claim_rate_pct,
|
||||||
|
yoy_growth_pct,
|
||||||
|
risk_level,
|
||||||
|
updated_at
|
||||||
|
) VALUES (
|
||||||
|
'C001',
|
||||||
|
DATE '2026-07-02',
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
90,
|
||||||
|
90,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
'GREEN',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
RAISE EXCEPTION 'Month-first-day constraint did not reject invalid input';
|
||||||
|
EXCEPTION
|
||||||
|
WHEN check_violation THEN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO hmm_demo.carrier_monthly_performance (
|
||||||
|
carrier_code,
|
||||||
|
performance_month,
|
||||||
|
contracted_teu,
|
||||||
|
shipped_teu,
|
||||||
|
revenue_usd,
|
||||||
|
gross_margin_usd,
|
||||||
|
schedule_reliability_pct,
|
||||||
|
vessel_utilization_pct,
|
||||||
|
claim_rate_pct,
|
||||||
|
yoy_growth_pct,
|
||||||
|
risk_level,
|
||||||
|
updated_at
|
||||||
|
) VALUES (
|
||||||
|
'UNKNOWN',
|
||||||
|
DATE '2026-08-01',
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
90,
|
||||||
|
90,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
'GREEN',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
RAISE EXCEPTION 'Foreign key constraint did not reject unknown carrier';
|
||||||
|
EXCEPTION
|
||||||
|
WHEN foreign_key_violation THEN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO hmm_demo.carrier_monthly_performance (
|
||||||
|
carrier_code,
|
||||||
|
performance_month,
|
||||||
|
contracted_teu,
|
||||||
|
shipped_teu,
|
||||||
|
revenue_usd,
|
||||||
|
gross_margin_usd,
|
||||||
|
schedule_reliability_pct,
|
||||||
|
vessel_utilization_pct,
|
||||||
|
claim_rate_pct,
|
||||||
|
yoy_growth_pct,
|
||||||
|
risk_level,
|
||||||
|
updated_at
|
||||||
|
) VALUES (
|
||||||
|
'C001',
|
||||||
|
DATE '2026-08-01',
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
101,
|
||||||
|
90,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
'GREEN',
|
||||||
|
CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
RAISE EXCEPTION 'Percentage constraint did not reject invalid input';
|
||||||
|
EXCEPTION
|
||||||
|
WHEN check_violation THEN
|
||||||
|
NULL;
|
||||||
|
END;
|
||||||
|
END
|
||||||
|
$constraint_tests$;
|
||||||
|
|
||||||
|
\echo --- Row counts and period ---
|
||||||
|
SELECT
|
||||||
|
COUNT(DISTINCT carrier_code) AS carrier_count,
|
||||||
|
COUNT(*) AS monthly_row_count,
|
||||||
|
MIN(performance_month) AS first_month,
|
||||||
|
MAX(performance_month) AS latest_month
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
AND performance_month BETWEEN DATE '2025-02-01' AND DATE '2026-07-01';
|
||||||
|
|
||||||
|
\echo --- Per-carrier series ---
|
||||||
|
SELECT
|
||||||
|
c.carrier_code,
|
||||||
|
c.carrier_name,
|
||||||
|
COUNT(p.*) AS month_count,
|
||||||
|
MIN(p.performance_month) AS first_month,
|
||||||
|
MAX(p.performance_month) AS latest_month
|
||||||
|
FROM hmm_demo.carriers c
|
||||||
|
JOIN hmm_demo.carrier_monthly_performance p
|
||||||
|
ON p.carrier_code = c.carrier_code
|
||||||
|
WHERE c.carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
GROUP BY c.carrier_code, c.carrier_name
|
||||||
|
ORDER BY c.carrier_code;
|
||||||
|
|
||||||
|
\echo --- Latest KPI and risk distribution ---
|
||||||
|
SELECT
|
||||||
|
carrier_code,
|
||||||
|
carrier_name,
|
||||||
|
performance_month,
|
||||||
|
shipped_teu,
|
||||||
|
revenue_usd,
|
||||||
|
gross_margin_usd,
|
||||||
|
schedule_reliability_pct,
|
||||||
|
claim_rate_pct,
|
||||||
|
risk_level
|
||||||
|
FROM hmm_demo.carrier_performance_latest_v
|
||||||
|
ORDER BY carrier_code;
|
||||||
|
|
||||||
|
SELECT risk_level, COUNT(*) AS carrier_count
|
||||||
|
FROM hmm_demo.carrier_performance_latest_v
|
||||||
|
GROUP BY risk_level
|
||||||
|
ORDER BY risk_level;
|
||||||
|
|
||||||
|
\echo --- First-to-latest revenue trend ---
|
||||||
|
WITH boundaries AS (
|
||||||
|
SELECT
|
||||||
|
carrier_code,
|
||||||
|
MAX(revenue_usd) FILTER (WHERE performance_month = DATE '2025-02-01') AS first_revenue,
|
||||||
|
MAX(revenue_usd) FILTER (WHERE performance_month = DATE '2026-07-01') AS latest_revenue
|
||||||
|
FROM hmm_demo.carrier_monthly_performance
|
||||||
|
WHERE carrier_code BETWEEN 'C001' AND 'C008'
|
||||||
|
GROUP BY carrier_code
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
carrier_code,
|
||||||
|
first_revenue,
|
||||||
|
latest_revenue,
|
||||||
|
CASE
|
||||||
|
WHEN latest_revenue > first_revenue THEN 'UP'
|
||||||
|
WHEN latest_revenue < first_revenue THEN 'DOWN'
|
||||||
|
ELSE 'FLAT'
|
||||||
|
END AS trend
|
||||||
|
FROM boundaries
|
||||||
|
ORDER BY carrier_code;
|
||||||
|
|
||||||
|
\echo --- TLS session ---
|
||||||
|
SELECT
|
||||||
|
ssl,
|
||||||
|
version AS tls_version,
|
||||||
|
cipher,
|
||||||
|
bits
|
||||||
|
FROM pg_stat_ssl
|
||||||
|
WHERE pid = pg_backend_pid();
|
||||||
|
|
||||||
|
\echo --- Read-only role privileges ---
|
||||||
|
SELECT
|
||||||
|
(SELECT NOT rolcanlogin
|
||||||
|
FROM pg_roles
|
||||||
|
WHERE rolname = 'hmm_federation_reader') AS no_login,
|
||||||
|
has_schema_privilege('hmm_federation_reader', 'hmm_demo', 'USAGE') AS schema_usage,
|
||||||
|
has_schema_privilege('hmm_federation_reader', 'hmm_demo', 'CREATE') AS schema_create,
|
||||||
|
has_table_privilege(
|
||||||
|
'hmm_federation_reader',
|
||||||
|
'hmm_demo.carrier_monthly_performance',
|
||||||
|
'SELECT'
|
||||||
|
) AS can_select,
|
||||||
|
has_table_privilege(
|
||||||
|
'hmm_federation_reader',
|
||||||
|
'hmm_demo.carrier_monthly_performance',
|
||||||
|
'INSERT'
|
||||||
|
) AS can_insert;
|
||||||
|
|
||||||
|
\echo === HMM carrier performance demo: verification complete ===
|
||||||
Reference in New Issue
Block a user