Files
ExperionCrawler/dxf-graph/monthly-report-plan.md
windpacer 7330711499 chore: 프로젝트 파일 구조 정리 - 루트 파일 폴더별 이동, 테스트/구버전 삭제
루트 파일 정리:
- DXF/P&ID 관련 → dxf-graph/
- fastTable 관련 → fastTable/
- plan/ → plans/ 통합 (최신 버전 유지)
- 테스트 출력 파일, 구버전 프로젝트 삭제
- 불필요한 루트 문서 삭제
2026-05-10 17:39:58 +09:00

14 KiB
Raw Blame History

일일/월간/연간 생산 레포트 구현 계획

현황 파악

항목 내용
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 채움 가능.