14 KiB
14 KiB
일일/월간/연간 생산 레포트 구현 계획
현황 파악
| 항목 | 내용 |
|---|---|
| DB | PostgreSQL + TimescaleDB, history_table |
| 데이터 주기 | 1분 스냅샷 |
| 현재 태그 수 | 1,807개 |
| 이용 가능 태그 종류 | FI, FICQ, FIC, LI, LICA, TI, TICA, PI, PIC 등 |
⚠️ 구현 전 반드시 확인해야 할 사항 (사용자 결정 필요)
1. 생산량 정의
어떤 태그가 "생산량"을 나타내는지 사용자가 지정해야 한다.
| 질문 | 예시 |
|---|---|
| 주요 생산 제품은? | 예: 에틸렌, LPG, 나프타 등 |
| 각 제품의 생산량 태그는? | 예: ficq-6101.pv = 6호기 에틸렌 출하 유량 |
| 유량의 공학 단위는? | 예: ton/hr, Nm³/hr, kg/hr |
| 적산 방법은? | 순간유량(PV) × 1분 → 시간적산, 또는 별도 적산 태그 존재 여부 |
| 조업시간 판정 기준 태그는? | 예: 특정 태그값 > 0 이면 운전 중 |
2. 레포트 항목 정의
사용자가 원하는 레포트 항목을 구체화해야 한다. 아래는 일반적인 공정 플랜트 기준 초안.
레포트 구조 설계 (초안)
일일 레포트 (1일치)
┌────────────────────────────────────────────────────────┐
│ ○○플랜트 일일 생산 레포트 2026-05-01 (목) │
├──────────────┬─────────────────────────────────────────┤
│ 1. 생산 실적 │ 제품별 일일 생산량 (ton 또는 Nm³) │
│ │ - 각 FICQ 태그 적산값 │
│ │ - 전일 대비 증감 │
│ │ - 월 누계 │
├──────────────┼─────────────────────────────────────────┤
│ 2. 조업 현황 │ 운전시간 (분), 가동률 (%) │
│ │ 트러블/정지 횟수 │
├──────────────┼─────────────────────────────────────────┤
│ 3. 주요 공정 │ 핵심 온도/압력/레벨 태그 평균·최대·최소 │
│ 조건 │ (TI, PI, LI 대표 태그 선정) │
├──────────────┼─────────────────────────────────────────┤
│ 4. 품질 지표 │ 해당 태그 존재 시 추가 │
└──────────────┴─────────────────────────────────────────┘
월간 레포트 (1개월치 — 일별 집계)
┌────────────────────────────────────────────────────────┐
│ ○○플랜트 월간 생산 레포트 2026년 5월 │
├──────────────┬─────────────────────────────────────────┤
│ 1. 월간 생산 │ 제품별 월 총 생산량 │
│ 실적 │ 일별 생산량 추이 (테이블 + 차트) │
│ │ 최대/최소 생산일 │
├──────────────┼─────────────────────────────────────────┤
│ 2. 가동률 │ 월간 가동 시간 / 목표 시간 │
│ │ 일별 가동률 테이블 │
├──────────────┼─────────────────────────────────────────┤
│ 3. 공정 조건 │ 월 평균·최대·최소 (온도, 압력, 레벨) │
│ 통계 │ 일별 평균 추이 테이블 │
└──────────────┴─────────────────────────────────────────┘
연간 레포트 (1년치 — 월별 집계)
┌────────────────────────────────────────────────────────┐
│ ○○플랜트 연간 생산 레포트 2026년 │
├──────────────┬─────────────────────────────────────────┤
│ 1. 월별 생산 │ 제품별 월별 생산량 (1~12월 테이블) │
│ 실적 │ 연 총 생산량 │
├──────────────┼─────────────────────────────────────────┤
│ 2. 월별 가동률│ 월별 가동시간 / 가동률 │
├──────────────┼─────────────────────────────────────────┤
│ 3. 공정 조건 │ 월별 평균 공정 조건 추이 │
│ 월별 통계 │ │
└──────────────┴─────────────────────────────────────────┘
핵심 SQL 설계
일일 유량 적산 (1분 데이터 → 일일 합계)
-- FICQ 태그 일일 적산값 (단위: 공학단위/분 × 1440분)
-- 순간유량이 ton/hr 단위일 경우 × (1/60) = ton/분
SELECT
recorded_at::date AS day,
tagname,
SUM(value::double precision / 60.0) AS daily_total, -- ton/hr → ton
COUNT(*) AS data_points,
ROUND(COUNT(*) / 1440.0 * 100, 1) AS data_rate_pct -- 데이터 충족률
FROM history_table
WHERE tagname IN ('ficq-6101.pv', 'ficq-6113.pv', ...) -- 생산 태그 목록
AND recorded_at >= '2026-05-01+09'
AND recorded_at < '2026-06-01+09'
GROUP BY day, tagname
ORDER BY day, tagname;
공정 조건 일별 통계
SELECT
recorded_at::date AS day,
tagname,
AVG(value::double precision) AS avg_val,
MAX(value::double precision) AS max_val,
MIN(value::double precision) AS min_val,
STDDEV(value::double precision) AS stddev_val
FROM history_table
WHERE tagname IN ('ti-6111a.pv', 'ti-6211a.pv', ...) -- 대표 온도/압력 태그
AND recorded_at >= '2026-05-01+09'
AND recorded_at < '2026-06-01+09'
GROUP BY day, tagname
ORDER BY day, tagname;
조업시간 계산 (일별 가동분 집계)
-- 특정 태그(기준 태그)의 값이 0 초과인 분의 수 = 가동 분
SELECT
recorded_at::date AS day,
COUNT(*) FILTER (
WHERE value::double precision > 0
) AS running_minutes,
COUNT(*) AS total_minutes,
ROUND(
COUNT(*) FILTER (WHERE value::double precision > 0)
/ COUNT(*)::numeric * 100, 1
) AS availability_pct
FROM history_table
WHERE tagname = 'ficq-6101.pv' -- 가동 판정 기준 태그
AND recorded_at >= '2026-05-01+09'
AND recorded_at < '2026-06-01+09'
GROUP BY day
ORDER BY day;
월별 집계 (연간 레포트용)
SELECT
DATE_TRUNC('month', recorded_at AT TIME ZONE 'Asia/Seoul') AS month,
tagname,
SUM(value::double precision / 60.0) AS monthly_total,
AVG(value::double precision) AS avg_val
FROM history_table
WHERE tagname IN ('ficq-6101.pv', ...)
AND recorded_at >= '2026-01-01+09'
AND recorded_at < '2027-01-01+09'
GROUP BY month, tagname
ORDER BY month, tagname;
구현 구성요소
Backend (C# ASP.NET Core)
새 인터페이스 추가 (IExperionServices.cs)
// 레포트 서비스 인터페이스
public interface IProductionReportService
{
Task<DailyReportResult> GetDailyReportAsync(DateOnly date, ReportConfig config);
Task<MonthlyReportResult> GetMonthlyReportAsync(int year, int month, ReportConfig config);
Task<AnnualReportResult> GetAnnualReportAsync(int year, ReportConfig config);
}
// 레포트 설정 (사용자 정의 태그 목록)
public record ReportConfig(
List<string> ProductionTags, // 생산량 적산 태그
List<string> ConditionTags, // 공정 조건 태그 (온도/압력/레벨)
string AvailabilityTag, // 가동 판정 기준 태그
string FlowUnit, // 유량 단위 (ton/hr, Nm³/hr 등)
double FlowConvFactor // 단위 환산 계수 (예: 1/60 for ton/hr → ton/min)
);
// 결과 레코드
public record DailyProductionRow(string TagName, double DailyTotal, int DataPoints, double DataRatePct);
public record ConditionStatRow(string TagName, double Avg, double Max, double Min, double Stddev);
public record DailyReportResult(
DateOnly Date,
List<DailyProductionRow> Production,
List<ConditionStatRow> Conditions,
int RunningMinutes, int TotalMinutes, double AvailabilityPct
);
// Monthly/Annual 유사 구조
새 컨트롤러 (ExperionControllers.cs)
GET /api/report/daily?date=2026-05-01
GET /api/report/monthly?year=2026&month=5
GET /api/report/annual?year=2026
GET /api/report/config ← 현재 레포트 설정 조회
POST /api/report/config ← 레포트 설정 저장 (태그 목록 등)
레포트 설정 저장
report_config.json 파일로 서버 디렉토리에 저장 (appsettings 또는 별도 JSON).
Frontend (HTML/JS)
새 탭 추가 (index.html)
사이드바에 09 생산레포트 탭 추가, #pane-report 섹션.
UI 구성
┌─────────────────────────────────────────────┐
│ [일일] [월간] [연간] ← 레포트 유형 선택 │
│ 날짜/월/년 선택기 │
│ [조회] [Excel 다운로드] [PDF 인쇄] │
├─────────────────────────────────────────────┤
│ │
│ 레포트 본문 렌더링 영역 │
│ (HTML 테이블 기반, 인쇄 스타일 적용) │
│ │
└─────────────────────────────────────────────┘
JS 함수 목록
rptLoadDaily(date) // 일일 레포트 로드
rptLoadMonthly(y, m) // 월간 레포트 로드
rptLoadAnnual(y) // 연간 레포트 로드
rptRender(data, type) // 레포트 HTML 렌더링
rptExportExcel() // SheetJS로 Excel 출력 (기존 t2sExportExcel 패턴 재사용)
rptPrint() // window.print() — 인쇄/PDF 저장
rptSaveConfig(config) // 태그 설정 저장
레포트 설정 화면 (태그 관리)
레포트 생성 전에 어떤 태그가 무슨 의미인지 등록해야 한다.
생산량 태그 등록:
태그명 설명 단위 환산계수
ficq-6101.pv 6호기 원료 유량 ton/hr 0.01667
ficq-6113.pv 6호기 제품 유량 ton/hr 0.01667
...
공정 조건 태그 등록:
태그명 설명 단위
ti-6111a.pv 6호기 반응온도 ℃
pi-6101.pv 6호기 반응압력 kPa
li-6111.pv 6호기 레벨 %
...
가동 판정 기준 태그: ficq-6101.pv (값 > [0] 이면 운전)
이 설정을 report_config.json으로 저장하고 API에서 읽어 SQL을 동적 생성.
수정/추가 파일 목록
| 파일 | 작업 |
|---|---|
src/Core/Application/Interfaces/IExperionServices.cs |
IProductionReportService, ReportConfig, 결과 record 추가 |
src/Infrastructure/Database/ExperionDbContext.cs |
ProductionReportService 구현 (일별/월별/연간 SQL) |
src/Web/Controllers/ExperionControllers.cs |
ProductionReportController 추가 (5개 엔드포인트) |
src/Web/Program.cs |
ProductionReportService DI 등록 |
src/Web/wwwroot/index.html |
09 생산레포트 탭 + #pane-report 섹션 추가 |
src/Web/wwwroot/js/app.js |
rptLoad*, rptRender, rptExportExcel, rptPrint 구현 |
src/Web/wwwroot/css/style.css |
레포트 전용 스타일 + @media print 인쇄 스타일 |
src/Web/report_config.json |
생산 태그 설정 파일 (신규) |
서버 코드(Python MCP) 변경 없음.
구현 순서 권장
1단계 (필수 선행): 사용자가 생산 태그 목록 및 단위 확정
↓
2단계: report_config.json 스키마 설계 + ReportConfig record
↓
3단계: DB 쿼리 레이어 (ProductionReportService) — 일별 집계부터
↓
4단계: API 엔드포인트 (컨트롤러)
↓
5단계: 프론트엔드 UI + 테이블 렌더링
↓
6단계: Excel export + 인쇄 스타일
↓
7단계: 월간 → 연간으로 확장
주의 사항
- KST 기준 집계:
recorded_at은 UTC 저장이므로 일별 집계 시AT TIME ZONE 'Asia/Seoul'또는+ INTERVAL '9 hours'적용 필수. 그렇지 않으면 UTC 기준으로 집계되어 날짜가 달라짐. - 유량 적산 단위:
ficq-*.pv태그가ton/hr단위이면 1분 적산 시× (1/60). 단위 확인 필수. - 결측 데이터 처리: 데이터 충족률(
data_rate_pct)이 낮은 날은 레포트에*표시 권장. - 과거 데이터 부재: 현재 history_table은 2026-04-22부터만 존재. 5월 데이터는 5월 이후 수집 시 자동 반영됨.
- TimescaleDB 활용:
time_bucket()또는DATE_TRUNC()로 일별/월별 집계 —time_bucket_gapfill()로 결측 구간 0 채움 가능.