세티스 readme 초안
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
# saman-statis (사내 ERP 그룹웨어 통계 시스템)
|
||||
|
||||
본 프로젝트는 사내 ERP 내에서 사용되는 통계 및 데이터 시각화 기능을 제공하는 내부 시스템입니다. PHP와 Smarty 템플릿 엔진을 기반으로 구축되었으며, 프론트엔드는 JavaScript, CSS, W2UI Grid, JqGrid 등을 활용하여 구성되어 있습니다.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 기술 스택 (Tech Stack)
|
||||
|
||||
* **DB:** Oracle 11g
|
||||
* **Backend:** PHP 5.2.12
|
||||
* **Template Engine:** Smarty
|
||||
* **Frontend:** JavaScript, HTML5, CSS3,
|
||||
* **Web Server:** Apache
|
||||
|
||||
---
|
||||
|
||||
## 📂 디렉토리 구조 (Directory Structure)
|
||||
|
||||
```text
|
||||
├── Satis/ # 핵심 로직 및 모듈 폴더(Controller, model)
|
||||
├── Smarty/ # Smarty 템플릿 파일 (.tpl) 및 컴파일 폴더
|
||||
├── SmartyConfig.php # Smarty 엔진 설정 및 초기화 파일
|
||||
├── index.php # 시스템 메인 진입점 (Entry Point)
|
||||
├── index_org.php # 백업 또는 원본 인덱스 파일
|
||||
└── phpinfo.php # 서버 환경 확인용 스크립트 (운영 환경에서는 삭제 권장)
|
||||
@@ -0,0 +1,172 @@
|
||||
# (주)삼안 ERP 및 그룹웨어 시스템 (Satis) 하이레벨 아키텍처 (High-Level Architecture)
|
||||
|
||||
본 문서는 (주)삼안의 **ERP 및 그룹웨어 시스템(`saman-statis` / `Satis`)** 프로젝트의 전체 하이레벨 아키텍처(HLA) 명세서입니다.
|
||||
시스템의 전체 개요, 계층형 구조, 기술 스택, 업무 도메인뿐만 아니라 **인프라/배포 아키텍처, 보안/인증 아키텍처, 외부 시스템 연동 구조**를 종합적으로 포함합니다.
|
||||
*(참고: 압축파일 `*.zip`은 분석에서 제외하였습니다.)*
|
||||
|
||||
---
|
||||
|
||||
## 1. 프로젝트 개요 (Project Overview)
|
||||
|
||||
* **프로젝트명**: 삼안 ERP / 그룹웨어 (`saman-statis` / `Satis`)
|
||||
* **운영 도메인**: `satis2.samaneng.com`, `erp.samaneng.com`
|
||||
* **시스템 성격**: 엔지니어링/건설 분야 기업 자원 관리(ERP) 및 통합 그룹웨어
|
||||
* **주요 기능**: 인사/급여, 회계/전표, 프로젝트/현장 공정, 영업/기성, 전자결재, 고정자산, 출장 정산, 경영분석 등
|
||||
|
||||
---
|
||||
|
||||
## 2. 하이레벨 시스템 아키텍처 (High-Level System Architecture)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Client Tier
|
||||
Browser["Web Browser <br/> (HTML5, jQuery, jqGrid, w2ui)"]
|
||||
end
|
||||
|
||||
subgraph Web / Presentation Tier
|
||||
WebServer["Web Server <br/> (Windows Server / APM_Setup)"]
|
||||
Smarty["Smarty Template Engine v2.6 <br/> (Smarty/templates/Satis/*.tpl)"]
|
||||
end
|
||||
|
||||
subgraph Application Tier
|
||||
Controller["MVC Controllers <br/> (Satis/sys/controller/*)"]
|
||||
AuthModule["Security & Auth Engine <br/> (AuthClass.php / Session)"]
|
||||
BizLogic["Business Models & Utility <br/> (Satis/sys/model/*, OracleClass.php)"]
|
||||
end
|
||||
|
||||
subgraph Data & Integration Tier
|
||||
OracleDB[("Main Oracle Database <br/> (OCI Connection)")]
|
||||
iCubeDB[("Douzone iCube ERP <br/> (MS-SQL: DZICUBE)")]
|
||||
IntranetDB[("Intranet Database <br/> (MySQL: hallaerp)")]
|
||||
end
|
||||
|
||||
Browser <-->|HTTPS / HTTP| WebServer
|
||||
WebServer <--> Smarty
|
||||
WebServer <--> Controller
|
||||
Controller <--> AuthModule
|
||||
Controller <--> BizLogic
|
||||
BizLogic <-->|OCI Connection| OracleDB
|
||||
BizLogic <-->|MS-SQL Driver| iCubeDB
|
||||
BizLogic <-->|MySQL Driver| IntranetDB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 계층별 기술 스택 (Layered Tech Stack)
|
||||
|
||||
| 계층 (Layer) | 구성 기술 및 디렉토리 | 설명 |
|
||||
| :--- | :--- | :--- |
|
||||
| **Presentation Tier** | `Smarty 2.6`, `Smarty/templates/Satis/` | Server-Side Rendering (SSR) 뷰 템플릿 엔진 (`.tpl`) |
|
||||
| **Client UI Tier** | `jQuery`, `jqGrid`, `w2ui`, `Satis/js/` | 엔지니어링/회계 대용량 동적 그리드 및 사용자 인터랙션 처리 |
|
||||
| **Application Tier** | `PHP 5.x`, `Satis/sys/controller/` | Custom MVC Controller (`ActionMode` 라우팅 파라미터 처리) |
|
||||
| **Security Tier** | `Satis/sys/util/AuthClass.php` | 세션 보안, CSRF Anti-Forgery Token 검증, 접근 권한 통제 |
|
||||
| **Persistence Tier** | `OracleClass.php`, `Satis/inc/*.inc` | Oracle OCI, MS-SQL(iCube), MySQL 다중 DB 연결 지원 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 인프라 및 배포 아키텍처 (Infrastructure & Deployment Architecture)
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Infrastructure Layout
|
||||
WebSvr["Web Application Server <br/> (APM_Setup / Windows Server)"]
|
||||
OracleSvr[("Oracle Database Server <br/> (Main ERP Data)")]
|
||||
iCubeSvr[("Douzone iCube Server <br/> (MS-SQL 192.168.13.50:5539)")]
|
||||
MySQLSvr[("Intranet MySQL Server <br/> (erp.samaneng.com / hallaerp)")]
|
||||
end
|
||||
|
||||
WebSvr -->|OCI Client| OracleSvr
|
||||
WebSvr -->|MS-SQL TCP 5539| iCubeSvr
|
||||
WebSvr -->|MySQL TCP 3306| MySQLSvr
|
||||
```
|
||||
|
||||
* **서버 환경**: Windows Server 기반 APM (Apache + PHP + MySQL) 단일/이중화 실행 환경 (`D:/APM_Setup/htdocs/`)
|
||||
* **PHP 실행 옵션**:
|
||||
* 메모리 제한 해제 (`ini_set("memory_limit", -1)`)를 통한 대용량 프로젝트/연말정산 엑셀 보고서 생성 지원
|
||||
* 캐시 무효화 헤더 설정 (`Expires: 0`, `Cache-Control: no-cache`)을 통한 세션 및 보안 강화
|
||||
* **경로 및 컴파일 구조**:
|
||||
* Smarty 템플릿 컴파일 경로: `D:/APM_Setup/htdocs/Smarty/templates_c`
|
||||
* 템플릿 설정 경로: `SmartyConfig.php` 관리
|
||||
|
||||
---
|
||||
|
||||
## 5. 보안 및 인증 아키텍처 (Security & Authentication Architecture)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor User as 사용자
|
||||
participant Controller as Login Controller
|
||||
participant Auth as AuthClass
|
||||
participant Session as PHP Session
|
||||
participant DB as Oracle DB
|
||||
|
||||
User->>Controller: 로그인 요청 (ID / Password)
|
||||
Controller->>DB: 사용자 정보 및 권한 검증
|
||||
DB-->>Controller: 인증 성공 반환
|
||||
Controller->>Auth: Auth_TokenGenerater() 호출
|
||||
Auth->>Session: Session ID & Token 생성/저장
|
||||
Session-->>User: Session Cookie 발급 (private)
|
||||
|
||||
Note over User, Controller: 후속 요청 시 Token 및 Session 권한 검증 (Auth_TokenChecker)
|
||||
```
|
||||
|
||||
1. **세션 및 인증 관리 (Session Management)**
|
||||
* PHP 세션 생성 (`session_start()`, `session_cache_limiter('private')`)
|
||||
* 사용자 식별자 관리: `$_SESSION['satis_user_id']`, `$_SESSION['satis_user_deptcode']`, `$_SESSION['satis_user_name']`
|
||||
2. **CSRF 방어 및 난수 토큰 (Token Security)**
|
||||
* `AuthClass.php` 내 10자리 영문/숫자 난수 토큰 생성기 (`Auth_TokenGenerater`) 및 검증기 (`Auth_TokenChecker`) 탑재
|
||||
* 비인가 접근 시 자동 세션 파기 (`session_destroy()`) 및 로그인 페이지 전환 (`auth_move_page.tpl`)
|
||||
3. **역할 기반 권한 통제 (RBAC / Role-Based Access Control)**
|
||||
* `AuthClass` 및 `GetUserInfo.php`를 통해 사용자 직급/부서/권한 등급별 메뉴 접근 권한 세분화
|
||||
|
||||
---
|
||||
|
||||
## 6. 외부 시스템 연동 아키텍처 (External System Integration Architecture)
|
||||
|
||||
이 시스템은 단일 DB에 의존하지 않고, 사내 타 이종(Heterogeneous) 시스템과 실시간 연결되는 하이브리드 데이터 아키텍처를 가집니다.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
SatisCore["Satis ERP Core System"]
|
||||
|
||||
SatisCore <-->|OCI Native Connection| OracleSystem["메인 그룹웨어/ERP DB (Oracle)"]
|
||||
SatisCore <-->|MS-SQL Driver (Port 5539)| iCubeSystem["더존 iCube ERP (MS-SQL: DZICUBE) <br/> IP: 192.168.13.50"]
|
||||
SatisCore <-->|MySQL Driver (Port 3306)| IntranetSystem["인트라넷 시스템 (MySQL: hallaerp) <br/> Host: erp.samaneng.com"]
|
||||
```
|
||||
|
||||
1. **더존 iCube ERP 연동 (`saman_icube_dbcon.inc`)**
|
||||
* **연동 목적**: 사내 더존 회계/인사 ERP 데이터와의 실시간 동기화 및 전표 전송
|
||||
* **접속 방식**: Dedicated MS-SQL Connection (`192.168.13.50:5539`, DB명: `DZICUBE`)
|
||||
2. **사내 인트라넷 연동 (`dbcon.inc`)**
|
||||
* **연동 목적**: 인트라넷 기존 데이터 및 파일 연결
|
||||
* **접속 방식**: MySQL Connection (`erp.samaneng.com`, DB명: `hallaerp`)
|
||||
3. **메인 Oracle DB 연동 (`OracleClass.php`)**
|
||||
* **연동 목적**: Satis 그룹웨어 고유의 결재, 인사, 프로젝트, 출장, 자산 관리 데이터 처리
|
||||
* **접속 방식**: Oracle OCI8 라이브러리 및 커스텀 트랜잭션 바인딩 처리
|
||||
|
||||
---
|
||||
|
||||
## 7. 주요 업무 도메인 서브시스템 (Business Subsystems)
|
||||
|
||||
| 도메인 구분 | 서브시스템 모듈 | 아키텍처적 역할 및 주요 처리 기능 |
|
||||
| :--- | :--- | :--- |
|
||||
| **회계/재무** | `Account` | 전표 생성/승인, 예산 관리, 결산, 재무제표, 법인세/부가세, 원가 계산 |
|
||||
| **인사/급여** | `Person` | 인사기록, 근태 관리, 급여/상여 계산, 연말정산(`yeta_data`) 처리 |
|
||||
| **프로젝트/공정** | `Project`, `Project_work` | 엔지니어링 프로젝트 현장 관리, 공정률 계산, 기성 산출, 수주/매출 처리 |
|
||||
| **전자결재/문서** | `Document`, `Sign` | 전자결재 작성, 양식/결재선 관리, 전자서명 및 인장 관리 |
|
||||
| **영업/구매** | `Sale`, `Purchase` | 수주/매출 관리, 자재 구매 신청 및 발주 처리 |
|
||||
| **자산/도서/출장** | `Asset`, `Book`, `Travel` | 고정자산 추적, 도서 대여 관리, 국내/외 출장 신청 및 여비 정산 |
|
||||
| **시스템 관리** | `Supervisor`, `Common` | 전체 공정/부서/직급 코드 관리 (`CommonCodeList.php`), 관리자 권한 설정 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 아키텍처 총평 및 고려사항 (Architectural Evaluation)
|
||||
|
||||
1. **강점 (Strengths)**:
|
||||
* **명확한 모듈화**: 업무 도메인별 Controller, Model, View가 체계적으로 분리되어 있어 대규모 ERP 시스템의 확장성이 확보되어 있습니다.
|
||||
* **이종 DB 유연성**: Oracle, MS-SQL(더존 iCube), MySQL을 동시에 연동하는 하이브리드 데이터 아키텍처를 안정적으로 운영합니다.
|
||||
* **대용량 그리드 최적화**: `jqGrid` 라이브러리와 메모리 해제 조치(`ini_set`)를 통해 수만 건 이상의 공정/회계 데이터 조회를 지원합니다.
|
||||
2. **향후 아키텍처 개선 제언 (Future Roadmap)**:
|
||||
* **PHP 버전을 현대화**: Classic PHP 드라이버(`mssql_*`, `mysql_*`)를 최신 `PDO` 또는 `sqlsrv`/`mysqli`로 마이그레이션 권장.
|
||||
* **하드코딩된 DB 접속 정보 격리**: `saman_icube_dbcon.inc` 등의 DB 계정 정보를 `.env` 또는 보안 설정 파일로 분리 관리 권장.
|
||||
@@ -0,0 +1,614 @@
|
||||
# (주)삼안 ERP 및 그룹웨어 시스템 (Satis) 초상세 로우레벨 분석 명세서 v2
|
||||
|
||||
본 문서는 (주)삼안의 **ERP 및 그룹웨어 시스템 (`saman-statis` / `Satis`)**의 실제 소스 코드를 직접 분석한
|
||||
**초상세 로우레벨(Ultra-Detailed Low-Level) 구현 명세서**입니다.
|
||||
`OracleClass.php` 전체 메소드 명세, 전자결재 알고리즘, 문서번호 채번 방식, 인코딩 파이프라인, 결재 서명 렌더링,
|
||||
시스템 글로벌 변수, DB 데이터 모델, 보안 핸들링 등을 실제 소스 코드 기반으로 완전히 명세합니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 모듈별 컨트롤러 & 뷰 맵핑 딕셔너리 (Module Controller-View Map)
|
||||
|
||||
### 1.1 회계 관리 모듈 (`Account`) — 30개 컨트롤러
|
||||
| 컨트롤러 (`Satis/sys/controller/Account/`) | 대응 View (`Smarty/templates/Satis/Account/`) | 주요 기능 |
|
||||
| :--- | :--- | :--- |
|
||||
| `AccountSlipTemp_Controller.php` | `AccountSlipTemp.tpl` | 임시전표 작성/조회/수정/결재 상신 |
|
||||
| `AccountSlipConfirmed_Controller.php` | `AccountSlipConfirmed.tpl` | 확정전표 조회 및 결재 상태 확인 |
|
||||
| `AccountSlipAutoManager_Controller.php` | `AccountSlipAutoManager.tpl` | 더존 iCube ERP 자동전표 전송 |
|
||||
| `AccountBalanceStatement_Controller.php` | `AccountBalanceStatement.tpl` | 합계잔액시산표 생성 |
|
||||
| `AccountFinancialStatement_Controller.php` | `AccountFinancialStatement.tpl` | 손익계산서(P/L) / 대차대조표(B/S) |
|
||||
| `AccountGisungCalculation_Controller.php` | `AccountGisungCalculation.tpl` | 프로젝트 기성 청구금액 산출 |
|
||||
| `AccountJointOfficeBudgetManager_Controller.php` | `AccountJointOfficeBudget.tpl` | 공동도급(JV) 예산/지분율 원가 관리 |
|
||||
| `AccountFixAsset_Controller.php` | `AccountFixAsset.tpl` | 고정자산 감가상각비/대장 관리 |
|
||||
| `AccountCorporateTax_Controller.php` | `AccountCorporateTax.tpl` | 법인세 계산 및 세무 조정 |
|
||||
| `AccountWithHoldingTax_Controller.php` | `AccountWithHoldingTax.tpl` | 원천세 신고 / 원천징수 영수증 |
|
||||
| `AccountVAT_Controller.php` | `AccountVAT.tpl` | 부가가치세 신고 데이터 집계 |
|
||||
| `AccountCostCalculation_Controller.php` | `AccountCostCalculation.tpl` | 원가 계산 및 분석 |
|
||||
| `AccountCostManagement_Controller.php` | `AccountCostManagement.tpl` | 원가 관리 현황 |
|
||||
| `AccountFundPlan_Controller.php` | `AccountFundPlan.tpl` | 자금 계획 관리 |
|
||||
| `AccountDepositsManager_Controller.php` | `AccountDepositsManager.tpl` | 예금/차입금 관리 |
|
||||
| `AccountLoanManager_Controller.php` | `AccountLoanManager.tpl` | 대출 관리 |
|
||||
| `AccountSecurities_Controller.php` | `AccountSecurities.tpl` | 유가증권 관리 |
|
||||
| `AccountEntertainmentExpenses_Controller.php` | `AccountEntertainmentExpenses.tpl` | 접대비 관리 |
|
||||
| `AccountCarManager_Controller.php` | `AccountCarManager.tpl` | 차량 운행/유지비 관리 |
|
||||
| `AccountDailyWorkTask_Controller.php` | `AccountDailyWorkTask.tpl` | 일일 업무 실적 처리 |
|
||||
| `AccountSummary_Controller.php` | `AccountSummary.tpl` | 회계 요약 현황 |
|
||||
| `AccountSummaryReport_Controller.php` | `AccountSummaryReport.tpl` | 회계 종합 보고서 |
|
||||
| `AccountDeadlineManager_Controller.php` | `AccountDeadlineManager.tpl` | 결산 기한 관리 |
|
||||
| `AccountMonthSupplementary_Controller.php` | `AccountMonthSupplementary.tpl` | 월별 추가 분개 관리 |
|
||||
| `AccountBillCheckManager_Controller.php` | `AccountBillCheckManager.tpl` | 어음/수표 관리 |
|
||||
| `AccountFinaCode_Controller.php` | `AccountFinaCode.tpl` | 재무 코드 관리 |
|
||||
| `AccountFundCode_Controller.php` | `AccountFundCode.tpl` | 자금 코드 관리 |
|
||||
| `AccountAssetCode_Controller.php` | `AccountAssetCode.tpl` | 자산 코드 관리 |
|
||||
| `FinalClosing_Controller.php` | `FinalClosing.tpl` | 결산 확정 처리 |
|
||||
| `AccountGisungCalculation_Controller.php` | `AccountGisungCalculation.tpl` | 기성 계산 처리 |
|
||||
|
||||
### 1.2 인사/급여 관리 모듈 (`Person`) — 23개 컨트롤러
|
||||
| 컨트롤러 (`Satis/sys/controller/Person/`) | 대응 View (`Smarty/templates/Satis/Person/`) | 주요 기능 |
|
||||
| :--- | :--- | :--- |
|
||||
| `PersonInfoManager_Controller.php` | `PersonInfoManager.tpl` | 인사기록 카드, 신상정보, 이력 관리 |
|
||||
| `PersonAppointment_Controller.php` | `PersonAppointment.tpl` | 발령 처리 (입사/퇴사/이동/승진/전보) |
|
||||
| `PersonInsaLicense_Controller.php` | `PersonInsaLicense.tpl` | 엔지니어링 기술자 자격증 관리 |
|
||||
| `PersonCode_Controller.php` | `PersonCode.tpl` | 인사 코드 마스터 관리 |
|
||||
| `PersonTime_Controller.php` | `PersonTime.tpl` | 근태 관리 (연차/야근/출퇴근) |
|
||||
| `PersonPayBase_Controller.php` | `PersonPayBase.tpl` | 급여 기준 정보 설정 |
|
||||
| `PersonPayBasic_Controller.php` | `PersonPayBasic.tpl` | 기본급/수당 항목 설정 |
|
||||
| `PersonPaymentCalculation_Controller.php` | `PersonPaymentCalculation.tpl` | 월 급여/상여 계산 엔진 |
|
||||
| `PersonPaymentReport_Controller.php` | `PersonPaymentReport.tpl` | 급여명세서 / 부서별 지급 총괄 |
|
||||
| `PersonSlipPaymentManager_Controller.php` | `PersonSlipPaymentManager.tpl` | 급여 전표 연동 처리 |
|
||||
| `PersonRetirementPay_Controller.php` | `PersonRetirementPay.tpl` | 퇴직금 계산 및 충당금 정산 |
|
||||
| `PersonYearEndTax_Controller.php` | `PersonYearEndTax.tpl` | 연말정산 (`yeta_data` 연동) |
|
||||
| `PersonInsaReport_Controller.php` | `PersonInsaReport.tpl` | 인사 현황 보고서 |
|
||||
| `PersonInsaStatusReport_Controller.php` | `PersonInsaStatusReport.tpl` | 인사 상태 보고서 |
|
||||
| `PersonOrganiz_Controller.php` | `PersonOrganiz.tpl` | 조직도 관리 |
|
||||
| `Duzon_link_controller.php` | `Duzon_link.tpl` | 더존 인사/급여 ERP 데이터 싱크 |
|
||||
| `auth_pay_controller.php` | `auth_pay.tpl` | 급여 지급 권한 처리 |
|
||||
| `emp_check_controller.php` | `emp_check.tpl` | 재직 여부 확인 |
|
||||
|
||||
### 1.3 프로젝트/현장 공정 모듈 (`Project`) — 15개 컨트롤러
|
||||
| 컨트롤러 (`Satis/sys/controller/Project/`) | 대응 View (`Smarty/templates/Satis/Project/`) | 주요 기능 |
|
||||
| :--- | :--- | :--- |
|
||||
| `Project_Controller.php` | `Project.tpl` | 프로젝트 마스터 등록/관리 |
|
||||
| `ProjectOrderContract_Controller.php` | `ProjectOrderContract.tpl` | 수주 계약, 변경 계약, 공동도급 지분율 |
|
||||
| `ProjectOrderGisung_Controller.php` | `ProjectOrderGisung.tpl` | 기성 청구 / 수금 / 미수금 |
|
||||
| `ProjectMenHour_Controller.php` | `ProjectMenHour.tpl` | M/M 공수 집계 및 원가 배부 |
|
||||
| `ProjectCostStatus_Controller.php` | `ProjectCostStatus.tpl` | 투입 원가(인건비/직접비/경비) 현황 |
|
||||
| `ProjectCostTotal_Controller.php` | `ProjectCostTotal.tpl` | 원가 합계 현황 |
|
||||
| `ProjectPrePayment_Controller.php` | `ProjectPrePayment.tpl` | 선급금 신청/수금/정산 |
|
||||
| `ProjectStatus_Controller.php` | `ProjectStatus.tpl` | 프로젝트 진행 현황 |
|
||||
| `ProjectBaseCode_Controller.php` | `ProjectBaseCode.tpl` | 프로젝트 기본 코드 관리 |
|
||||
| `ProjectPartner_Controller.php` | `ProjectPartner.tpl` | 협력업체 관리 |
|
||||
| `DeptAssessment_Controller.php` | `DeptAssessment.tpl` | 부서 평가 관리 |
|
||||
| `TargetManagement_Controller.php` | `TargetManagement.tpl` | 수주 목표 관리 |
|
||||
| `PrinterCopy_Controller.php` | `PrinterCopy.tpl` | 인쇄 출력 처리 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 핵심 클래스 전체 메소드 명세 (OracleClass.php — 1,392라인)
|
||||
|
||||
`Satis/sys/util/OracleClass.php`는 시스템 전체 Oracle DB 연동의 핵심 클래스입니다.
|
||||
실제 소스 분석 기반의 **전체 메소드 분류표**입니다.
|
||||
|
||||
### 2.1 DB 커넥션 및 기본 쿼리 메소드
|
||||
|
||||
| 메소드명 | 설명 |
|
||||
| :--- | :--- |
|
||||
| `OracleClass($smarty)` | 생성자. OCI 커넥션 생성. `oci_connect('satis', 'SATIS11707808', 'samandb')` |
|
||||
| `db_close_oracle()` | 커넥션 명시적 해제. `oci_close()` |
|
||||
| `Query($i_azsql)` | SQL 파싱 및 실행 후 Statement 핸들 반환. |
|
||||
| `fetch_array($stmt)` | `oci_fetch_array($stmt, OCI_BOTH)` — 연관+인덱스 배열 동시 반환 |
|
||||
| `ExcuteQuery($i_azsql)` | DML 단순 실행 (반환값 없음) |
|
||||
| `LoadSql($i_azsql)` | 레거시 `ociparse/ociexecute/ocifetchinto` API 기반 단일 컬럼 조회 |
|
||||
| `LoadConfigData($i_azsql)` | 설정 데이터를 `name=value` 포맷으로 직접 `echo` 출력 |
|
||||
| `__destruct()` | PHP 소멸자: Statement 자동 해제 + 커넥션 자동 close |
|
||||
|
||||
### 2.2 Stored Procedure (저장 프로시저) 조회 메소드
|
||||
|
||||
| 메소드명 | 인자 | 반환 방식 | 특이사항 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `LoadProcedure($sql, $title, $short_array)` | SQL, Smarty 변수명 | `$query_data` 배열 + Smarty assign | 기본 프로시저 호출 메소드 |
|
||||
| `LoadProcedure_old($sql, $title, $short_array)` | SQL, Smarty 변수명 | `$query_data` 배열 | `$_short` 축약형 컬럼 지원 (구버전) |
|
||||
| `LoadProcedure_new($sql, $title, $short_array, $return_type)` | SQL, 변수명, 반환 타입 | `array` / `json` / `jsonchart` / `print_r` / Smarty | 출력 타입 지정 가능 |
|
||||
| `LoadProcedure_new2($sql, $title, $short_array, $return_type)` | SQL, 변수명, 반환 타입 | 단일 Row 전용 | 단건 조회용 최적화 |
|
||||
| `LoadProcedure_empty($sql, $title, $load_type, $return_type)` | SQL, 변수명, 로드타입 | `$query_data` 배열 | `w2ui` 모드 시 `recid` 자동 부여 |
|
||||
| `LoadProcedure_broken_cp949($sql, $title, $load_type, $return_type)` | SQL, 변수명, 로드타입 | `$query_data` 배열 | CP949 인코딩 깨짐 데이터 처리용 |
|
||||
| `LoadProcedureAjax($sql)` | SQL | `print_r(urldecode(json_encode($data)))` | Ajax 요청 전용 JSON 직접 출력 |
|
||||
| `LoadProcedureApi($sql, $output_type)` | SQL, 출력 타입 | `array` / `json` / `jsonchart` | API/외부 호출 전용 |
|
||||
| `Get_ProcedureData($Param01~05)` | 최대 5개 파라미터 | `array` | `usp_get_procedure_data` 프로시저 공통 호출 래퍼 |
|
||||
| `executeSelect($sql)` | SQL | 구조화된 결과 객체 (`success`, `rows`, `columns`, `error`) | 최신 트랜잭션 안전 조회 함수 (2025-07-25 추가) |
|
||||
|
||||
### 2.3 DML 실행 메소드 (INSERT / UPDATE / DELETE)
|
||||
|
||||
| 메소드명 | 설명 | 에러 반환 방식 |
|
||||
| :--- | :--- | :--- |
|
||||
| `ProcedureExcuteQuery($sql)` | 프로시저 DML 실행, 에러 시 `echo` | `echo '-----'.$err['message']` |
|
||||
| `ProcedureExcuteQuery_new($sql, $encode_type, $return_type)` | 인코딩 선택(`utf8`/`euckr`) 후 DML 실행 | echo 출력 |
|
||||
| `ProcedureExcuteQuery_boolean($sql)` | DML 실행 후 `true`/`false` 반환 | boolean |
|
||||
| `ProcedureExcuteQuery_boolean2($sql)` | DML 실행 후 `result`/`error` 구조체 반환 | 배열 구조체 |
|
||||
| `ProcedureExcuteQuery_ErrorCheck($sql, $memberId, $date, $returnYN, $encode_type, $output_msg)` | 프로시저 실행 후 `Common_Confirm_Error` 프로시저로 이중 에러 검증 | `echo` 또는 `return` |
|
||||
| `ProcedureExcuteQuery_Return($sql, $ReturnContent)` | DML 후 `RESULT_CODE` / `RESULT_MSG` / `ALL` 선택 반환 | 문자열 또는 배열 |
|
||||
| `ProcedureExcuteQuery_ExcReturn($sql, $ReturnContent)` | 최신 try-catch 기반 DML. Oracle 에러코드 한국어 메시지 매핑 | JSON 또는 한국어 에러 문자열 |
|
||||
| `executeDml($sql)` | 트랜잭션 안전 DML 실행 (2025-07-25 신규 추가) | 구조화된 결과 객체 |
|
||||
| `ProcedureExcuteQuery_ErrorPrint($sql, $encode_type, $return_type)` | 에러 발생 시 콘솔 출력 | `echo` |
|
||||
|
||||
### 2.4 Oracle 에러코드 → 한국어 메시지 매핑 테이블
|
||||
|
||||
`ProcedureExcuteQuery_ExcReturn()` 내부의 `$ErrorKind_Array`로 Oracle ORA- 에러 코드를 사용자 친화적 한국어 메시지로 변환합니다.
|
||||
|
||||
```php
|
||||
$ErrorKind_Array = [
|
||||
"-1" => "존재하는 내용입니다. 확인 후 입력해 주세요.", // ORA-00001: DUP_VAL_ON_INDEX
|
||||
"-1400" => "빈값을 입력 할 수 없습니다.", // NOT NULL 위반
|
||||
"-1722" => "숫자자리에 문자를 입력할 수 없습니다.", // INVALID_NUMBER
|
||||
"-1407" => "빈값을 입력 할 수 없습니다.", // NOT NULL 위반 (다른 컬럼)
|
||||
"-1438" => "숫자값이 너무 커서 입력할 수 없습니다.", // 숫자 정밀도 초과
|
||||
"-12899" => "글자가 너무 길어 입력할 수 없습니다.", // VARCHAR2 길이 초과
|
||||
"-6550" => "필수항목이 입력되지 않았습니다.", // PL/SQL 컴파일 에러
|
||||
"-6511" => "(CURSOR_ALREADY_OPEN) : 커서가 이미 OPEN 상태",
|
||||
"-6502" => "(VALUE_ERROR) : 수치 또는 값 오류",
|
||||
"-1476" => "(ZERO_DIVIDE) : 0으로 나눌때",
|
||||
"-1017" => "(LOGIN_DENIED) : 잘못된 사용자 이름이나 비밀번호로 로그인 시도",
|
||||
"-1422" => "(TOO_MANY_ROWS) : SELECT INTO 결과가 두 건 이상",
|
||||
];
|
||||
```
|
||||
|
||||
### 2.5 문자 인코딩 변환 메소드 (CP949 ↔ UTF-8 파이프라인)
|
||||
|
||||
Oracle DB는 `CP949 (EUC-KR)` 인코딩을 사용하고, 웹 화면은 `UTF-8`로 구성되어 있어 양방향 변환이 필수입니다.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
DB["Oracle DB (CP949/EUC-KR)"]
|
||||
PHP["PHP Application (UTF-8)"]
|
||||
Browser["Web Browser (UTF-8)"]
|
||||
|
||||
DB -->|HangleEncode: ICONV cp949→UTF-8| PHP
|
||||
PHP -->|HangleEncodeUTF8_EUCKR: ICONV UTF-8→cp949| DB
|
||||
PHP -->|HangleEncodeAjax: cp949→UTF-8 Ajax 전용| Browser
|
||||
```
|
||||
|
||||
| 메소드명 | 변환 방향 | 비고 |
|
||||
| :--- | :--- | :--- |
|
||||
| `HangleEncode($item)` | `CP949 → UTF-8` | 공백은 ` `로 대체 |
|
||||
| `HangleEncode_empty($item)` | `CP949 → UTF-8` | 공백 대체 없음 |
|
||||
| `HangleEncodeAjax($item)` | `CP949 → UTF-8` | Ajax 응답 전용 |
|
||||
| `HangleEncodeUTF8_EUCKR($item)` | `UTF-8 → CP949` | SQL 삽입 시 한글 보호 |
|
||||
| `bear3StrCut($str, $len, $tail)` | — | 멀티바이트 문자열 정규식 자르기 (`preg_match`) |
|
||||
| `resizeString($str, $size, $addStr)` | — | `mb_strlen/mb_substr` 기반 UTF-8 자르기 |
|
||||
|
||||
### 2.6 로그 기록 메소드
|
||||
|
||||
```php
|
||||
function OracleLogWrite($msg, $menu) {
|
||||
// 로그 파일 경로: Satis/sys/log/YYYY-MM-DD_{메소드명}.txt
|
||||
$cfile = "../../log/" . date("Y-m-d") . "_" . $menu . ".txt";
|
||||
|
||||
// 기존 파일 내용 읽기 → 새 내용 추가 → 파일 쓰기
|
||||
if (file_exists($cfile)) {
|
||||
$fd = fopen($cfile, 'r');
|
||||
$con = fread($fd, filesize($cfile));
|
||||
fclose($fd);
|
||||
}
|
||||
$fp = fopen($cfile, 'w');
|
||||
$cond = $con . date("Y-m-d H:i:s") . " " . $msg . "\n";
|
||||
fwrite($fp, $cond);
|
||||
fclose($fp);
|
||||
}
|
||||
```
|
||||
|
||||
> **로그 파일 명명 규칙**: `YYYY-MM-DD_{호출된메소드명}.txt`
|
||||
> 예: `2026-07-20_LoadProcedure.txt`, `2026-07-20_ExcuteQuery_new.txt`
|
||||
|
||||
### 2.7 최신 트랜잭션 안전 메소드 (2025-07-25 추가, 김병철)
|
||||
|
||||
```php
|
||||
function executeSelect($sql) {
|
||||
try {
|
||||
set_error_handler(array($this, 'custom_error_handler'));
|
||||
$stmt = oci_parse($this->connection, $this->HangleEncodeUTF8_EUCKR($sql));
|
||||
|
||||
// Ref Cursor 포함 여부 자동 감지
|
||||
if (strpos($sql, ":entries") !== false) {
|
||||
$entries = oci_new_cursor($this->connection);
|
||||
oci_bind_by_name($stmt, ":entries", $entries, -1, OCI_B_CURSOR);
|
||||
oci_execute($stmt, OCI_DEFAULT);
|
||||
oci_execute($entries);
|
||||
$fetchResult = $this->fetchResults($entries, $result);
|
||||
} else {
|
||||
oci_execute($stmt, OCI_DEFAULT);
|
||||
$fetchResult = $this->fetchResults($stmt, $result);
|
||||
}
|
||||
$result["rows"] = $fetchResult[0];
|
||||
$result["columns"] = $fetchResult[1];
|
||||
|
||||
} catch (Exception $e) {
|
||||
oci_rollback($this->connection); // 에러 시 자동 롤백
|
||||
$this->makeErrorResult($result, $stmt, $e->getMessage());
|
||||
|
||||
// Oracle 에러코드 20000 이상 = 사용자 정의 예외 → DB 에러로그 삽입
|
||||
if ($result["error"]["datas"]["oci_error_data"]["code"] >= 20000) {
|
||||
$this->insertSmErrorLog($_SESSION["satis_user_id"], $errorMessage);
|
||||
}
|
||||
}
|
||||
restore_error_handler();
|
||||
return $result;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 전자결재 엔진 알고리즘 (`Satis/inc/approval_function.php` — 1,224라인)
|
||||
|
||||
### 3.1 전자결재 상태 머신 (State Machine)
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> CREATE : 기안 문서 작성 (DOC_STATUS_CREATE)
|
||||
|
||||
CREATE --> TEMP : 임시저장 (TEMP-00001)
|
||||
CREATE --> APPROVE: 결재 상신 (PROCESS_APPROVE=1)
|
||||
TEMP --> APPROVE: 상신 실행
|
||||
|
||||
state APPROVE {
|
||||
[*] --> DEPT : 부서내결재 (부서내 / PROCESS_CODE)
|
||||
DEPT --> RECV : 부서접수 (RECEIVE)
|
||||
RECV --> SANCTION: 결의부서내 (SANCTION_CODE)
|
||||
SANCTION --> FINISH_LOOP: 처리부서내 (SANCTION_CODE2)
|
||||
}
|
||||
|
||||
APPROVE --> BACK : 이전 결재자 반송 (PROCESS_BACK="BACK")
|
||||
APPROVE --> RETURN : 부결/반송 (PROCESS_RETURN="RETURN")
|
||||
APPROVE --> FINISH : 최종 승인 (PROCESS_FINISH="FINISH")
|
||||
APPROVE --> DECISION : 전결 (PROCESS_DECISION="FINISH-DECISION")
|
||||
|
||||
BACK --> APPROVE : 재결재
|
||||
RETURN --> CREATE : 재기안
|
||||
FINISH --> [*]
|
||||
DECISION --> [*]
|
||||
```
|
||||
|
||||
### 3.2 전체 상태 상수 정의 (`approval_var.php`)
|
||||
|
||||
```php
|
||||
/* 결재 진행 상태 코드 */
|
||||
$PROCESS_APPROVE = 1; // 결재진행중
|
||||
$PROCESS_TEMPORARY = "TEMP-"; // 임시저장 (형식: TEMP-00001 또는 TEMP-00001-T02211)
|
||||
$PROCESS_ACCEPT = "ACCEPT"; // 가결
|
||||
$PROCESS_REJECTION = "REJECT"; // 부결 (기능삭제됨)
|
||||
$PROCESS_RETURN = "RETURN"; // 반송 (재기안 가능)
|
||||
$PROCESS_BACK = "BACK"; // 반송 - 이전 결재자에게 재전달
|
||||
$PROCESS_FINISH = "FINISH"; // 최종 결재완료
|
||||
$PROCESS_DECISION = "FINISH-DECISION"; // 전결 처리
|
||||
$PROCESS_RECEIVE = "RECEIVE"; // 부서접수 대기
|
||||
$PROCESS_CANCEL = "CANCEL"; // 기안취소
|
||||
$PROCESS_DELETE = "DELETE"; // 기안 삭제
|
||||
|
||||
/* 문서 편집 상태 코드 */
|
||||
$DOC_STATUS_CREATE = "CREATE"; // 새 기안 문서 작성
|
||||
$DOC_STATUS_EDIT = "EDIT"; // 기안 문서 편집
|
||||
$DOC_STATUS_VIEW = "VIEWER"; // 기안 문서 보기 (편집불가)
|
||||
$DOC_STATUS_APPROVE = "APPROVE"; // 결재함 문서 결재하기
|
||||
$DOC_STATUS_ACCEPT = "ACCEPT"; // 부서 문서 접수하기
|
||||
|
||||
/* 결재 라인 위치 코드 */
|
||||
$PROCESS_CODE = "부서내"; // 부서내 결재 진행 중
|
||||
$TEMPORARY_CODE = "부서내임시저장"; // 임시저장 코드
|
||||
$SANCTION_CODE = "결의부서내"; // 결의부서 결재 진행 중
|
||||
$SANCTION_CODE2 = "처리부서내"; // 처리부서 결재 진행 중
|
||||
$STEP_NO = 9; // 최대 결재 단계 수
|
||||
```
|
||||
|
||||
### 3.3 문서 번호 채번 알고리즘 (Serial Number Generation)
|
||||
|
||||
결재 상신 시 문서번호가 자동으로 채번되는 두 가지 방식이 있습니다.
|
||||
|
||||
#### A. 임시저장 문서번호 (`TempSerialNo` / `TempSerialNo2`)
|
||||
|
||||
```php
|
||||
// 형식: "TEMP-00001" 또는 "TEMP-00001-T02211"
|
||||
function TempSerialNo() {
|
||||
// SanctionDoc_tbl에서 TEMP-로 시작하는 마지막 번호 조회
|
||||
$res04 = mysql_query("SELECT * FROM SanctionDoc_tbl WHERE DocSN LIKE 'TEMP-%' ORDER BY DocSN DESC LIMIT 0,1", $db);
|
||||
if (mysql_num_rows($res04) > 0) {
|
||||
$aa = mysql_result($res04, 0, "DocSN");
|
||||
$bb = split("TEMP-", $aa);
|
||||
return "TEMP-" . sprintf("%05d", ($bb[1] + 1)); // 5자리 zero-padding
|
||||
} else {
|
||||
return "TEMP-" . sprintf("%05d", 1); // 최초: TEMP-00001
|
||||
}
|
||||
}
|
||||
|
||||
// TempSerialNo2: 사번 suffix 포함 형식 (TEMP-00001-T02211)
|
||||
// split("-", "TEMP-00021-T02211") → $bb[1] = "00021"
|
||||
```
|
||||
|
||||
#### B. 결재 상신 문서번호 (`NewSerialNo` / `NewSerialNo2`)
|
||||
|
||||
```php
|
||||
// 형식: "2026-00001" 또는 "2026-00001-T02211"
|
||||
function NewSerialNo() {
|
||||
$NewKey = date('Y-'); // "2026-"
|
||||
$res04 = mysql_query("SELECT * FROM SanctionDoc_tbl WHERE DocSN LIKE '$NewKey%' ORDER BY DocSN DESC LIMIT 0,1", $db);
|
||||
if (mysql_num_rows($res04) > 0) {
|
||||
$aa = mysql_result($res04, 0, "DocSN");
|
||||
$bb = split($NewKey, $aa); // "2026-00005" → $bb[1] = "00005"
|
||||
return $NewKey . sprintf("%05d", ($bb[1] + 1)); // "2026-00006"
|
||||
} else {
|
||||
return $NewKey . sprintf("%05d", 1); // 최초: "2026-00001"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 결재선 순회 알고리즘 (`NextSanctionState`)
|
||||
|
||||
결재 진행 시 현재 결재 위치를 다음 결재자로 이동시키는 핵심 알고리즘입니다.
|
||||
|
||||
```php
|
||||
function NextSanctionState($Tmp_Sanction, $Tmp_SanctionState) {
|
||||
// $Tmp_Sanction = "A001:B002:RECEIVE:C003:D004:FINISH" (결재선 배열, ':' 구분)
|
||||
// $Tmp_SanctionState = "1:부서내:A001:2026-07-20" (현재 단계:코드:사번:날짜)
|
||||
|
||||
$TmpState = split(":", $Tmp_SanctionState);
|
||||
$Start = $TmpState[0]; // 현재 결재 인덱스
|
||||
|
||||
// RECEIVE 위치(index) 먼저 탐색
|
||||
for ($i = $Start; $i < count($TmpArr); $i++) {
|
||||
if ($TmpArr[$i] == $PROCESS_RECEIVE) {
|
||||
$RECEIVE_INDEX = $i; break;
|
||||
}
|
||||
}
|
||||
|
||||
// 다음 결재자 상태 결정
|
||||
for ($i = $Start; $i < count($TmpArr); $i++) {
|
||||
switch ($TmpArr[$i]) {
|
||||
case $PROCESS_RECEIVE: // 부서접수로 넘김
|
||||
$Res_SanctionState = ($i+1).":".$PROCESS_RECEIVE.":".$TmpState[2].":".date('Y-m-d');
|
||||
break;
|
||||
case $PROCESS_FINISH: // 결재 완료
|
||||
$Res_SanctionState = ($i+1).":".$PROCESS_FINISH.":".$TmpState[2].":".date('Y-m-d');
|
||||
break;
|
||||
default: // 다음 결재자에게 넘김
|
||||
// RECEIVE 이후면 처리부서내(SANCTION_CODE2), 이전이면 결의부서내(SANCTION_CODE)
|
||||
$SANCTION_CODE_ = ($i > $RECEIVE_INDEX) ? $SANCTION_CODE2 : $SANCTION_CODE;
|
||||
$Res_SanctionState = ($i+1).":".$SANCTION_CODE_.":".$TmpArr[$i].":".date('Y-m-d');
|
||||
break;
|
||||
}
|
||||
break; // 첫 번째 유효 결재자만 처리
|
||||
}
|
||||
return $Res_SanctionState;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 결재 서명/인장 렌더링 알고리즘 (`FindSanctionState` / `FindSanctionState2`)
|
||||
|
||||
결재 문서 화면에서 결재자 서명 이미지(인장) 또는 텍스트를 표시하는 렌더링 로직입니다.
|
||||
|
||||
```php
|
||||
function FindSanctionState2($TmpSN, $sName, $sGroup) {
|
||||
// SanctionState_tbl에서 해당 결재자의 결재 이력 조회
|
||||
$azSQL = "SELECT * FROM SanctionState_tbl WHERE DocSN='$TmpSN' AND MemberNo LIKE '%$sName%'";
|
||||
|
||||
$SanctionState = mysql_result($res06, 0, "SanctionState");
|
||||
$src_photo = "../../../erpphoto/$MemberNo.jpg"; // 결재자 서명 사진 경로
|
||||
|
||||
// 대리결재 감지
|
||||
if ($sGroup == "결의부서내") {
|
||||
if (strpos(mysql_result($res06, 0, "MemberNo"), "대결") !== false) {
|
||||
$Member_Name .= "-대결"; // 대리결재 표시
|
||||
}
|
||||
}
|
||||
|
||||
if ($SanctionState == "ACCEPT" || $SanctionState == "FINISH-DECISION") {
|
||||
if (file_exists($src_photo)) {
|
||||
// 서명 이미지 존재 시: <img src='erpphoto/A001.jpg' height=30>
|
||||
return "<img src='$src_photo' height=30><br>$Member_Name<br>($SanctionDate)";
|
||||
} else {
|
||||
// 서명 없음 시: 빨간색 텍스트("승인" 또는 "전결")
|
||||
$ok_str = ($SanctionState == "ACCEPT") ? "승인" : "전결";
|
||||
return "<font color=red>$ok_str</font><br><br>$Member_Name<br>($SanctionDate)";
|
||||
}
|
||||
} else {
|
||||
return "<br><br>$Member_Name<br>(미결)"; // 아직 결재 안 됨
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 공통 코드 룩업 함수 목록 (`approval_function.php`)
|
||||
|
||||
전자결재 처리 중 MySQL `intranet_tbl` / `member_tbl` / `SystemConfig_Tbl`을 조회하는 헬퍼 함수 목록입니다.
|
||||
|
||||
| 함수명 | 조회 테이블 | 반환값 |
|
||||
| :--- | :--- | :--- |
|
||||
| `MemberNo2Ip($mCode)` | `intranet_tbl` | 사번으로 IP 주소 반환 (끝자리 0/1이면 공백) |
|
||||
| `MemberNo2BossIP($Tmp_Sanction, $Step)` | `intranet_tbl` | 결재선 특정 스텝의 결재자 IP |
|
||||
| `MemberNo2Name($mCode)` | `member_tbl` | 사번 → 한글 성명 |
|
||||
| `MemberNo2Rank($mCode)` | `member_tbl`, `SystemConfig_Tbl` | 사번 → 직급명 |
|
||||
| `MemberNo2GroupCode($mCode)` | `member_tbl` | 사번 → 부서코드 (2자리 zero-pad) |
|
||||
| `MemberNo2GroupName($mCode)` | `member_tbl`, `SystemConfig_Tbl` | 사번 → 부서명 |
|
||||
| `MemberNo2SiteName($mCode)` | `systemconfig_tbl` | 사번 → 현장명 (TeamLeader 기준) |
|
||||
| `DocCode2Name($DocCode)` | `systemconfig_tbl` | 결재 서식 코드 → 서식명 |
|
||||
| `ProjectCode2Name($mCode)` | `project_tbl` | 프로젝트 코드 → 약칭 |
|
||||
| `ProjectCode2Bridge($mCode, $no)` | `project_cs_summary_tbl` | 교량 프로젝트 약칭 |
|
||||
| `Code2Name($mCode, $dbSysKey, $Kind)` | `SystemConfig_Tbl` | 일반 코드 → 명칭 (`Kind=0`) 또는 설명 (`Kind=1`) |
|
||||
| `Group2Manager($mCode)` | `SystemConfig_Tbl` | 부서코드 → 부서장 사번 (`Note` 컬럼) |
|
||||
| `ProcessingState($TmpSN, $tmpState, $mCode)` | `SanctionDoc_tbl` | 현재 결재 상태를 한국어 명칭으로 변환 |
|
||||
| `FindSanctionDate($TmpSN, $TmpMemberNo)` | `SanctionState_tbl` | 특정 결재자의 결재일자 반환 |
|
||||
| `TempState($mCode)` | — | 임시저장 상태 문자열 생성 (`0:부서내임시저장:A001:YYYY-MM-DD`) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 시스템 글로벌 변수 및 초기화 파일 (`DefaultInformation.php`)
|
||||
|
||||
모든 컨트롤러에서 `include "../../util/DefaultInformation.php"`로 로드되는
|
||||
**시스템 기본 정보 세션 초기화 파일**입니다.
|
||||
|
||||
```php
|
||||
/* 화면 요청 정보 */
|
||||
$smarty->assign('auth_page_id', $_REQUEST['target_id']);
|
||||
$smarty->assign('auth_page_devYN2', 'Y');
|
||||
$smarty->assign('satis_user_id', $_SESSION['satis_user_id']);
|
||||
|
||||
/* 개발자 화이트리스트 (devYN='Y' 권한 부여) */
|
||||
$devUserList = [
|
||||
"203155" => "한정규",
|
||||
"216070" => "정명준",
|
||||
"209171" => "신지호",
|
||||
"216011" => "장계석",
|
||||
"221064" => "김병철",
|
||||
"223158" => "김진선",
|
||||
];
|
||||
|
||||
/* 로그인 사용자가 개발자 목록에 있으면 devYN='Y' 설정 */
|
||||
if (array_key_exists($_SESSION['satis_user_id'], $devUserList)) {
|
||||
$smarty->assign('auth_page_devYN', 'Y');
|
||||
}
|
||||
|
||||
/* 회사 기본 정보 */
|
||||
$site_code = "SAMAN"; // 회사 영문 식별 코드
|
||||
$site_name = "삼안";
|
||||
$Corporation_name = "(주)삼안";
|
||||
$company_registration_number = "211-81-25425"; // 사업자등록번호
|
||||
$smarty->assign('site_code', $site_code);
|
||||
$smarty->assign('site_name', $site_name);
|
||||
$smarty->assign('Corporation_name', $Corporation_name);
|
||||
$smarty->assign('company_registration_number', $company_registration_number);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 공통 헬퍼 함수 라이브러리 (`Satis/inc/function.php` — 1,093라인)
|
||||
|
||||
| 함수명 | 설명 |
|
||||
| :--- | :--- |
|
||||
| `str_cutting($str, $len)` | 멀티바이트 문자열 자르기 (한글 2바이트 처리, 생략 시 `...` 추가) |
|
||||
| `substr1($str, $len)` | str_cutting의 Trailing 없는 단순 잘라내기 버전 |
|
||||
| `ConfigName($category, $code)` | `config_tbl` 코드 → 명칭 반환 |
|
||||
| `ConfigName2($category, $code)` | `config_tbl` 코드 → 설명(desc) 반환 |
|
||||
| `Code2Name($mCode, $dbSysKey, $Kind)` | `SystemConfig_Tbl` 일반 코드 → 명칭 반환 |
|
||||
| `change_code($pcode)` | 연도 코드 `XX`를 실제 연도(2자리)로 치환 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 데이터베이스 스키마 상세 (MySQL 인트라넷 DB — `hallaerp`)
|
||||
|
||||
`approval_function.php`의 실제 SQL 쿼리 분석으로 도출한 인트라넷 MySQL DB 테이블 구조입니다.
|
||||
|
||||
| 테이블명 | 주요 컬럼 | 역할 |
|
||||
| :--- | :--- | :--- |
|
||||
| `member_tbl` | `MemberNo`, `KorName`, `RankCode`, `GroupCode`, `WorkPosition` | 사원 기본 정보 (`WorkPosition='9'` = 퇴직자) |
|
||||
| `intranet_tbl` | `MemberNo`, `UseIP` | 사원 네트워크 IP 정보 |
|
||||
| `SanctionDoc_tbl` | `DocSN`, `DocCode`, `PG_Date`, `DocTitle`, `DocStatus` | 전자결재 문서 마스터 |
|
||||
| `SanctionState_tbl` | `DocSN`, `MemberNo`, `SanctionOrder`, `SanctionState`, `SanctionDate` | 결재자별 결재 이력 |
|
||||
| `SystemConfig_Tbl` | `SysKey`, `Code`, `Name`, `Description`, `Note` | 시스템 공통 코드 사전 (부서코드, 직급코드, 결재서식 등) |
|
||||
| `project_tbl` | `ProjectCode`, `ProjectNickname` | 프로젝트 약칭 |
|
||||
| `project_cs_summary_tbl` | `ProjectCode`, `no`, `Item` | 교량/구조물 프로젝트 세부 항목 |
|
||||
| `config_tbl` | `category`, `code`, `name`, `desc` | 화면별 코드 설정 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 예외 처리 & 보안 핸들링 상세 (`AuthClass.php` — 591라인)
|
||||
|
||||
### 7.1 CSRF 토큰 생성 알고리즘
|
||||
```php
|
||||
function Auth_TokenGenerater($assign_boolean = false) {
|
||||
// 62자 문자풀에서 10자리 난수 토큰 생성
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$randomString = '';
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$randomString .= $characters[rand(0, 61)];
|
||||
}
|
||||
if ($assign_boolean) {
|
||||
$_SESSION['Token'] = $randomString; // 서버 세션에 저장
|
||||
$this->smarty->assign('Token', $randomString); // 뷰로 전달 (히든 필드 렌더링)
|
||||
} else {
|
||||
return $randomString;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 토큰 검증 흐름
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor User
|
||||
participant Controller
|
||||
participant AuthClass
|
||||
participant Session
|
||||
|
||||
User->>Controller: 폼 제출 (Token 파라미터 포함)
|
||||
Controller->>AuthClass: Auth_TokenChecker($Token, $page_move=true)
|
||||
AuthClass->>Session: $_SESSION['Token'] 조회
|
||||
alt 토큰 일치
|
||||
AuthClass->>Controller: Smarty assign('Token', ...) 후 정상 처리
|
||||
else 토큰 불일치
|
||||
AuthClass->>Session: session_destroy() 세션 파기
|
||||
AuthClass->>User: auth_move_page.tpl 출력 (로그인 페이지 이동)
|
||||
AuthClass->>Controller: exit() 강제 종료
|
||||
end
|
||||
```
|
||||
|
||||
### 7.3 세션 변수 목록
|
||||
|
||||
| 세션 키 | 설명 |
|
||||
| :--- | :--- |
|
||||
| `$_SESSION['satis_user_id']` | 로그인 사원번호 (예: `"221064"`) |
|
||||
| `$_SESSION['satis_user_name']` | 로그인 사원 성명 |
|
||||
| `$_SESSION['satis_user_deptcode']` | 사원 부서코드 |
|
||||
| `$_SESSION['satis_user_deptname']` | 사원 부서명 |
|
||||
| `$_SESSION['Token']` | CSRF Anti-Forgery Token (10자리 난수) |
|
||||
| `$_SESSION['Title']` | 현재 화면 제목 |
|
||||
| `$_SESSION['Auth']` | 권한 레벨 |
|
||||
| `$_SESSION['Type']` | 사용자 유형 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 핵심 소스 파일 사전 (Source File Dictionary — 전체)
|
||||
|
||||
| 파일 경로 | 용량 / 라인 | 핵심 역할 |
|
||||
| :--- | :--- | :--- |
|
||||
| `Satis/sys/util/OracleClass.php` | 46KB / 1,392라인 | Oracle OCI 커넥션, Ref Cursor 조회/DML, 인코딩 변환 |
|
||||
| `Satis/sys/util/AuthClass.php` | 18KB / 591라인 | 세션 토큰 생성/검증, CSRF 방어 |
|
||||
| `Satis/sys/util/CommonCodeList.php` | 294KB | 시스템 공통 코드 PHP 배열 인메모리 캐시 |
|
||||
| `Satis/inc/approval_function.php` | 35KB / 1,224라인 | 전자결재 상태 처리, 결재선 순회, 서명 렌더링 |
|
||||
| `Satis/inc/function.php` | 30KB / 1,093라인 | 문자열 처리, 코드룩업, 공통 헬퍼 함수 |
|
||||
| `Satis/inc/function_intranet.php` | 33KB | 인트라넷 전용 헬퍼 함수 |
|
||||
| `Satis/inc/approval_var.php` | 1.6KB / 29라인 | 전자결재 상태 상수 정의 |
|
||||
| `Satis/inc/dbcon.inc` | 0.4KB | 인트라넷 MySQL 커넥션 (`erp.samaneng.com/hallaerp`) |
|
||||
| `Satis/inc/saman_icube_dbcon.inc` | 0.5KB | 더존 iCube MS-SQL 커넥션 (`192.168.13.50:5539/DZICUBE`) |
|
||||
| `Satis/sys/util/DefaultInformation.php` | 1.3KB | 시스템 글로벌 변수, 개발자 권한, 회사 정보 초기화 |
|
||||
| `SmartyConfig.php` | 0.3KB | Smarty 엔진 경로 설정 |
|
||||
| `Satis/sys/util/PrintAgent.php` | 1KB | 인쇄 에이전트 유틸리티 |
|
||||
| `Satis/sys/util/ReportViewExcel.php` | 2.8KB | Excel 보고서 출력 처리 |
|
||||
|
||||
---
|
||||
|
||||
## 9. M/M (Man-Month) 투입 공수 및 원가 배부 공식
|
||||
|
||||
엔지니어링 업계 특성상 프로젝트별 인건비 원가 배부는 투입 M/M 비율을 기준으로 계산됩니다.
|
||||
|
||||
$$\text{Project}_{i} \text{ 원가 배부액} = \text{직원 월 급여} \times \left( \frac{\text{Project}_{i} \text{ 투입 M/M}}{\displaystyle\sum_{j=1}^{n} \text{Project}_{j} \text{ 투입 M/M}} \right)$$
|
||||
|
||||
**처리 흐름**:
|
||||
1. `PersonPaymentCalculation`: 직원의 당월 급여 총액 및 4대보험 회사 부담금 계산
|
||||
2. `ProjectMenHour`: 해당 월 직원의 프로젝트별 투입 M/M 입력
|
||||
3. Oracle 저장 프로시저: 비율 계산 → 각 프로젝트 원가 테이블 자동 배부
|
||||
4. `AccountGisungCalculation`: 프로젝트 기성 청구 시 누적 원가 반영
|
||||
|
||||
---
|
||||
|
||||
## 10. 로우레벨 개발 시 주의사항
|
||||
|
||||
> [!CAUTION]
|
||||
> **SQL Injection 위험**: `approval_function.php` 및 `function.php`의 MySQL 함수들은 대부분 `$mCode` 값을 필터링 없이 SQL에 직접 삽입합니다. 수정 시 반드시 `mysql_real_escape_string()` 또는 PDO Prepared Statement로 교체해야 합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> **레거시 드라이버**: `mysql_connect()`, `mssql_connect()` 등 PHP 7.x에서 완전히 제거된 드라이버를 사용합니다. PHP 5.6 이하 환경에서만 실행 가능합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> **하드코딩된 개발자 화이트리스트**: `DefaultInformation.php`에 개발자 사번이 하드코딩되어 있습니다. 인사 이동 시 소스 직접 수정이 필요합니다.
|
||||
|
||||
> [!NOTE]
|
||||
> **Oracle 트랜잭션**: `ProcedureExcuteQuery()`는 `OCI_COMMIT_ON_SUCCESS`(자동 커밋) 모드로 동작합니다. 여러 DML을 하나의 트랜잭션으로 묶으려면 `OCI_DEFAULT` 모드의 `executeDml()` / `executeSelect()`를 사용해야 합니다.
|
||||
|
||||
> [!NOTE]
|
||||
> **Session 의존성**: 모든 컨트롤러 로직은 `session_start()` → `GetUserInfo.php` → `DefaultInformation.php` 순서로 초기화가 완료되어야 합니다. 순서가 바뀌면 `$_SESSION['satis_user_id']`가 null이 되어 개발자 권한 판별이 실패합니다.
|
||||
Reference in New Issue
Block a user