Compare commits
12 Commits
V202510150
...
c26013bb81
| Author | SHA1 | Date | |
|---|---|---|---|
| c26013bb81 | |||
| 8a4aa8875f | |||
| eb715b8e1b | |||
| b0383d3479 | |||
| 2f20549444 | |||
| 60356f886c | |||
| 0be0790e03 | |||
| fec51a86f3 | |||
| 5b12cccb77 | |||
| 4c84ae5db2 | |||
| c3c86ae9cf | |||
| e0d992eb64 |
121
README.md
121
README.md
@@ -1,21 +1,21 @@
|
||||
# PLM 솔루션 (ILSHIN)
|
||||
# RPS 업무관리 시스템
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
본 프로젝트는 제품 수명 주기 관리(PLM - Product Lifecycle Management) 솔루션입니다. 제품 개발 초기 단계부터 설계, 생산, 유통, 유지보수 및 폐기에 이르기까지 제품과 관련된 모든 데이터와 프로세스를 통합적으로 관리하는 것을 목표로 합니다.
|
||||
본 프로젝트는 RPS(Resource Planning System) 업무관리 시스템입니다. 기업의 자원 계획 및 업무 프로세스를 통합적으로 관리하여 효율적인 업무 처리와 자원 최적화를 목표로 합니다.
|
||||
|
||||
## 주요 기능 (예상)
|
||||
## 주요 기능
|
||||
|
||||
소스 코드 분석 및 일반적인 PLM 솔루션의 기능을 바탕으로 다음과 같은 메뉴/기능을 포함할 것으로 예상됩니다. 실제 메뉴는 애플리케이션 실행 후 확인해야 합니다.
|
||||
RPS 업무관리 시스템의 주요 기능은 다음과 같습니다:
|
||||
|
||||
- **제품 정보 관리:** 제품 분류, 속성, 사양 등 관리
|
||||
- **BOM (Bill of Materials) 관리:** 부품 목록, 계층 구조 관리 (eBOM, mBOM 등)
|
||||
- **설계 변경 관리 (ECO/ECR):** 설계 변경 요청, 검토, 승인 프로세스 관리
|
||||
- **문서 관리:** CAD 데이터, 도면, 기술 문서 등의 버전 관리 및 접근 제어
|
||||
- **프로젝트/일정 관리:** 개발 프로젝트 일정, 리소스, 산출물 관리
|
||||
- **사용자 및 권한 관리:** 역할 기반 접근 제어
|
||||
- **워크플로우 관리:** 표준 프로세스 자동화 및 추적
|
||||
- **데이터 시각화/리포트:** 다양한 형식의 보고서 생성 (데이터 표시는 `jqGrid` 등을 활용할 것으로 보입니다.)
|
||||
- **자원 관리:** 인적 자원, 물적 자원, 시설 등의 통합 관리
|
||||
- **업무 프로세스 관리:** 업무 흐름 정의, 승인 프로세스, 워크플로우 관리
|
||||
- **프로젝트 관리:** 프로젝트 계획, 일정 관리, 진행 상황 추적
|
||||
- **문서 관리:** 업무 문서의 생성, 수정, 승인, 보관 및 검색
|
||||
- **보고서 및 분석:** 업무 현황 분석, KPI 관리, 대시보드 제공
|
||||
- **사용자 및 권한 관리:** 역할 기반 접근 제어 및 권한 관리
|
||||
- **알림 및 메시징:** 업무 관련 알림, 메시지 전송 기능
|
||||
- **데이터 시각화:** 차트, 그래프를 통한 데이터 시각화 (jqGrid, Tabulator 등 활용)
|
||||
|
||||
## 기술 스택
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
- MyBatis (v3.2.3) - 데이터베이스 연동
|
||||
- **Frontend:**
|
||||
- JSP (JavaServer Pages)
|
||||
- JavaScript (jQuery v1.11.3 / v2.1.4, jqGrid v4.7.1 확인)
|
||||
- CSS
|
||||
- JavaScript (jQuery v1.11.3 / v2.1.4, jqGrid v4.7.1, Tabulator 확인)
|
||||
- CSS (basic.css - 메인 스타일시트, 드롭다운 메뉴 및 반응형 디자인 포함)
|
||||
- Apache Tiles (v3.0.5) - 페이지 레이아웃/템플릿
|
||||
- **Database:**
|
||||
- PostgreSQL (연결 정보 및 드라이버 확인)
|
||||
@@ -44,6 +44,99 @@
|
||||
- `pdfbox` (PDF 처리)
|
||||
- 기타 다수 (`WebContent/WEB-INF/lib` 디렉토리 참조)
|
||||
|
||||
## UI 구조 및 메뉴 시스템
|
||||
|
||||
### 메뉴 구조
|
||||
- **상단 네비게이션:** 메인 메뉴가 상단 헤더에 위치
|
||||
- **드롭다운 메뉴:** 상단 메뉴 클릭 시 하위 메뉴가 드롭다운으로 표시
|
||||
- **전체 화면 활용:** 왼쪽 프레임을 제거하고 컨텐츠 영역을 전체 화면으로 확대
|
||||
- **반응형 디자인:** 다양한 화면 크기에 대응하는 반응형 레이아웃
|
||||
|
||||
### 주요 파일
|
||||
- **header.jsp:** 상단 메뉴 및 네비게이션 구조 정의
|
||||
- **basic.css:** 메인 스타일시트, 드롭다운 메뉴 스타일 포함
|
||||
- **메뉴 관련 JavaScript:** jQuery 기반 메뉴 인터랙션 처리
|
||||
|
||||
## Materialize CSS 드롭다운 시스템
|
||||
|
||||
본 시스템은 [Materialize CSS](https://materializecss.com/dropdown.html) 프레임워크의 드롭다운 컴포넌트를 활용하여 현대적이고 사용자 친화적인 메뉴 시스템을 구현합니다.
|
||||
|
||||
### Materialize CSS 드롭다운 특징
|
||||
|
||||
#### 기본 구조
|
||||
```html
|
||||
<!-- 드롭다운 트리거 -->
|
||||
<a class='dropdown-trigger btn' href='#' data-target='dropdown1'>Drop Me!</a>
|
||||
|
||||
<!-- 드롭다운 구조 -->
|
||||
<ul id='dropdown1' class='dropdown-content'>
|
||||
<li><a href="#!">one</a></li>
|
||||
<li><a href="#!">two</a></li>
|
||||
<li class="divider" tabindex="-1"></li>
|
||||
<li><a href="#!">three</a></li>
|
||||
<li><a href="#!"><i class="material-icons">view_module</i>four</a></li>
|
||||
<li><a href="#!"><i class="material-icons">cloud</i>five</a></li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
#### JavaScript 초기화
|
||||
```javascript
|
||||
// DOM 로드 완료 후 초기화
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var elems = document.querySelectorAll('.dropdown-trigger');
|
||||
var instances = M.Dropdown.init(elems, options);
|
||||
});
|
||||
|
||||
// jQuery 방식
|
||||
$('.dropdown-trigger').dropdown();
|
||||
```
|
||||
|
||||
#### 주요 옵션
|
||||
| 옵션명 | 타입 | 기본값 | 설명 |
|
||||
|--------|------|--------|------|
|
||||
| alignment | String | 'left' | 메뉴 정렬 방향 정의 |
|
||||
| autoTrigger | Boolean | true | 키보드 포커스 자동 설정 |
|
||||
| constrainWidth | Boolean | true | 드롭다운 너비를 트리거 크기에 맞춤 |
|
||||
| container | Element | null | 드롭다운의 경계 컨테이너 지정 |
|
||||
| coverTrigger | Boolean | true | false시 트리거 아래에 드롭다운 표시 |
|
||||
| closeOnClick | Boolean | true | 항목 클릭시 드롭다운 닫기 |
|
||||
| hover | Boolean | false | 호버시 드롭다운 열기 |
|
||||
| inDuration | Number | 150 | 열림 애니메이션 지속시간 (ms) |
|
||||
| outDuration | Number | 250 | 닫힘 애니메이션 지속시간 (ms) |
|
||||
|
||||
#### 주요 메서드
|
||||
- **`.open()`**: 드롭다운 열기
|
||||
- **`.close()`**: 드롭다운 닫기
|
||||
- **`.recalculateDimensions()`**: 내용 변경시 크기 재계산
|
||||
- **`.destroy()`**: 인스턴스 제거
|
||||
|
||||
#### 인스턴스 속성
|
||||
- **`el`**: 초기화된 DOM 엘리먼트
|
||||
- **`options`**: 초기화 옵션 객체
|
||||
- **`id`**: 드롭다운 엘리먼트 ID
|
||||
- **`dropdownEl`**: 드롭다운 DOM 엘리먼트
|
||||
- **`isOpen`**: 드롭다운 열림 상태
|
||||
- **`isScrollable`**: 드롭다운 스크롤 가능 여부
|
||||
- **`focusedIndex`**: 포커스된 항목 인덱스
|
||||
|
||||
### 시스템 적용 방식
|
||||
|
||||
본 RPS 시스템에서는 Materialize CSS 드롭다운을 다음과 같이 활용합니다:
|
||||
|
||||
1. **CDN 라이브러리 로드**
|
||||
```html
|
||||
<!-- Materialize CSS -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||
<!-- Material Icons -->
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<!-- Materialize JavaScript -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||
```
|
||||
|
||||
2. **동적 메뉴 로딩**: AJAX를 통해 서버에서 메뉴 데이터를 가져와 동적으로 드롭다운 생성
|
||||
3. **Material Design 아이콘**: 메뉴 항목에 Material Icons 적용으로 시각적 향상
|
||||
4. **커스텀 스타일링**: basic.css를 통해 기존 시스템 디자인과 조화로운 스타일 적용
|
||||
|
||||
## 프로젝트 구조 (폴더별 역할)
|
||||
|
||||
- **`.git/`**: Git 버전 관리 시스템 메타데이터 저장소.
|
||||
|
||||
@@ -486,8 +486,57 @@
|
||||
,CODE_NAME(AREA_CD) AS AREA_NAME
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
B.OBJID AS ROUTE_OBJID,
|
||||
CASE B.STATUS
|
||||
WHEN 'inProcess' THEN '결재중'
|
||||
WHEN 'complete' THEN '결재완료'
|
||||
WHEN 'reject' THEN '반려'
|
||||
ELSE ''
|
||||
END APPR_STATUS,
|
||||
A.OBJID AS APPROVAL_OBJID,
|
||||
A.TARGET_OBJID,
|
||||
B.ROUTE_SEQ
|
||||
FROM
|
||||
APPROVAL A,
|
||||
(
|
||||
select
|
||||
T1.*
|
||||
from
|
||||
(
|
||||
select
|
||||
TARGET_OBJID,
|
||||
max(T.ROUTE_SEQ) as ROUTE_SEQ
|
||||
from
|
||||
ROUTE T
|
||||
group by
|
||||
T.TARGET_OBJID
|
||||
) T,
|
||||
ROUTE T1
|
||||
where
|
||||
T.TARGET_OBJID = T1.TARGET_OBJID
|
||||
and T.ROUTE_SEQ = T1.ROUTE_SEQ
|
||||
) B
|
||||
WHERE
|
||||
A.OBJID = B.APPROVAL_OBJID
|
||||
AND TARGET_TYPE IN ('CONTRACT_ESTIMATE')
|
||||
) A
|
||||
ON T.OBJID::numeric = A.TARGET_OBJID
|
||||
)
|
||||
</sql>
|
||||
|
||||
@@ -519,21 +568,27 @@
|
||||
<if test="product != null and product !='' ">
|
||||
AND product = #{product}
|
||||
</if>
|
||||
|
||||
|
||||
<if test="status_cd !=null and status_cd !=''">
|
||||
AND status_cd = #{status_cd}
|
||||
</if>
|
||||
|
||||
|
||||
|
||||
<if test="result_cd !=null and result_cd !=''">
|
||||
AND result_cd = #{result_cd}
|
||||
</if>
|
||||
|
||||
<if test="contract_start_date != null and !''.equals(contract_start_date)">
|
||||
AND TO_DATE(CONTRACT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
<if test="receipt_start_date != null and !''.equals(receipt_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{receipt_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="contract_end_date != null and !''.equals(contract_end_date)">
|
||||
AND TO_DATE(CONTRACT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
<if test="receipt_end_date != null and !''.equals(receipt_end_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{receipt_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{due_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="due_end_date != null and !''.equals(due_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{due_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
@@ -600,7 +655,46 @@
|
||||
</if>
|
||||
<if test="contract_month != null and !''.equals(contract_month)">
|
||||
AND TO_DATE(TO_CHAR(TO_DATE(CONTRACT_DATE,'YYYY-MM-DD'),'YYYY-MM-DD'),'YYYY-MM') <![CDATA[ = ]]> TO_DATE(SUBSTRING(#{contract_month} FROM 1 FOR 4) || '-' || SUBSTRING(#{contract_month} FROM 5 FOR 2), 'YYYY-MM')
|
||||
</if>
|
||||
</if>
|
||||
|
||||
<!-- 견적관리 추가 검색조건 -->
|
||||
<if test="appr_status !=null and appr_status != '' ">
|
||||
AND APPR_STATUS = #{appr_status}
|
||||
</if>
|
||||
|
||||
<if test="area_cd != null and area_cd !='' ">
|
||||
AND AREA_CD = #{area_cd}
|
||||
</if>
|
||||
|
||||
<if test="paid_type != null and paid_type !='' ">
|
||||
AND PAID_TYPE = #{paid_type}
|
||||
</if>
|
||||
|
||||
<if test="search_partNo != null and search_partNo != ''">
|
||||
AND UPPER(PART_NO) LIKE UPPER('%${search_partNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_partName != null and search_partName != ''">
|
||||
AND UPPER(PART_NAME) LIKE UPPER('%${search_partName}%')
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="receipt_start_date != null and !''.equals(receipt_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{receipt_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="receipt_end_date != null and !''.equals(receipt_end_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{receipt_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{due_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="due_end_date != null and !''.equals(due_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{due_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
@@ -724,9 +818,193 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<update id="saveContractMgmtInfo" parameterType="map">
|
||||
INSERT INTO CONTRACT_MGMT
|
||||
(
|
||||
OBJID
|
||||
,CATEGORY_CD
|
||||
,CUSTOMER_OBJID
|
||||
,PRODUCT
|
||||
,CUSTOMER_PROJECT_NAME
|
||||
,STATUS_CD
|
||||
,DUE_DATE
|
||||
,LOCATION
|
||||
,SETUP
|
||||
,FACILITY
|
||||
,FACILITY_QTY
|
||||
,FACILITY_TYPE
|
||||
,FACILITY_DEPTH
|
||||
,PRODUCTION_NO
|
||||
,BUS_CAL_CD
|
||||
,CATEGORY1_CD
|
||||
,CHG_USER_ID
|
||||
,PLAN_DATE
|
||||
,COMPLETE_DATE
|
||||
,RESULT_CD
|
||||
,PROJECT_NO
|
||||
,PM_USER_ID
|
||||
,CONTRACT_PRICE
|
||||
,CONTRACT_PRICE_CURRENCY
|
||||
,CONTRACT_CURRENCY
|
||||
,REGDATE
|
||||
,WRITER
|
||||
,CONTRACT_NO
|
||||
,CUSTOMER_EQUIP_NAME
|
||||
,REQ_DEL_DATE
|
||||
,CONTRACT_DEL_DATE
|
||||
,CONTRACT_COMPANY
|
||||
,CONTRACT_DATE
|
||||
,PO_NO
|
||||
,MANUFACTURE_PLANT
|
||||
,CONTRACT_RESULT
|
||||
,PROJECT_NAME
|
||||
,SPEC_USER_ID
|
||||
,SPEC_PLAN_DATE
|
||||
,SPEC_COMP_DATE
|
||||
,SPEC_RESULT_CD
|
||||
,EST_USER_ID
|
||||
,EST_PLAN_DATE
|
||||
,EST_COMP_DATE
|
||||
,EST_RESULT_CD
|
||||
,AREA_CD
|
||||
,TARGET_PROJECT_NO
|
||||
,TARGET_PROJECT_NO_DIRECT
|
||||
,CUSTOMER_PRODUCTION_NO
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
#{objId}
|
||||
,#{category_cd}
|
||||
,#{customer_objid}
|
||||
,#{product}
|
||||
,#{customer_project_name}
|
||||
,#{status_cd}
|
||||
,#{due_date}
|
||||
,#{location}
|
||||
,#{setup}
|
||||
,#{facility}
|
||||
,#{facility_qty}
|
||||
,#{facility_type}
|
||||
,#{facility_depth}
|
||||
,#{production_no}
|
||||
,#{bus_cal_cd}
|
||||
,#{category1_cd}
|
||||
,#{chg_user_id}
|
||||
,#{plan_date}
|
||||
,#{complete_date}
|
||||
,#{result_cd}
|
||||
,#{project_no}
|
||||
,#{pm_user_id}
|
||||
,#{contract_price}
|
||||
,#{contract_price_currency}
|
||||
,#{contract_currency}
|
||||
,NOW()
|
||||
,#{writer}
|
||||
,(SELECT TO_CHAR(NOW(),'yy')::VARCHAR ||'C-'||LPAD((SELECT NEXTVAL('contract_mgmt_seq'))::VARCHAR ,4,'0'))
|
||||
,#{customer_equip_name}
|
||||
,#{req_del_date}
|
||||
,#{contract_del_date}
|
||||
,#{contract_company}
|
||||
,#{contract_date}
|
||||
,#{po_no}
|
||||
,#{manufacture_plant}
|
||||
,#{contract_result}
|
||||
,#{project_name}
|
||||
,#{spec_user_id}
|
||||
,#{spec_plan_date}
|
||||
,#{spec_comp_date}
|
||||
,#{spec_result_cd}
|
||||
,#{est_user_id}
|
||||
,#{est_plan_date}
|
||||
,#{est_comp_date}
|
||||
,#{est_result_cd}
|
||||
,#{area_cd}
|
||||
,#{target_project_no}
|
||||
,#{target_project_no_direct}
|
||||
,#{customer_production_no}
|
||||
,#{mechanical_type}
|
||||
,#{overhaul_order}
|
||||
,#{paid_type}
|
||||
,#{receipt_date}
|
||||
,#{part_no}
|
||||
,#{part_name}
|
||||
,#{serial_no}
|
||||
,#{quantity}
|
||||
,#{customer_request}
|
||||
,#{exchange_rate}
|
||||
)
|
||||
ON CONFLICT (OBJID) DO
|
||||
UPDATE
|
||||
SET
|
||||
CATEGORY_CD = #{category_cd}
|
||||
,CUSTOMER_OBJID = #{customer_objid}
|
||||
,PRODUCT = #{product}
|
||||
,CUSTOMER_PROJECT_NAME = #{customer_project_name}
|
||||
,STATUS_CD = #{status_cd}
|
||||
,DUE_DATE = #{due_date}
|
||||
,LOCATION = #{location}
|
||||
,SETUP = #{setup}
|
||||
,FACILITY = #{facility}
|
||||
,FACILITY_QTY = #{facility_qty}
|
||||
,FACILITY_TYPE = #{facility_type}
|
||||
,FACILITY_DEPTH = #{facility_depth}
|
||||
,PRODUCTION_NO = #{production_no}
|
||||
,BUS_CAL_CD = #{bus_cal_cd}
|
||||
,CATEGORY1_CD = #{category1_cd}
|
||||
,CHG_USER_ID = #{chg_user_id}
|
||||
,PLAN_DATE = #{plan_date}
|
||||
,COMPLETE_DATE = #{complete_date}
|
||||
,RESULT_CD = #{result_cd}
|
||||
,PROJECT_NO = #{project_no}
|
||||
,PM_USER_ID = #{pm_user_id}
|
||||
,CONTRACT_PRICE = #{contract_price}
|
||||
,CONTRACT_PRICE_CURRENCY = #{contract_price_currency}
|
||||
,CONTRACT_CURRENCY = #{contract_currency}
|
||||
,CUSTOMER_EQUIP_NAME = #{customer_equip_name}
|
||||
,REQ_DEL_DATE = #{req_del_date}
|
||||
,CONTRACT_DEL_DATE = #{contract_del_date}
|
||||
,CONTRACT_COMPANY = #{contract_company}
|
||||
,CONTRACT_DATE = #{contract_date}
|
||||
,PO_NO = #{po_no}
|
||||
,MANUFACTURE_PLANT = #{manufacture_plant}
|
||||
,CONTRACT_RESULT = #{contract_result}
|
||||
,PROJECT_NAME = #{project_name}
|
||||
,SPEC_USER_ID = #{spec_user_id}
|
||||
,SPEC_PLAN_DATE = #{spec_plan_date}
|
||||
,SPEC_COMP_DATE = #{spec_comp_date}
|
||||
,SPEC_RESULT_CD = #{spec_result_cd}
|
||||
,EST_USER_ID = #{est_user_id}
|
||||
,EST_PLAN_DATE = #{est_plan_date}
|
||||
,EST_COMP_DATE = #{est_comp_date}
|
||||
,EST_RESULT_CD = #{est_result_cd}
|
||||
,AREA_CD = #{area_cd}
|
||||
,TARGET_PROJECT_NO = #{target_project_no}
|
||||
,TARGET_PROJECT_NO_DIRECT= #{target_project_no_direct}
|
||||
,CUSTOMER_PRODUCTION_NO = #{customer_production_no}
|
||||
,MECHANICAL_TYPE = #{mechanical_type}
|
||||
,OVERHAUL_ORDER = #{overhaul_order}
|
||||
,PAID_TYPE = #{paid_type}
|
||||
,RECEIPT_DATE = #{receipt_date}
|
||||
,PART_NO = #{part_no}
|
||||
,PART_NAME = #{part_name}
|
||||
,SERIAL_NO = #{serial_no}
|
||||
,QUANTITY = #{quantity}
|
||||
,CUSTOMER_REQUEST = #{customer_request}
|
||||
,EXCHANGE_RATE = #{exchange_rate}
|
||||
</update>
|
||||
|
||||
<update id="saveContractMgmtInfo_old" parameterType="map">
|
||||
INSERT INTO CONTRACT_MGMT
|
||||
(
|
||||
OBJID
|
||||
,CATEGORY_CD
|
||||
@@ -1096,6 +1374,14 @@
|
||||
,CUSTOMER_PRODUCTION_NO
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt01' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT1
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt02' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT2
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt03' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT3
|
||||
@@ -3376,5 +3662,218 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
-->
|
||||
FROM END_COUNT E, PROJECT_STATS P, ING_COUNT I, DELAY_COUNT D, HOLD_COUNT H, NOPLAN_COUNT N
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 관련 쿼리 -->
|
||||
|
||||
<!-- 견적서 기본 정보 조회 -->
|
||||
<select id="getEstimateTemplateInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CATEGORY_CD,
|
||||
CODE_NAME(CATEGORY_CD) AS CATEGORY_NAME,
|
||||
CUSTOMER_OBJID,
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG AS O WHERE O.OBJID = T.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME,
|
||||
PRODUCT,
|
||||
CODE_NAME(PRODUCT) AS PRODUCT_NAME,
|
||||
CUSTOMER_PROJECT_NAME,
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
PAID_TYPE,
|
||||
RECEIPT_DATE,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
SERIAL_NO,
|
||||
QUANTITY,
|
||||
CUSTOMER_REQUEST,
|
||||
CONTRACT_CURRENCY,
|
||||
CODE_NAME(CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
EXCHANGE_RATE,
|
||||
DUE_DATE,
|
||||
WRITER,
|
||||
(SELECT USER_NAME FROM USER_INFO AS O WHERE O.USER_ID = T.WRITER) AS WRITER_NAME,
|
||||
REGDATE,
|
||||
TO_CHAR(REGDATE,'YYYY-MM-DD') AS REG_DATE
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
WHERE
|
||||
OBJID = #{objId}::NUMERIC
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (ESTIMATE_TEMPLATE 테이블) -->
|
||||
<select id="getEstimateTemplateData" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 -->
|
||||
<select id="getEstimateTemplateItems" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 저장 -->
|
||||
<insert id="insertEstimateTemplate" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{objId}::NUMERIC,
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
#{estimate_no},
|
||||
#{contact_person},
|
||||
#{greeting_text},
|
||||
#{model_name},
|
||||
#{model_code},
|
||||
#{executor_date},
|
||||
#{note1},
|
||||
#{note2},
|
||||
#{note3},
|
||||
#{note4},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 수정 -->
|
||||
<update id="updateEstimateTemplate" parameterType="map">
|
||||
UPDATE ESTIMATE_TEMPLATE
|
||||
SET
|
||||
EXECUTOR = #{executor},
|
||||
RECIPIENT = #{recipient},
|
||||
ESTIMATE_NO = #{estimate_no},
|
||||
CONTACT_PERSON = #{contact_person},
|
||||
GREETING_TEXT = #{greeting_text},
|
||||
MODEL_NAME = #{model_name},
|
||||
MODEL_CODE = #{model_code},
|
||||
EXECUTOR_DATE = #{executor_date},
|
||||
NOTE1 = #{note1},
|
||||
NOTE2 = #{note2},
|
||||
NOTE3 = #{note3},
|
||||
NOTE4 = #{note4},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
<!-- 견적서 템플릿 품목 삭제 -->
|
||||
<delete id="deleteEstimateTemplateItems" parameterType="map">
|
||||
DELETE FROM ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
</delete>
|
||||
|
||||
<!-- 견적서 템플릿 품목 저장 -->
|
||||
<insert id="insertEstimateTemplateItems" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE_ITEM (
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = #{objId}::NUMERIC AND TEMPLATE_TYPE = #{template_type}),
|
||||
(json_array_elements(#{items_json}::json)->>'seq')::INTEGER,
|
||||
json_array_elements(#{items_json}::json)->>'category',
|
||||
json_array_elements(#{items_json}::json)->>'description',
|
||||
json_array_elements(#{items_json}::json)->>'specification',
|
||||
json_array_elements(#{items_json}::json)->>'quantity',
|
||||
json_array_elements(#{items_json}::json)->>'unit',
|
||||
(json_array_elements(#{items_json}::json)->>'unit_price')::NUMERIC,
|
||||
(json_array_elements(#{items_json}::json)->>'amount')::NUMERIC,
|
||||
json_array_elements(#{items_json}::json)->>'note',
|
||||
json_array_elements(#{items_json}::json)->>'remark'
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 카테고리 업데이트 (장비 견적서용) -->
|
||||
<update id="updateEstimateTemplateCategories" parameterType="map">
|
||||
UPDATE ESTIMATE_TEMPLATE
|
||||
SET
|
||||
CATEGORIES_JSON = #{categories_json},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -74,6 +74,9 @@ $(function(){
|
||||
}else if(targetType == "INVOICE"){
|
||||
url = "/supplyChainMgmt/invoiceFormPopUp.do?checkArr="+targetObjId+"&actionType=view";
|
||||
window.open(url, "", "width=1000,height=880");
|
||||
}else if(targetType == "CONTRACT_ESTIMATE"){
|
||||
url = "/contractMgmt/estimateRegistFormPopup.do?objId="+targetObjId+"&actionType=view";
|
||||
window.open(url, "", "width=650,height=400");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -432,7 +432,9 @@ function openProjectFormPopUp(objId){
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<%-- <td><label for="status_cd">진행사항</label></td>
|
||||
<td>
|
||||
<select name="status_cd" id="status_cd" style="width:130px" class="select2" autocomplete="off">
|
||||
@@ -457,13 +459,13 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="pm_user_id">PM</label></td>
|
||||
<td>
|
||||
<select name="pm_user_id" id="pm_user_id" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.pm_user_id}
|
||||
</select>
|
||||
</td>
|
||||
<td><label for="pm_user_id">PM</label></td>
|
||||
<td>
|
||||
<select name="pm_user_id" id="pm_user_id" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.pm_user_id}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
591
WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp
Normal file
591
WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp
Normal file
@@ -0,0 +1,591 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<%
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String connector = person.getUserId();
|
||||
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
|
||||
<c:set var="now" value="<%=new java.util.Date() %>"/>
|
||||
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
|
||||
|
||||
<c:set var="connector" value="<%=connector %>" />
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
//날짜
|
||||
_fnc_datepick();
|
||||
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
$("#btnSearch").click(function(){
|
||||
$("#page").val("1");
|
||||
fn_search();
|
||||
});
|
||||
|
||||
//SR자료등록 팝업
|
||||
$(".File").click(function(){
|
||||
var popup_width = 800;
|
||||
var popup_height = 335;
|
||||
|
||||
var objId = $(this).attr("data-OBJID");
|
||||
var docType =$(this).attr("data-docType");
|
||||
var docTypeName = $(this).attr("data-docTypeName");
|
||||
var params = "?targetObjId="+objId+"&docType="+docType+"&docTypeName="+docTypeName;
|
||||
var url = "/projectConcept/FileRegistPopup.do"+params;
|
||||
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
});
|
||||
|
||||
//영업활동 등록 팝업
|
||||
$(".btnRegist").click(function(){
|
||||
var popup_width = 650;
|
||||
var popup_height = 400;
|
||||
var params = "?actionType=regist"
|
||||
var url = "/contractMgmt/estimateRegistFormPopup.do"+params;
|
||||
//window.open("/ordermgmt/ordermgmtUpdateFormPopup.do"+params, "", "width=650, height=750","menubars=no, scrollbars=yes, resizable=yes");
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
});
|
||||
|
||||
//견적작성 팝업
|
||||
$("#btnEstimate").click(function(){
|
||||
var selectedData = _tabulGrid.getSelectedData();
|
||||
if(selectedData.length < 1){
|
||||
Swal.fire("견적서를 작성할 행을 선택해주십시오.");
|
||||
return false;
|
||||
} else if(selectedData.length > 1){
|
||||
Swal.fire("한번에 한개의 견적서만 작성 가능합니다.");
|
||||
return false;
|
||||
} else {
|
||||
var objId = fnc_checkNull(selectedData[0].OBJID);
|
||||
|
||||
// 견적서 양식 선택 팝업
|
||||
Swal.fire({
|
||||
title: '견적서 양식을 선택하세요',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: '일반 견적서',
|
||||
denyButtonText: '장비 견적서',
|
||||
cancelButtonText: '취소',
|
||||
confirmButtonColor: '#3085d6',
|
||||
denyButtonColor: '#28a745',
|
||||
cancelButtonColor: '#d33',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// 일반 견적서 (Template 1)
|
||||
fn_openEstimateTemplate(objId, "1");
|
||||
} else if (result.isDenied) {
|
||||
// 장비 견적서 (Template 2)
|
||||
fn_openEstimateTemplate(objId, "2");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//고객 등록 팝업
|
||||
$(".supplyMng").click(function(){
|
||||
//window.open("/ordermgmt/ordermgmtUpdateFormPopup.do"+params, "", "width=650, height=750","menubars=no, scrollbars=yes, resizable=yes");
|
||||
window.open("/contractMgmt/supplyMngPagingList.do", "", "width=1150, height=676","menubars=no, scrollbars=yes, resizable=yes");
|
||||
});
|
||||
|
||||
|
||||
//엔터 조회
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#page").val("1");
|
||||
fn_search();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//삭제
|
||||
$("#btnDelete").click(function(){
|
||||
fn_delete();
|
||||
});
|
||||
|
||||
|
||||
$("#btnExcel").click(function(){
|
||||
document.form1.actionType.value = "excel";
|
||||
document.form1.action = "/contractMgmt/contractList.do";
|
||||
document.form1.submit();
|
||||
});
|
||||
|
||||
//결재상신
|
||||
$("#btnApproval").click(function(){
|
||||
var selectedData = _tabulGrid.getSelectedData();
|
||||
if(selectedData.length<1){
|
||||
Swal.fire("결재상신할 행을 선택해주십시오.");
|
||||
return false;
|
||||
}else if(selectedData.length>1){
|
||||
Swal.fire("한번에 한개의 결재만 가능합니다.");
|
||||
return false;
|
||||
}else{
|
||||
|
||||
var targetStatus = fnc_checkNull(selectedData[0].APPR_STATUS);
|
||||
var status = fnc_checkNull(selectedData[0].STATUS);
|
||||
|
||||
if(targetStatus == "결재완료" || targetStatus == "결재중" || status == "cancel"){
|
||||
Swal.fire("작성중/결재반려인 상태만 결재상신 가능합니다.");
|
||||
return false;
|
||||
}else{
|
||||
if(confirm("결재상신 하시겠습니까?")){
|
||||
var objId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var title = encodeURIComponent(fnc_checkNull(selectedData[0].CONTRACT_NO));
|
||||
window.open("/approval/registApproval.do?targetType=CONTRACT_ESTIMATE&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
fn_search();
|
||||
});
|
||||
|
||||
var columns = [
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '영업번호', field : 'CONTRACT_NO', frozen:true,
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_projectConceptDetail(objid);
|
||||
}
|
||||
},
|
||||
{title:"영업정보(상세)", headerHozAlign:'center', //고객정보
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '계약구분', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '차수', field : 'OVERHAUL_ORDER'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '국내/해외', field : 'AREA_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '기계형식', field : 'MECHANICAL_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '고객사 프로젝트명', field : 'CUSTOMER_PROJECT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '예상납기일', field : 'DUE_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '입고지', field : 'LOCATION' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '셋업지', field : 'SETUP' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비방향', field : 'FACILITY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '설비대수', field : 'FACILITY_QTY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '설비타입', field : 'FACILITY_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비길이', field : 'FACILITY_DEPTH' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '담당자', field : 'WRITER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '등록일', field : 'REG_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '첨부파일', field : 'CU01_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
var docType = 'contractMgmt01';
|
||||
var docTypeName = 'contractMgmt01';
|
||||
fn_FileRegist(objid, docType, docTypeName);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{title:"진행사항", headerHozAlign:'center',
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '검토내용', field : 'CU03_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_projectConceptReviewDetail(objid);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '상태', field : 'CONTRACT_RESULT_NAME' }
|
||||
]
|
||||
},
|
||||
{title:"수주정보", headerHozAlign:'center',
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '수주일', field : 'CONTRACT_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : 'PO계약 No', field : 'PO_NO' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : 'PM', field : 'PM_USER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '통화', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주가', field : 'CONTRACT_PRICE_CURRENCY',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '170', title : '당사프로젝트명', field : 'PROJECT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '계약납기일', field : 'CONTRACT_DEL_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '요청납기일', field : 'REQ_DEL_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수주회사', field : 'CONTRACT_COMPANY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제작공장', field : 'MANUFACTURE_PLANT_NAME' }
|
||||
]
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '상태', field : 'APPR_STATUS' ,
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
var APPROVAL_OBJID = fnc_checkNull(cell.getData().APPROVAL_OBJID);
|
||||
var ROUTE_OBJID = fnc_checkNull(cell.getData().ROUTE_OBJID);
|
||||
approval_form(APPROVAL_OBJID,ROUTE_OBJID);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
//var grid;
|
||||
function fn_search(){
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/contractMgmt/contractGridList.do", columns, true);
|
||||
}
|
||||
|
||||
function _fnc_datepick(){
|
||||
var $dateinput = $("input.date_icon");
|
||||
for(var i=0; i<$dateinput.length; i++){
|
||||
$dateinput.eq(i).attr("size","10");
|
||||
$dateinput.eq(i).datepicker({
|
||||
changeMonth:true,
|
||||
changeYear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fn_delete(){
|
||||
var checkedObj = _tabulGrid.getSelectedData();
|
||||
if(0 < checkedObj.length){
|
||||
var objId = fnc_checkNull(checkedObj[0].OBJID);
|
||||
//if(confirm("선택한 정보를 삭제하시겠습니까?")){
|
||||
Swal.fire({
|
||||
title: '선택한 고객정보를 삭제하시겠습니까?',
|
||||
text: '',
|
||||
icon: 'warning',
|
||||
|
||||
showCancelButton: true, // cancel버튼 보이기. 기본은 원래 없음
|
||||
confirmButtonColor: '#3085d6', // confrim 버튼 색깔 지정
|
||||
cancelButtonColor: '#d33', // cancel 버튼 색깔 지정
|
||||
confirmButtonText: '확인', // confirm 버튼 텍스트 지정
|
||||
cancelButtonText: '취소', // cancel 버튼 텍스트 지정
|
||||
reverseButtons: false, // 버튼 순서 거꾸로
|
||||
|
||||
}).then(result => {
|
||||
// 만약 Promise리턴을 받으면,
|
||||
if (result.isConfirmed) { // 만약 모달창에서 confirm 버튼을 눌렀다면
|
||||
//var param = $("#form1").serialize();
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : "/contractMgmt/deleteContractMngInfo.do",
|
||||
data: {
|
||||
"objId":objId
|
||||
},
|
||||
dataType:"json",
|
||||
success:function(data){
|
||||
if(data.result == 'true'){
|
||||
Swal.fire("삭제되었습니다.");
|
||||
fn_search();
|
||||
};
|
||||
}
|
||||
,error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
Swal.fire("선택한 항목이 없습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
function approval_form(APPROVAL_OBJID,ROUTE_OBJID){
|
||||
|
||||
url = "/approval/approvalDetail.do?approvalObjId="+APPROVAL_OBJID+"&routeObjId="+ROUTE_OBJID;
|
||||
|
||||
fn_centerPopup(650,400,url,'approvalDetailPopup')
|
||||
}
|
||||
|
||||
function fn_FileRegist(objId, docType, docTypeName){
|
||||
var popup_width = 800;
|
||||
var popup_height = 300;
|
||||
|
||||
var objId = objId;
|
||||
var docType = docType;
|
||||
var docTypeName = docTypeName;
|
||||
var params = "?targetObjId="+objId+"&docType="+docType+"&docTypeName="+docTypeName;
|
||||
var url = "/projectConcept/FileRegistPopup.do"+params;
|
||||
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
//영업활동등록 상세
|
||||
function fn_projectConceptDetail(objId){
|
||||
var popup_width = 650;
|
||||
var popup_height = 400;
|
||||
var url = "/contractMgmt/estimateRegistFormPopup.do?objId="+objId;
|
||||
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
//검토내용 상세
|
||||
function fn_projectConceptReviewDetail(objId){
|
||||
var popup_width = 800;
|
||||
var popup_height = 250;
|
||||
var url = "/contractMgmt/contracMgmtReviewFormPopup.do?objId="+objId;
|
||||
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
//견적서 양식 열기
|
||||
function fn_openEstimateTemplate(objId, templateType){
|
||||
var popup_width = 900;
|
||||
var popup_height = 800;
|
||||
var url = "";
|
||||
|
||||
if(templateType === "1"){
|
||||
// 일반 견적서
|
||||
url = "/contractMgmt/estimateTemplate1.do?objId="+objId;
|
||||
} else if(templateType === "2"){
|
||||
// 장비 견적서
|
||||
url = "/contractMgmt/estimateTemplate2.do?objId="+objId;
|
||||
}
|
||||
|
||||
window.open(url, "estimateTemplate", "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
//코드값을 받아와서 동적으로 selectbox 생성
|
||||
function optionJobGroup(code){
|
||||
var val=code;
|
||||
var params = "";
|
||||
var option="";
|
||||
var combobox = $("#writer");
|
||||
combobox.empty();
|
||||
if(val!=""){
|
||||
params += "codeId="+val;
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : "/projectConcept/makewrite.do",
|
||||
data : params,
|
||||
dataType:"json",
|
||||
async: false,
|
||||
success: function(data){
|
||||
if(data.RESULT !=""){
|
||||
option += "<option value=''>전체</option>";
|
||||
option += data.RESULT;
|
||||
combobox.append(option);
|
||||
}
|
||||
}
|
||||
});
|
||||
// alert(Number(lev-1));
|
||||
//$("#code"+Number(lev-1)).val(code).prop("selected", true);
|
||||
}else{
|
||||
|
||||
option += "<option value=''>전체</option>";
|
||||
combobox.append(option);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//코드값을 받아와서 동적으로 selectbox 생성
|
||||
function makeSelect(code){
|
||||
var val=code;
|
||||
var params = "";
|
||||
var option="";
|
||||
var combobox = $("#outc_cd6_td");
|
||||
combobox.empty();
|
||||
|
||||
|
||||
/* <select name="outc_cd6" id="outc_cd6" type="select">
|
||||
<option value="">선택</option>
|
||||
</select> */
|
||||
|
||||
if(val!="" && val!="PLA03000"){
|
||||
params += "codeId="+val;
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : "/ordermgmt/makeCodeselect.do",
|
||||
data : params,
|
||||
dataType:"json",
|
||||
async: false,
|
||||
success: function(data){
|
||||
if(data.RESULT !=""){
|
||||
option += "<select name='outc_cd6' id='outc_cd6' type='select'>"
|
||||
option += "<option value=''>선택</option>";
|
||||
option += data.RESULT;
|
||||
option += "</select>";
|
||||
combobox.append(option);
|
||||
$("#outc_cd6").val("${param.outc_cd6}");
|
||||
//$("#outc_cd6").select2();
|
||||
}
|
||||
}
|
||||
});
|
||||
}else{
|
||||
if(val=="PLA03000"){
|
||||
option += "<input type='text' name='outc_cd6' id='outc_cd6' value='${param.outc_cd6}'>"
|
||||
combobox.append(option);
|
||||
}else{
|
||||
option += "<select name='outc_cd6' id='outc_cd6' type='select'>"
|
||||
option += "<option value=''>선택</option>";
|
||||
option += "</select>";
|
||||
combobox.append(option);
|
||||
//$("#outc_cd6").select2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveexcelpop() {
|
||||
|
||||
var partLength = $("input[name=partCheckBox]:checked").length;
|
||||
if(partLength == 0){
|
||||
Swal.fire('선택된 영업정보가 없습니다.');
|
||||
return;
|
||||
}
|
||||
if(partLength > 1){
|
||||
Swal.fire('단건씩 선택해 주세요');
|
||||
return;
|
||||
}
|
||||
|
||||
var orderobjId ="";
|
||||
$("input[name=partCheckBox]:checked").each(function(){
|
||||
orderobjId = fnc_checkNull($(this).attr("data-objId").replace(" ",""));
|
||||
});
|
||||
|
||||
var url = "/ordermgmt/openOrderExcelImportPopUp.do?orderobjId="+orderobjId;
|
||||
var target = "openOrderExcelImportPopUp";
|
||||
window.open(url, target,"width=1245, height=700, menubars=no, scrollbars=yes, resizable=yes");
|
||||
}
|
||||
|
||||
|
||||
//프로젝트의 form,detail 팝업을 보여준다.
|
||||
function openProjectFormPopUp(objId){
|
||||
window.open("","projectFormPopUp","width=1150, height=676");
|
||||
var params = "?actionType=regist"
|
||||
var url = "/project/projectFormPopUp.do"+params;
|
||||
if("" != objId){
|
||||
url = "/project/projectDetailPopUp.do";
|
||||
}
|
||||
var form = document.form1;
|
||||
form.objId.value = objId;
|
||||
form.action = url;
|
||||
form.target = "projectFormPopUp";
|
||||
form.submit();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body class="bodyNoScroll">
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="actionType" value="" />
|
||||
|
||||
<!-- 대시보드용 -->
|
||||
<input type="hidden" name="contract_month" id="contract_month" value="${param.contract_month}">
|
||||
<div class="min_part_enroll">
|
||||
<div class="content-box">
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span>영업관리_견적관리</span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch" name="btnSearch">
|
||||
<input type="button" value="삭제" class="plm_btns" id="btnDelete">
|
||||
<input type="button" value="견적요청등록" class="plm_btns btnRegist">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval">
|
||||
<input type="button" value="견적작성" class="plm_btns" id="btnEstimate">
|
||||
<input type="button" value="메일발송" class="plm_btns" id="btnMail">
|
||||
<!-- <input type="button" value="Excel Download" class="plm_btns" id="btnExcel">
|
||||
<input type="button" value="고객등록" class="plm_btns supplyMng create"> -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="category_cd">주문유형</label></td>
|
||||
<td>
|
||||
<select name="category_cd" id="category_cd" style="width:150px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.category_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="product">제품구분</label></td>
|
||||
<td>
|
||||
<select name="product" id="product" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="area_cd">국내/해외</label></td>
|
||||
<td>
|
||||
<select name="area_cd" id="area_cd" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="0001220">국내</option>
|
||||
<option value="0001221">해외</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="customer_objid">고객사</label></td>
|
||||
<td>
|
||||
<select name="customer_objid" id="customer_objid" style="width:190px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.customer_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="paid_type">유/무상</label></td>
|
||||
<td>
|
||||
<select name="paid_type" id="paid_type" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="paid">유상</option>
|
||||
<option value="free">무상</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="search_partNo" id="search_partNo" value="${param.search_partNo}"/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="search_partName" id="search_partName" value="${param.search_partName}"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="">
|
||||
<label for="" class="">S/N</label>
|
||||
</td>
|
||||
<td colspan="">
|
||||
<input type="text" name="search_serialNo" id="search_serialNo" value="${param.search_serialNo}"/>
|
||||
</td>
|
||||
|
||||
<td><label for="">결재상태</label></td>
|
||||
<td>
|
||||
<select name="appr_status" id="appr_status" class="select2" autocomplete="off" style="width:130px">
|
||||
<option value="">선택</option>
|
||||
<%-- ${code_map.appr_status} --%>
|
||||
<option value="작성중">작성중</option>
|
||||
<option value="결재중">결재중</option>
|
||||
<option value="반려">반려</option>
|
||||
<option value="결재완료">결재완료</option>
|
||||
<option value="취소">취소</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class="">
|
||||
<label>접수일</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="receipt_start_date" id="receipt_start_date" style="width:90px;" autocomplete="off" value="${param.receipt_start_date}" class="date_icon">~
|
||||
<input type="text" name="receipt_end_date" id="receipt_end_date" style="width:90px;" autocomplete="off" value="${param.receipt_end_date}" class="date_icon">
|
||||
</td>
|
||||
|
||||
<td class="">
|
||||
<label>요청납기</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="due_start_date" id="due_start_date" style="width:90px;" autocomplete="off" value="${param.due_start_date}" class="date_icon">~
|
||||
<input type="text" name="due_end_date" id="due_end_date" style="width:90px;" autocomplete="off" value="${param.due_end_date}" class="date_icon">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
1302
WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp
Normal file
1302
WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp
Normal file
File diff suppressed because it is too large
Load Diff
552
WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp
Normal file
552
WebContent/WEB-INF/view/contractMgmt/estimateTemplate1.jsp
Normal file
@@ -0,0 +1,552 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<%
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
String objId = CommonUtils.checkNull(request.getParameter("objId"));
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%> - 견적서 양식1</title>
|
||||
<style type="text/css">
|
||||
@media print {
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 10mm;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Malgun Gothic", "맑은 고딕", Arial, sans-serif;
|
||||
font-size: 12pt;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.estimate-container {
|
||||
width: 210mm;
|
||||
min-height: 297mm;
|
||||
background: white;
|
||||
margin: 0 auto;
|
||||
padding: 20mm;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 28pt;
|
||||
font-weight: bold;
|
||||
letter-spacing: 20px;
|
||||
margin-bottom: 40px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.info-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.info-table td {
|
||||
padding: 5px 8px;
|
||||
border: 1px solid #000;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.info-table .label {
|
||||
background-color: #f0f0f0;
|
||||
font-weight: bold;
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
float: right;
|
||||
text-align: right;
|
||||
margin-top: -80px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.company-stamp {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border: 2px solid #e74c3c;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.company-stamp-text {
|
||||
writing-mode: vertical-rl;
|
||||
font-size: 16pt;
|
||||
font-weight: bold;
|
||||
color: #e74c3c;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
|
||||
.company-details {
|
||||
font-size: 9pt;
|
||||
line-height: 1.6;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.greeting {
|
||||
font-size: 11pt;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.items-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.items-table th,
|
||||
.items-table td {
|
||||
border: 1px solid #000;
|
||||
padding: 6px 8px;
|
||||
text-align: center;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.items-table th {
|
||||
background-color: #f0f0f0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.items-table .col-no { width: 8%; }
|
||||
.items-table .col-desc { width: 22%; }
|
||||
.items-table .col-spec { width: 25%; }
|
||||
.items-table .col-qty { width: 8%; }
|
||||
.items-table .col-unit { width: 10%; }
|
||||
.items-table .col-price { width: 12%; }
|
||||
.items-table .col-amount { width: 12%; }
|
||||
.items-table .col-note { width: 13%; }
|
||||
|
||||
.items-table .text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.items-table .text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.notes-section {
|
||||
margin-top: 30px;
|
||||
font-size: 10pt;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.notes-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.footer-company {
|
||||
text-align: right;
|
||||
margin-top: 40px;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.btn-area {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.plm_btns {
|
||||
padding: 10px 30px;
|
||||
margin: 0 5px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f9fa;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.plm_btns:hover {
|
||||
background-color: #e2e6ea;
|
||||
border-color: #dae0e5;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
textarea {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.editable {
|
||||
background-color: #fffef0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.editable {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
|
||||
// 인쇄 버튼
|
||||
$("#btnPrint").click(function(){
|
||||
window.print();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
if(confirm("견적서를 저장하시겠습니까?")) {
|
||||
fn_save();
|
||||
}
|
||||
});
|
||||
|
||||
// 닫기 버튼
|
||||
$("#btnClose").click(function(){
|
||||
self.close();
|
||||
});
|
||||
|
||||
// 행 추가 버튼
|
||||
$("#btnAddRow").click(function(){
|
||||
fn_addItemRow();
|
||||
});
|
||||
|
||||
// 금액 자동 계산
|
||||
$(document).on("change keyup", ".item-qty, .item-price", function(){
|
||||
fn_calculateAmount($(this).closest("tr"));
|
||||
});
|
||||
|
||||
// 콤마 자동 추가
|
||||
$(".item-price, .item-amount").on("blur", function(){
|
||||
var val = $(this).val().replace(/,/g, "");
|
||||
if(!isNaN(val) && val !== "") {
|
||||
$(this).val(addComma(val));
|
||||
}
|
||||
});
|
||||
|
||||
// 데이터 로드
|
||||
if("<%=objId%>" !== "" && "<%=objId%>" !== "-1") {
|
||||
fn_loadData();
|
||||
}
|
||||
});
|
||||
|
||||
// 금액 계산
|
||||
function fn_calculateAmount(row) {
|
||||
var qty = row.find(".item-qty").val().replace(/,/g, "") || "0";
|
||||
var price = row.find(".item-price").val().replace(/,/g, "") || "0";
|
||||
|
||||
var amount = parseInt(qty) * parseInt(price);
|
||||
if(!isNaN(amount)) {
|
||||
row.find(".item-amount").val(addComma(amount));
|
||||
}
|
||||
}
|
||||
|
||||
// 콤마 추가
|
||||
function addComma(num) {
|
||||
var regexp = /\B(?=(\d{3})+(?!\d))/g;
|
||||
return num.toString().replace(regexp, ',');
|
||||
}
|
||||
|
||||
// 행 추가 함수
|
||||
function fn_addItemRow() {
|
||||
// 비고 행 제외하고 마지막 품목 행 찾기
|
||||
var $lastRow = $("#itemsTableBody tr").not(":last");
|
||||
var lastRowIndex = $lastRow.length;
|
||||
var nextNo = lastRowIndex + 1;
|
||||
|
||||
// 새 행 생성
|
||||
var newRow = '<tr>' +
|
||||
'<td>' + nextNo + '</td>' +
|
||||
'<td class="text-left editable"><input type="text" class="item-desc" value=""></td>' +
|
||||
'<td class="text-left editable"><textarea class="item-spec"></textarea></td>' +
|
||||
'<td class="editable"><input type="text" class="item-qty" value=""></td>' +
|
||||
'<td class="editable"><input type="text" class="item-unit" value="EA"></td>' +
|
||||
'<td class="text-right editable"><input type="text" class="item-price" value=""></td>' +
|
||||
'<td class="text-right editable"><input type="text" class="item-amount" value="₩0" readonly></td>' +
|
||||
'<td class="editable"><input type="text" class="item-note" value=""></td>' +
|
||||
'</tr>';
|
||||
|
||||
// 비고 행 바로 위에 추가
|
||||
$("#itemsTableBody tr:last").before(newRow);
|
||||
|
||||
// 콤마 자동 추가 이벤트 바인딩
|
||||
$("#itemsTableBody").find(".item-price, .item-amount").last().on("blur", function(){
|
||||
var val = $(this).val().replace(/,/g, "");
|
||||
if(!isNaN(val) && val !== "") {
|
||||
$(this).val(addComma(val));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 데이터 로드
|
||||
function fn_loadData() {
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getEstimateDetail.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
objId: "<%=objId%>"
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data && data.estimate) {
|
||||
// 데이터 바인딩
|
||||
$("#executor").val(data.estimate.EXECUTOR || "");
|
||||
$("#recipient").val(data.estimate.RECIPIENT || "");
|
||||
$("#estimate_no").val(data.estimate.ESTIMATE_NO || "");
|
||||
$("#contact_person").val(data.estimate.CONTACT_PERSON || "");
|
||||
$("#greeting_text").val(data.estimate.GREETING_TEXT || "견적을 요청해 주셔서 대단히 감사합니다.\n하기와 같이 견적서를 제출합니다.");
|
||||
|
||||
// 품목 데이터 로드
|
||||
if(data.items && data.items.length > 0) {
|
||||
// 기존 행 초기화 후 데이터 추가
|
||||
var itemsHtml = "";
|
||||
for(var i = 0; i < data.items.length; i++) {
|
||||
var item = data.items[i];
|
||||
itemsHtml += '<tr>';
|
||||
itemsHtml += '<td>' + (i + 1) + '</td>';
|
||||
itemsHtml += '<td class="text-left editable"><input type="text" class="item-desc" value="' + (item.DESCRIPTION || '') + '"></td>';
|
||||
itemsHtml += '<td class="text-left editable"><textarea class="item-spec">' + (item.SPECIFICATION || '') + '</textarea></td>';
|
||||
itemsHtml += '<td class="editable"><input type="text" class="item-qty" value="' + (item.QUANTITY || '') + '"></td>';
|
||||
itemsHtml += '<td class="editable"><input type="text" class="item-unit" value="' + (item.UNIT || 'EA') + '"></td>';
|
||||
itemsHtml += '<td class="text-right editable"><input type="text" class="item-price" value="' + (item.UNIT_PRICE ? addComma(item.UNIT_PRICE) : '') + '"></td>';
|
||||
itemsHtml += '<td class="text-right editable"><input type="text" class="item-amount" value="' + (item.AMOUNT ? addComma(item.AMOUNT) : '₩0') + '" readonly></td>';
|
||||
itemsHtml += '<td class="editable"><input type="text" class="item-note" value="' + (item.NOTE || '') + '"></td>';
|
||||
itemsHtml += '</tr>';
|
||||
}
|
||||
$("#itemsTableBody").html(itemsHtml);
|
||||
}
|
||||
|
||||
// 비고 로드
|
||||
$("#note1").val(data.estimate.NOTE1 || "1. 견적유효기간: 일");
|
||||
$("#note2").val(data.estimate.NOTE2 || "2. 납품기간: 발주 후 1주 이내");
|
||||
$("#note3").val(data.estimate.NOTE3 || "3. VAT 별도");
|
||||
$("#note4").val(data.estimate.NOTE4 || "4. 결제 조건 : 기존 결제조건에 따름.");
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var items = [];
|
||||
$("#itemsTableBody tr").each(function(idx) {
|
||||
var row = $(this);
|
||||
items.push({
|
||||
seq: idx + 1,
|
||||
description: row.find(".item-desc").val(),
|
||||
specification: row.find(".item-spec").val(),
|
||||
quantity: row.find(".item-qty").val(),
|
||||
unit: row.find(".item-unit").val(),
|
||||
unit_price: row.find(".item-price").val().replace(/,/g, ""),
|
||||
amount: row.find(".item-amount").val().replace(/,/g, "").replace(/₩/g, ""),
|
||||
note: row.find(".item-note").val()
|
||||
});
|
||||
});
|
||||
|
||||
var formData = {
|
||||
objId: "<%=objId%>",
|
||||
template_type: "1",
|
||||
executor: $("#executor").val(),
|
||||
recipient: $("#recipient").val(),
|
||||
estimate_no: $("#estimate_no").val(),
|
||||
contact_person: $("#contact_person").val(),
|
||||
greeting_text: $("#greeting_text").val(),
|
||||
note1: $("#note1").val(),
|
||||
note2: $("#note2").val(),
|
||||
note3: $("#note3").val(),
|
||||
note4: $("#note4").val(),
|
||||
items: JSON.stringify(items)
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/contractMgmt/saveEstimate.do",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data.result === "success") {
|
||||
Swal.fire({
|
||||
title: "저장되었습니다.",
|
||||
icon: "success"
|
||||
}).then(function() {
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
self.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire("저장에 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="estimate-container">
|
||||
<!-- 제목 -->
|
||||
<div class="title">견 적 서</div>
|
||||
|
||||
<!-- 상단 정보 테이블 -->
|
||||
<table class="info-table">
|
||||
<colgroup>
|
||||
<col width="80px" />
|
||||
<col width="*" />
|
||||
<col width="300px" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td class="label">시행일자</td>
|
||||
<td class="editable">
|
||||
<input type="text" id="executor" value="">
|
||||
</td>
|
||||
<td rowspan="4" style="text-align: center; border: none; vertical-align: middle; padding: 0;">
|
||||
<div style="width: 100%; text-align: center; margin-bottom: 5px;">
|
||||
<img src="/images/company_stamp.png" alt="회사 도장" style="width: 100%; height: auto;"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
||||
<div class="company-stamp" style="display: none; width: 100%; height: 250px;">
|
||||
<div class="company-stamp-text">㈊알피에스<br>RPS CO., LTD<br>대표이사이동준</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: left; font-size: 9pt; line-height: 1.8; padding: 0 5px;">
|
||||
담당자 : 영업부<br>
|
||||
연락처 :
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">수신처</td>
|
||||
<td class="editable">
|
||||
<input type="text" id="recipient" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">수신인</td>
|
||||
<td class="editable">
|
||||
<input type="text" id="contact_person" value="구매 담당자님 귀하">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">견적번호</td>
|
||||
<td class="editable">
|
||||
<input type="text" id="estimate_no" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 인사말 -->
|
||||
<div style="margin-bottom: 10px; padding: 0px 5px; line-height: 1.6; font-size: 10pt;">
|
||||
견적을 요청해 주셔서 대단히 감사합니다.<br>
|
||||
하기와 같이 견적서를 제출합니다.
|
||||
</div>
|
||||
|
||||
<!-- 부가세 별도 표시 -->
|
||||
<div style="text-align: right; margin-top: -30px; margin-bottom: 20px; padding-right: 10px; font-size: 10pt;">
|
||||
부가세 별도
|
||||
</div>
|
||||
|
||||
<!-- 품목 테이블 -->
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-no">번호<br>NO.</th>
|
||||
<th class="col-desc">품 명<br>DESCRIPTION</th>
|
||||
<th class="col-spec">규 격<br>SPECIFICATION</th>
|
||||
<th class="col-qty">수량<br>Q'TY</th>
|
||||
<th class="col-unit">단위<br>UNIT</th>
|
||||
<th class="col-price">단 가<br>UNIT<br>PRICE</th>
|
||||
<th class="col-amount">금 액<br>AMOUNT</th>
|
||||
<th class="col-note">비고</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="itemsTableBody">
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td class="text-left editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
|
||||
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="text-right editable"><input type="text" class="item-amount" value="₩0" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-note" value=""></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td class="text-left editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
|
||||
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="text-right editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-note" value=""></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" style="height: 100px; vertical-align: top; padding: 10px; text-align: left;">
|
||||
<div style="font-weight: bold; margin-bottom: 10px; text-align: left;"><비고></div>
|
||||
<textarea id="note_remarks" style="width: 100%; height: 70px; border: none; resize: none; font-family: inherit; font-size: 10pt; text-align: left;"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 참조사항 섹션 -->
|
||||
<div class="notes-section">
|
||||
<div class="notes-title"><참조사항></div>
|
||||
<div class="editable"><input type="text" id="note1" value="1. 견적유효기간: 일"></div>
|
||||
<div class="editable"><input type="text" id="note2" value="2. 납품기간: 발주 후 1주 이내"></div>
|
||||
<div class="editable"><input type="text" id="note3" value="3. VAT 별도"></div>
|
||||
<div class="editable"><input type="text" id="note4" value="4. 결제 조건 : 기존 결제조건에 따름."></div>
|
||||
</div>
|
||||
|
||||
<!-- 하단 회사명 -->
|
||||
<div class="footer-company">
|
||||
㈜알피에스
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 버튼 영역 -->
|
||||
<div class="btn-area no-print">
|
||||
<input type="button" value="행 추가" id="btnAddRow" class="plm_btns">
|
||||
<input type="button" value="인쇄" id="btnPrint" class="plm_btns">
|
||||
<input type="button" value="저장" id="btnSave" class="plm_btns">
|
||||
<input type="button" value="닫기" id="btnClose" class="plm_btns">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
718
WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp
Normal file
718
WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp
Normal file
@@ -0,0 +1,718 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<%
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
String objId = CommonUtils.checkNull(request.getParameter("objId"));
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%> - 장비 견적서</title>
|
||||
<style type="text/css">
|
||||
@media print {
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 10mm;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Malgun Gothic", "맑은 고딕", Arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.estimate-container {
|
||||
width: 210mm;
|
||||
min-height: 297mm;
|
||||
background: white;
|
||||
margin: 0 auto;
|
||||
padding: 15mm;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.logo-section {
|
||||
flex: 0 0 150px;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
width: 120px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.title-section {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24pt;
|
||||
font-weight: bold;
|
||||
letter-spacing: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
flex: 0 0 200px;
|
||||
text-align: right;
|
||||
font-size: 9pt;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.basic-info-left {
|
||||
flex: 0 0 40%;
|
||||
}
|
||||
|
||||
.basic-info-right {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
width: 80px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.model-header {
|
||||
background-color: #90EE90;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 1px solid #000;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.items-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.items-table th,
|
||||
.items-table td {
|
||||
border: 1px solid #000;
|
||||
padding: 8px;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.items-table th {
|
||||
background-color: #E8E8E8;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.items-table .col-no { width: 5%; text-align: center; }
|
||||
.items-table .col-desc { width: 25%; }
|
||||
.items-table .col-spec { width: 30%; }
|
||||
.items-table .col-qty { width: 7%; text-align: center; }
|
||||
.items-table .col-price { width: 12%; text-align: right; }
|
||||
.items-table .col-amount { width: 12%; text-align: right; }
|
||||
.items-table .col-remark { width: 9%; text-align: center; }
|
||||
|
||||
.category-row {
|
||||
background-color: #f0f0f0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtotal-row {
|
||||
background-color: #FFFF00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtotal-row td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.notes-section {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
font-size: 9pt;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.notes-section ul {
|
||||
margin: 5px 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.notes-section li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
font-size: 8pt;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.company-footer {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
textarea {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.editable {
|
||||
background-color: #fffef0;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: #FFFF00 !important;
|
||||
}
|
||||
|
||||
.vat-badge {
|
||||
background-color: #FFFF00;
|
||||
padding: 3px 8px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-area {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.plm_btns {
|
||||
padding: 10px 30px;
|
||||
margin: 0 5px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.editable {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
|
||||
// 인쇄 버튼
|
||||
$("#btnPrint").click(function(){
|
||||
window.print();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
if(confirm("장비 견적서를 저장하시겠습니까?")) {
|
||||
fn_save();
|
||||
}
|
||||
});
|
||||
|
||||
// 닫기 버튼
|
||||
$("#btnClose").click(function(){
|
||||
self.close();
|
||||
});
|
||||
|
||||
// 금액 자동 계산
|
||||
$(".item-qty, .item-price").on("change keyup", function(){
|
||||
fn_calculateAmount($(this).closest("tr"));
|
||||
fn_calculateSubtotal($(this).closest("tbody"));
|
||||
});
|
||||
|
||||
// 콤마 자동 추가
|
||||
$(".item-price, .item-amount, .subtotal-amount").on("blur", function(){
|
||||
var val = $(this).val().replace(/,/g, "");
|
||||
if(!isNaN(val) && val !== "") {
|
||||
$(this).val(addComma(val));
|
||||
}
|
||||
});
|
||||
|
||||
// 데이터 로드
|
||||
if("<%=objId%>" !== "" && "<%=objId%>" !== "-1") {
|
||||
fn_loadData();
|
||||
}
|
||||
});
|
||||
|
||||
// 금액 계산
|
||||
function fn_calculateAmount(row) {
|
||||
if(row.hasClass("category-row") || row.hasClass("subtotal-row")) {
|
||||
return;
|
||||
}
|
||||
|
||||
var qty = row.find(".item-qty").val() || "1";
|
||||
var price = row.find(".item-price").val().replace(/,/g, "") || "0";
|
||||
|
||||
var amount = parseInt(qty) * parseInt(price);
|
||||
if(!isNaN(amount)) {
|
||||
row.find(".item-amount").val(addComma(amount));
|
||||
}
|
||||
}
|
||||
|
||||
// 소계 계산
|
||||
function fn_calculateSubtotal(tbody) {
|
||||
var total = 0;
|
||||
tbody.find("tr:not(.category-row):not(.subtotal-row)").each(function() {
|
||||
var amount = $(this).find(".item-amount").val();
|
||||
if(amount) {
|
||||
var numAmount = parseInt(amount.replace(/,/g, "").replace(/-/g, ""));
|
||||
if(!isNaN(numAmount)) {
|
||||
total += numAmount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tbody.find(".subtotal-amount").val(addComma(total));
|
||||
}
|
||||
|
||||
// 콤마 추가
|
||||
function addComma(num) {
|
||||
var regexp = /\B(?=(\d{3})+(?!\d))/g;
|
||||
return num.toString().replace(regexp, ',');
|
||||
}
|
||||
|
||||
// 데이터 로드
|
||||
function fn_loadData() {
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getEstimateDetail.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
objId: "<%=objId%>",
|
||||
template_type: "2"
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data && data.estimate) {
|
||||
// 기본 정보 바인딩
|
||||
$("#executor_date").val(data.estimate.EXECUTOR_DATE || "");
|
||||
$("#recipient").val(data.estimate.RECIPIENT || "");
|
||||
$("#model_name").val(data.estimate.MODEL_NAME || "");
|
||||
$("#model_code").val(data.estimate.MODEL_CODE || "RUV-RA500S");
|
||||
|
||||
// 품목 데이터 로드 (카테고리별로 구분된 경우)
|
||||
if(data.items && data.items.length > 0) {
|
||||
// 데이터 바인딩 로직
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var categories = [];
|
||||
|
||||
// 각 카테고리별 데이터 수집
|
||||
$(".category-section").each(function() {
|
||||
var section = $(this);
|
||||
var categoryName = section.data("category");
|
||||
var items = [];
|
||||
|
||||
section.find("tr.detail-row").each(function() {
|
||||
var row = $(this);
|
||||
items.push({
|
||||
description: row.find(".item-desc").val(),
|
||||
specification: row.find(".item-spec").val(),
|
||||
quantity: row.find(".item-qty").val(),
|
||||
unit_price: row.find(".item-price").val().replace(/,/g, ""),
|
||||
amount: row.find(".item-amount").val().replace(/,/g, ""),
|
||||
remark: row.find(".item-remark").val()
|
||||
});
|
||||
});
|
||||
|
||||
var subtotal = section.find(".subtotal-amount").val().replace(/,/g, "");
|
||||
|
||||
categories.push({
|
||||
category: categoryName,
|
||||
items: items,
|
||||
subtotal: subtotal
|
||||
});
|
||||
});
|
||||
|
||||
var formData = {
|
||||
objId: "<%=objId%>",
|
||||
template_type: "2",
|
||||
executor_date: $("#executor_date").val(),
|
||||
recipient: $("#recipient").val(),
|
||||
model_name: $("#model_name").val(),
|
||||
model_code: $("#model_code").val(),
|
||||
categories: JSON.stringify(categories)
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/contractMgmt/saveEstimate.do",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data.result === "success") {
|
||||
Swal.fire({
|
||||
title: "저장되었습니다.",
|
||||
icon: "success"
|
||||
}).then(function() {
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
self.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire("저장에 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="estimate-container">
|
||||
<!-- 헤더 섹션 -->
|
||||
<div class="header-section">
|
||||
<div class="logo-section">
|
||||
<div style="border: 1px solid #ccc; padding: 20px; text-align: center; font-weight: bold; color: #0066cc;">
|
||||
RPS<br>
|
||||
<span style="font-size: 8pt;">A division of Cimcherry</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title-section">
|
||||
<div class="title">견 적 서</div>
|
||||
</div>
|
||||
<div class="company-info">
|
||||
<div class="company-name">RPS CO., LTD</div>
|
||||
<div>대전광역시 유성구 국제과학로 10로 8</div>
|
||||
<div>TEL: (042)602-3300, FAX: (042)672-3399</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 기본 정보 -->
|
||||
<div class="basic-info">
|
||||
<div class="basic-info-left">
|
||||
<div class="info-row">
|
||||
<div class="info-label">시행일자 :</div>
|
||||
<div class="info-value editable">
|
||||
<input type="text" id="executor_date" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">수신처 :</div>
|
||||
<div class="info-value editable">
|
||||
<input type="text" id="recipient" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-label">품 명 :</div>
|
||||
<div class="info-value editable">
|
||||
<input type="text" id="model_name" value="RUV-RA500S">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 설비 Model 헤더 -->
|
||||
<div class="model-header">
|
||||
설비 Model : <span class="editable" style="display: inline-block; min-width: 200px;">
|
||||
<input type="text" id="model_code" value="RUV-RA500S" style="text-align: center; font-weight: bold;">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 품목 테이블 헤더 -->
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-no">NO</th>
|
||||
<th class="col-desc">DESCRIPTION</th>
|
||||
<th class="col-spec">SPECIFICATION</th>
|
||||
<th class="col-qty">Q'TY</th>
|
||||
<th>UNIT PRICE</th>
|
||||
<th>AMOUNT</th>
|
||||
<th class="col-remark">REMARK</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<!-- 1. 초음파 CNC Machine -->
|
||||
<table class="items-table category-section" data-category="cnc_machine">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">1</td>
|
||||
<td colspan="6">초음파 CNC Machine</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable">
|
||||
<div><input type="text" value="Hole 가공" style="margin-bottom: 5px;"></div>
|
||||
<div class="highlight"><input type="text" class="item-spec" value="최종 견적가"></div>
|
||||
</td>
|
||||
<td class="editable"><input type="text" class="item-qty" value="1"></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable">
|
||||
<div class="vat-badge">VAT 별도</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td colspan="2" class="editable"><input type="text" value="기구"></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 2. 초음파 스캔용 오돔 -->
|
||||
<table class="items-table category-section" data-category="scan_odom">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">2</td>
|
||||
<td colspan="6">초음파 스캔용 오돔</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 3. 전장 -->
|
||||
<table class="items-table category-section" data-category="electric">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">3</td>
|
||||
<td colspan="6">전장</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 4. UTILITY -->
|
||||
<table class="items-table category-section" data-category="utility">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">4</td>
|
||||
<td colspan="6">UTILITY</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 5. 자동화 -->
|
||||
<table class="items-table category-section" data-category="automation">
|
||||
<tbody>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">5</td>
|
||||
<td colspan="6">자동화</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 6. Option -->
|
||||
<table class="items-table category-section" data-category="option">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">6</td>
|
||||
<td colspan="6">Option</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 7. Set up -->
|
||||
<table class="items-table category-section" data-category="setup">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">7</td>
|
||||
<td colspan="6">Set up</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 8. 포장/운송 -->
|
||||
<table class="items-table category-section" data-category="packing">
|
||||
<tbody>
|
||||
<tr class="category-row">
|
||||
<td class="col-no">8</td>
|
||||
<td colspan="6">포장/운송</td>
|
||||
</tr>
|
||||
<tr class="detail-row">
|
||||
<td></td>
|
||||
<td class="editable"><input type="text" class="item-desc" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-spec" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-qty" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-price" value=""></td>
|
||||
<td class="editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-remark" value=""></td>
|
||||
</tr>
|
||||
<tr class="subtotal-row">
|
||||
<td colspan="5">Subtotal</td>
|
||||
<td class="editable"><input type="text" class="subtotal-amount" value="-" readonly></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 비고 섹션 -->
|
||||
<div class="notes-section">
|
||||
<ul style="list-style: none; padding-left: 0;">
|
||||
<li>■ 최종 견적가는 부가세 별도입니다.</li>
|
||||
<li>■ 장비 납기 : 발주 후 7개월</li>
|
||||
<li>■ 운송 조건 : -</li>
|
||||
<li>■ 결제 조건 : 계약금 : 30% / 잔금 : 70%</li>
|
||||
<li style="padding-left: 20px;">- 계약금 : 발주</li>
|
||||
<li style="padding-left: 20px;">- 잔금 : 검사 완료 후</li>
|
||||
<li>■ 특이사항 : 최종 장비 사양 확인 후 추가 변경 발생 시 견적 재산정 진행</li>
|
||||
<li>■ Warrenty Period: 1년(소모성 parts 제외)</li>
|
||||
<li>■ 주의 : RPS 등의의인 초음파 스캔용 임의 탈거 또는 세척시 보증 할 수 없음.</li>
|
||||
<li>■ 패킹 견적은 양산 20대 기준의 견적조건 운송 장비 전달 시 동일한 가격 적용 모로.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 푸터 -->
|
||||
<div class="footer-section">
|
||||
<div>* 견적유효기간: 4/5</div>
|
||||
<div class="company-footer">(㈜)알피에스</div>
|
||||
</div>
|
||||
<div style="text-align: right; font-size: 7pt; color: #999; margin-top: 5px;">
|
||||
* RPS 견적서 - 문서번호: RPS-SE-사업부명 양식 제치부작성 적용본 등을은 결제안전버리
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 버튼 영역 -->
|
||||
<div class="btn-area no-print">
|
||||
<input type="button" value="인쇄" id="btnPrint" class="plm_btns">
|
||||
<input type="button" value="저장" id="btnSave" class="plm_btns">
|
||||
<input type="button" value="닫기" id="btnClose" class="plm_btns">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -10,6 +10,215 @@ uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<link rel="stylesheet" href="/css/basic.css" />
|
||||
<script src="/js/jquery-2.1.4.min.js"></script>
|
||||
<script type="text/javascript" src="/js/sweetalert2.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
background: #f8fafc;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
#loginBack_ilshin {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login_layout {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
width: 420px;
|
||||
position: relative;
|
||||
border: 1px solid #e2e8f0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.logo_slogan_box {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.company-logo {
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 60px;
|
||||
margin: 0 auto 40px;
|
||||
background: url(/images/loginLogo_ilshin.png) center center no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
font-size: 14px;
|
||||
color: #64748b;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.slogun_box_ilshin {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loginWrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#login_box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loginLogo_ilshin {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
background: white;
|
||||
transition: all 0.2s ease;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type="text"]:focus, input[type="password"]:focus {
|
||||
border-color: #3b82f6;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
input[type="text"]::placeholder, input[type="password"]::placeholder {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.login_btn {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
background: #1e293b;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.login_btn:hover {
|
||||
background: #0f172a;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.login_btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 로딩 상태 */
|
||||
.login_btn.loading {
|
||||
background: #64748b !important;
|
||||
cursor: not-allowed;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.login_btn.loading:hover {
|
||||
background: #64748b !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* 로딩바 */
|
||||
.loading-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: #e2e8f0;
|
||||
z-index: 9999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loading-bar.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loading-bar::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background: linear-gradient(90deg, #3b82f6, #1d4ed8);
|
||||
animation: loading-progress 1s ease-in-out forwards;
|
||||
}
|
||||
|
||||
@keyframes loading-progress {
|
||||
0% { width: 0%; }
|
||||
50% { width: 70%; }
|
||||
100% { width: 100%; }
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
text-align: center;
|
||||
margin-top: 32px;
|
||||
font-size: 14px;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.footer-text a {
|
||||
color: #3b82f6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 반응형 디자인 */
|
||||
@media (max-width: 480px) {
|
||||
.login_layout {
|
||||
width: 90%;
|
||||
padding: 32px 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(function () {
|
||||
$(document).ready(function () {
|
||||
@@ -19,7 +228,11 @@ uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
|
||||
$(".login_btn").click(function () {
|
||||
//Swal.fire("userId : "+$("#userId").val()+", password : "+$("#password").val());
|
||||
login();
|
||||
$(this).addClass('loading').text('로그인 중...');
|
||||
$("#loadingBar").addClass('active');
|
||||
setTimeout(function() {
|
||||
login();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
$("#userId, #password").keypress(function (event) {
|
||||
@@ -42,76 +255,55 @@ uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 로딩바 -->
|
||||
<div class="loading-bar" id="loadingBar"></div>
|
||||
|
||||
<div id="loginBack_ilshin">
|
||||
<form name="loginForm" id="loginForm" method="post">
|
||||
<div class="login_layout">
|
||||
<div class="logo_slogan_box">
|
||||
<div class="slogun_box_ilshin"></div>
|
||||
</div>
|
||||
<div id="loginWrap">
|
||||
<div id="login_box">
|
||||
<a class="loginLogo_ilshin"></a>
|
||||
<label for="userId" class="userId">ID</label>
|
||||
<input
|
||||
type="text"
|
||||
id="userId"
|
||||
name="userId"
|
||||
value="plm_admin"
|
||||
placeholder="USER ID"
|
||||
/>
|
||||
<label for="userPw" class="userPw">PWD</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
value="qlalfqjsgh11"
|
||||
placeholder="PASSWORD"
|
||||
/>
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
/* border: 1px solid #ffffff80; */
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
width: 278px;
|
||||
height: 28px;
|
||||
color: #000;
|
||||
margin-top: 9px;
|
||||
"
|
||||
class="radio-group"
|
||||
>
|
||||
<!-- <input type="radio" name="chk_info" value="우성에스이" checked="checked" style="
|
||||
width: 14px;
|
||||
margin-left: 6px;
|
||||
margin-top: -3px;
|
||||
margin-right: 5px;
|
||||
"><div id="radio-name">우성에스이</div>
|
||||
<input type="radio" name="chk_info" value="성하" style="
|
||||
margin-left: 14px;
|
||||
width: 14px;
|
||||
margin-top: -3px;
|
||||
margin-right: 5px;
|
||||
"><div id="radio-name">성하엔지니어링</div>
|
||||
<input type="radio" name="chk_info" value="현준엔지니어링" style="
|
||||
width: 14px;
|
||||
margin-left: 17px;
|
||||
margin-top: -3px;
|
||||
margin-right: 5px;
|
||||
"><div id="radio-name">외주</div>
|
||||
-->
|
||||
</div>
|
||||
<!--
|
||||
<select name="lang" class="userId">
|
||||
<option value="ko">한국어</option>
|
||||
<option value="en">영어</option>
|
||||
<option value="jp">일본어</option>
|
||||
</select> -->
|
||||
|
||||
<input type="button" value="login" class="login_btn" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 상단 로고 -->
|
||||
<div class="company-logo"></div>
|
||||
|
||||
<div class="login_layout">
|
||||
<div class="logo_slogan_box">
|
||||
<div class="login-title">로그인</div>
|
||||
<div class="login-subtitle">계정 정보를 입력해주세요</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form name="loginForm" id="loginForm" method="post">
|
||||
<div class="form-group">
|
||||
<label class="form-label">사용자 ID</label>
|
||||
<input
|
||||
type="text"
|
||||
id="userId"
|
||||
name="userId"
|
||||
value="plm_admin"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">비밀번호</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
value="qlalfqjsgh11"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="radio-group">
|
||||
<!-- 기존 라디오 버튼들 숨김 처리 -->
|
||||
</div>
|
||||
|
||||
<input type="button" value="로그인" class="login_btn" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 하단 푸터 -->
|
||||
<div class="footer-text">
|
||||
© 2025 RPS. All rights reserved.<br>
|
||||
Powered by RPS
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
<frameset cols="197px,1px,*" border="0" id="parentsObj">
|
||||
|
||||
<frame src="/main/menu.do" name="menu_page"/>
|
||||
<frame src="/main/toggle.do" name="fToggle" style="border-right: 1px solid #b4b4b4;" scrolling="no"/>
|
||||
<frame src="/main/mainContents.do" name="contents_page" />
|
||||
<!--
|
||||
<frame src="/dashboard/dashboardMyTask.do" name="contents_page" />
|
||||
|
||||
<frame src="/dashboard/dashboard.do" name="contents_page" />
|
||||
<frameset cols="197px,14px,*" border="0" id="parentsObj">
|
||||
<frame src="/main/menu.do" name="menu_page">
|
||||
<frame src="/main/toggle.do" name="toggle_page"/>
|
||||
<frame src="/main/mainContents.do" name="contents_page"/>
|
||||
-->
|
||||
</frameset>
|
||||
|
||||
<!--
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
parent.frames["headerFS"].fn_goMyTask();
|
||||
});
|
||||
</script>
|
||||
-->
|
||||
@@ -11,7 +11,7 @@ ArrayList userMenuList = new ArrayList();
|
||||
userMenuList = (ArrayList)request.getAttribute("userMenuList");
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html style="height: 100%; overflow: hidden; margin: 0; padding: 0;">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%=Constants.SYSTEM_NAME %></title>
|
||||
@@ -26,17 +26,25 @@ userMenuList = (ArrayList)request.getAttribute("userMenuList");
|
||||
}
|
||||
*/
|
||||
.menu_off{
|
||||
color:#000;
|
||||
font-size:14px;
|
||||
font-weight:normal;
|
||||
color:#fff !important; padding: 2px 3px; font-size:9px; background-color:#0011ff; border-radius:2px;
|
||||
display: inline-block; min-width: 40px; text-align: center; margin: 0px;
|
||||
transition: all 0.3s ease; text-decoration: none !important; border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu_on{
|
||||
color:#B3A7A7;
|
||||
font-size:15px;
|
||||
font-weight:bold;
|
||||
color:#333 !important; padding: 2px 3px; font-size:9px; background-color:#d0d0d0; border-radius:2px;
|
||||
display: inline-block; min-width: 40px; text-align: center; margin: 0px;
|
||||
transition: all 0.3s ease; text-decoration: none !important; border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu_off:hover {
|
||||
background-color: #003399 !important;
|
||||
text-decoration: none !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/css/basic.css">
|
||||
|
||||
<script src="/js/jquery-1.11.3.min.js"></script>
|
||||
<script src="/js/html5shiv.js"></script>
|
||||
<!-- //datepicker -->
|
||||
@@ -83,16 +91,51 @@ $(function(){
|
||||
fn_registDetailPopup(userId);
|
||||
});
|
||||
|
||||
$(".menu").click(function(){
|
||||
var menuObjid = $(this).attr("menuObjid");
|
||||
|
||||
$(".menu_on").removeClass('menu_on').addClass('menu_off'); //이전 클릭한 메뉴 원복
|
||||
$(this).removeClass('menu_off');
|
||||
$(this).addClass('menu_on');
|
||||
$(".menu").click(function(){
|
||||
// 모든 메뉴를 off 스타일로 변경
|
||||
$(".menu").css({
|
||||
'background-color': '#0011ff',
|
||||
'color': '#fff'
|
||||
}).removeClass('menu_on').addClass('menu_off');
|
||||
|
||||
// 클릭된 메뉴를 on 스타일로 변경
|
||||
$(this).css({
|
||||
'background-color': '#d0d0d0',
|
||||
'color': '#333'
|
||||
}).removeClass('menu_off').addClass('menu_on');
|
||||
|
||||
var menuObjid = $(this).attr("menuObjId");
|
||||
|
||||
// 안전하게 메뉴 처리
|
||||
try {
|
||||
if(parent.frames["contentsFS"] && parent.frames["contentsFS"].frames["menu_page"]) {
|
||||
var menuFrame = parent.frames["contentsFS"].frames["menu_page"];
|
||||
if(menuFrame.fn_initMenuArea && menuFrame.add_menu) {
|
||||
menuFrame.fn_initMenuArea();
|
||||
menuFrame.add_menu(menuObjid);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Menu frame not ready:", e);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
parent.frames["contentsFS"].frames["menu_page"].fn_initMenuArea();
|
||||
parent.frames["contentsFS"].frames["menu_page"].add_menu(menuObjid);
|
||||
});
|
||||
// 메뉴 hover 효과
|
||||
$(".menu").hover(
|
||||
function() {
|
||||
if (!$(this).hasClass('menu_on')) {
|
||||
$(this).css('background-color', '#003399');
|
||||
}
|
||||
},
|
||||
function() {
|
||||
if (!$(this).hasClass('menu_on')) {
|
||||
$(this).css('background-color', '#0011ff');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
$(".btnApprovalList").click(function(){
|
||||
fn_goMyTaskMyApproval();
|
||||
@@ -162,7 +205,31 @@ function fn_goFirstMenu(){
|
||||
if($(".menu") && $(".menu").eq(0)){
|
||||
var menuObjId = $(".menu").eq(0).attr("menuObjId");
|
||||
//alert(menuObjId); -84984128(scm)
|
||||
fn_goMenu(menuObjId);
|
||||
|
||||
// 모든 메뉴를 off 스타일로 변경
|
||||
$(".menu").css({
|
||||
'background-color': '#0011ff',
|
||||
'color': '#fff'
|
||||
}).removeClass('menu_on').addClass('menu_off');
|
||||
|
||||
// 첫 번째 메뉴를 on 스타일로 변경
|
||||
$(".menu").eq(0).css({
|
||||
'background-color': '#d0d0d0',
|
||||
'color': '#333'
|
||||
}).removeClass('menu_off').addClass('menu_on');
|
||||
|
||||
// 안전하게 메뉴 처리
|
||||
try {
|
||||
if(parent.frames["contentsFS"] && parent.frames["contentsFS"].frames["menu_page"]) {
|
||||
var menuFrame = parent.frames["contentsFS"].frames["menu_page"];
|
||||
if(menuFrame.fn_initMenuArea && menuFrame.add_menu) {
|
||||
menuFrame.fn_initMenuArea();
|
||||
menuFrame.add_menu(menuObjId);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Menu frame not ready:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
function fn_goMyTask(subMenuObjid, onlyViewMenu){
|
||||
@@ -175,37 +242,43 @@ function fn_goDashboard(subMenuObjid, onlyViewMenu){
|
||||
fn_goMenu(menuobjid, subMenuObjid, onlyViewMenu);
|
||||
}
|
||||
function sel_menu(menuobjid, subMenuObjid, onlyViewMenu){
|
||||
parent.frames["contentsFS"].frames["menu_page"].sel_menu(menuobjid, subMenuObjid, onlyViewMenu);
|
||||
// 왼쪽 프레임 제거로 인해 더 이상 사용하지 않음
|
||||
// parent.frames["contentsFS"].frames["menu_page"].sel_menu(menuobjid, subMenuObjid, onlyViewMenu);
|
||||
console.log("sel_menu 호출됨 - 드롭다운 메뉴 방식으로 변경됨");
|
||||
}
|
||||
function fn_goMenu(menuobjid, subMenuObjid, onlyViewMenu){
|
||||
|
||||
if(fnc_isEmpty(menuobjid)){
|
||||
return;
|
||||
}
|
||||
//$(".menu[menuobjid="+menuobjid+"]").trigger("click");
|
||||
|
||||
fn_selTopMenu(menuobjid);
|
||||
|
||||
/*
|
||||
if(parent && parent.parent && parent.parent.frames["headerFS"] && typeof(parent.parent.frames["headerFS"].fn_goMyTask) == "function" ){
|
||||
parent.parent.frames["headerFS"].fn_goMyTask();
|
||||
}
|
||||
*/
|
||||
// 드롭다운 메뉴 방식으로 변경 - 왼쪽 프레임 제거됨
|
||||
// 메뉴 클릭시 해당 메뉴의 첫 번째 하위 메뉴로 이동하거나 기본 페이지로 이동
|
||||
$(".menu[menuObjId='" + menuobjid + "']").trigger("click");
|
||||
|
||||
/* 기존 왼쪽 프레임 방식 제거
|
||||
parent.frames["contentsFS"].frames["menu_page"].fn_initMenuArea();
|
||||
parent.frames["contentsFS"].frames["menu_page"].add_menu(menuobjid, subMenuObjid, onlyViewMenu);
|
||||
|
||||
//top.frames["contentsFS"].frames["menu_page"].fn_initMenuArea();
|
||||
//top.frames["contentsFS"].frames["menu_page"].add_menu(menuobjid, subMenuObjid, onlyViewMenu);
|
||||
*/
|
||||
}
|
||||
|
||||
var menuLoaded = false;
|
||||
|
||||
function fn_firstCallMenu(){
|
||||
if( parent
|
||||
&& parent.frames["contentsFS"]
|
||||
&& parent.frames["contentsFS"].frames["menu_page"]
|
||||
&& parent.frames["contentsFS"].frames["menu_page"].fn_initMenuArea ){
|
||||
//fn_goMyTask();
|
||||
//alert('1');
|
||||
fn_goFirstMenu();
|
||||
clearInterval(_intervalId);
|
||||
// 이미 로드되었으면 중복 실행 방지
|
||||
if(menuLoaded) return;
|
||||
|
||||
// 왼쪽 프레임이 복구되었으므로 기존 방식으로 첫 번째 메뉴 호출
|
||||
if(parent && parent.frames["contentsFS"] && parent.frames["contentsFS"].frames["menu_page"]){
|
||||
// 메뉴 프레임이 완전히 로드될 때까지 기다림
|
||||
var menuFrame = parent.frames["contentsFS"].frames["menu_page"];
|
||||
if(menuFrame.fn_initMenuArea && menuFrame.add_menu) {
|
||||
fn_goFirstMenu();
|
||||
clearInterval(_intervalId);
|
||||
menuLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +332,7 @@ function openAdminMngPop(){
|
||||
window.open("/admin/adminMainFS.do","<%=Constants.SYSTEM_NAME %>","width=1630,height=950,menuBar=no,status=no");
|
||||
}
|
||||
|
||||
|
||||
//결재건수조회
|
||||
function fn_setApprovalCnt(){
|
||||
$.ajax({
|
||||
@@ -285,72 +359,63 @@ function fn_setApprovalCnt(){
|
||||
</script>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
<body style="height:100%;overflow-y: hidden;">
|
||||
<body style="height:100%;overflow: hidden; margin: 0; padding: 0;">
|
||||
<form name="HeaderForm" action="" method="post">
|
||||
<input type="hidden" name="action" id="action">
|
||||
|
||||
<header>
|
||||
<div style="height:35px;">
|
||||
<header style="background-color: #fff; border-bottom: 1px solid #ddd; padding: 0; height: 50px; overflow: hidden;">
|
||||
<div style="height:50px; display: flex; align-items: center;">
|
||||
|
||||
<h1><a href="#" id="logo" class="mainLogo_new"></a></h1>
|
||||
<h1 style="margin: 0; padding: 0 20px;"><a href="#" id="logo" class="mainLogo_new"></a></h1>
|
||||
|
||||
<table>
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<colgroup>
|
||||
<col width="*%"/>
|
||||
<col width="*%"/>
|
||||
<col width="*%"/>
|
||||
<col width="*%"/>
|
||||
<col width="*%"/>
|
||||
<col width="*"/>
|
||||
<col width="400px"/>
|
||||
</colgroup>
|
||||
<tr>
|
||||
<tr style="height: 50px; vertical-align: middle;">
|
||||
|
||||
<%
|
||||
for(int i=0;i<userMenuList.size();i++){
|
||||
HashMap menuMap = (HashMap)userMenuList.get(i);
|
||||
String menuDesc = CommonUtils.checkNull(menuMap.get("MENU_DESC"));
|
||||
String menuKorName = CommonUtils.checkNull(menuMap.get("MENU_NAME_KOR"));
|
||||
String menuObjid = CommonUtils.checkNull(menuMap.get("OBJID"));
|
||||
String parentObjid = CommonUtils.checkNull(menuMap.get("PARENT_OBJ_ID"));
|
||||
String menuUrl = CommonUtils.checkNull(menuMap.get("MENU_URL"));
|
||||
String lev = CommonUtils.checkNull(menuMap.get("LEV"));
|
||||
/* String menuSeq = CommonUtils.checkNull(menuMap.get("SEQ")); */
|
||||
/* String menuMaxSeq = CommonUtils.checkNull(menuMap.get("MAX_SEQ"));
|
||||
String menuMinSeq = CommonUtils.checkNull(menuMap.get("MIN_SEQ")); */
|
||||
|
||||
if("2".equals(lev)){
|
||||
%>
|
||||
<%--
|
||||
<td style=""><a href="#" style="" class="menu menu_off" menuObjId="<%=menuObjid%>"><%=menuKorName%></a></td>
|
||||
<div class="main_menu" menuObjId="<%=menuObjid%>"><span><a href="#" url="<%=menuUrl%>" objType="menuObj" menuObjId="<%=menuObjid%>"><%=menuKorName%></a></span></div>
|
||||
--%>
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
<td class="work_notice" style="position:relative;">
|
||||
<span id="blink" style="padding: 2px 10px 5px 10px;border-radius:0;" class="btnApprovalList blink_none">
|
||||
<span class="bell_back"><img src="" height='20' width='20' /></span>
|
||||
<label class="notice_no">0</label> 개의 결재가 있습니다.</span>
|
||||
</td>
|
||||
|
||||
<!--
|
||||
<td style="font-size:11px; "><a href="#" onclick="javascript:fn_openBoardList('notice');" style="color:#fff;background-color:#676868; border-radius:0; padding:4px 10px 5px 10px;">공지사항</a></td>
|
||||
-->
|
||||
<td style="font-size:11px; "><a href="#" onclick="javascript:fn_openBoardList('qna');" style="color:#fff;background-color:#676868; border-radius:0; padding:4px 10px 5px 10px;">Q&A</a></td>
|
||||
<td style="font-size:11px; "><a href="#" id="manualDownload" style="color:#fff;background-color:#676868; border-radius:0; padding:4px 10px 5px 10px;">Manual Download</a></td>
|
||||
<%--
|
||||
<td class="admin"><%if("plm_admin".equals(userId)){%><a href="#" onclick="javascript:openAdminMngPop();" style="color:#fff; padding: 5px 10px; font-size:11px; background-color:#75a0b6; border-radius:3px;">Admin</a><%}%></td>
|
||||
<td class="admin"><a href="#" class="" data-USER_ID="<%=userId %>"><img src="/images/top-icon05.png"><%=person.getDeptName() %> <%=person.getUserName() %> <%=person.getPositionName() %></a></td>
|
||||
--%>
|
||||
<td class="crew" style="">
|
||||
<a href="#" class="btnDetail" data-USER_ID="<%=userId %>">
|
||||
<span style=" color:#fff; padding: 4.5px 10px; font-size:11px; background-color:#676868; border-radius:0;">
|
||||
<!-- 메뉴 영역 -->
|
||||
<td style="text-align: left; padding-left: 10px;">
|
||||
<%
|
||||
for(int i=0;i<userMenuList.size();i++){
|
||||
HashMap menuMap = (HashMap)userMenuList.get(i);
|
||||
String menuDesc = CommonUtils.checkNull(menuMap.get("MENU_DESC"));
|
||||
String menuKorName = CommonUtils.checkNull(menuMap.get("MENU_NAME_KOR"));
|
||||
String menuObjid = CommonUtils.checkNull(menuMap.get("OBJID"));
|
||||
String parentObjid = CommonUtils.checkNull(menuMap.get("PARENT_OBJ_ID"));
|
||||
String menuUrl = CommonUtils.checkNull(menuMap.get("MENU_URL"));
|
||||
String lev = CommonUtils.checkNull(menuMap.get("LEV"));
|
||||
/* String menuSeq = CommonUtils.checkNull(menuMap.get("SEQ")); */
|
||||
/* String menuMaxSeq = CommonUtils.checkNull(menuMap.get("MAX_SEQ"));
|
||||
String menuMinSeq = CommonUtils.checkNull(menuMap.get("MIN_SEQ")); */
|
||||
|
||||
if("2".equals(lev)){
|
||||
%>
|
||||
<a href="#" class="menu menu_off" menuObjId="<%=menuObjid%>" style="background-color: #0015ff; color: #fff; padding: 3px 6px; font-size: 10px; border-radius: 3px; text-decoration: none; display: inline-block; min-width: 50px; text-align: center; margin-right: 4px;"><%=menuKorName%></a>
|
||||
<%
|
||||
}
|
||||
}
|
||||
%>
|
||||
</td>
|
||||
|
||||
<!-- 우측 버튼 영역 -->
|
||||
<td style="text-align: right; padding-right: 10px;">
|
||||
<span id="blink" style="padding: 3px 6px; border-radius:3px; font-size:10px; background-color:#ff6b35; color:#fff; cursor:pointer; margin-right: 5px;" class="btnApprovalList blink_none">
|
||||
결재 <label class="notice_no">0</label>건</span>
|
||||
|
||||
<a href="#" onclick="javascript:fn_openBoardList('qna');" style="color:#fff;background-color:#676868; border-radius:2px; padding:2px 4px; text-decoration: none; display: inline-block; font-size:9px; margin-right: 5px;">Q&A</a>
|
||||
|
||||
<a href="#" id="manualDownload" style="color:#fff;background-color:#676868; border-radius:2px; padding:2px 4px; text-decoration: none; display: inline-block; font-size:9px; margin-right: 5px;">Manual Download</a>
|
||||
|
||||
<a href="#" class="btnDetail" data-USER_ID="<%=userId %>" style="text-decoration: none; margin-right: 5px;">
|
||||
<span style="color:#fff; padding: 2px 4px; font-size:9px; background-color:#676868; border-radius:2px; display: inline-block;">
|
||||
<%=person.getDeptName() %> <%=person.getUserName() %> <%=person.getPositionName() %>
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
<td style=""><a href="#" style="color:#fff; padding: 4.5px 10px; font-size:11px; background-color:#676868; border-radius:0;" class="btnLogout">Logout</a></td>
|
||||
|
||||
<a href="#" style="color:#fff; padding: 2px 4px; font-size:9px; background-color:#676868; border-radius:2px; text-decoration: none; display: inline-block;" class="btnLogout">Logout</a>
|
||||
</td>
|
||||
<%--
|
||||
<td style=""><a href="#" id="manualDownload" style="color:#fff; padding: 5px 10px; font-size:11px; background-color:#38426b; border-radius:3px;">Manual Download</a></td>
|
||||
<td class="admin"><%if("plm_admin".equals(userId)){%><a href="#" onclick="javascript:openAdminMngPop();" style="color:#fff; padding: 5px 10px; font-size:11px; background-color:#75a0b6; border-radius:3px;">Admin</a><%}%></td>
|
||||
@@ -384,8 +449,10 @@ function fn_setApprovalCnt(){
|
||||
if("2".equals(lev)){
|
||||
%>
|
||||
<li class="" data-menu-id="417" data-menu-target="Current" data-menu-alias="" data-menu-alias2="" data-menu-url="">
|
||||
<a href="#" style="" class="menu menu_off" menuObjId="<%=menuObjid%>"><%=menuKorName%></a>
|
||||
<%-- <div class="main_menu" menuObjId="<%=menuObjid%>"><span><a href="#" url="<%=menuUrl%>" objType="menuObj" menuObjId="<%=menuObjid%>"><%=menuKorName%></a></span></div> --%>
|
||||
<a href="#" class="menu menu_off waves-effect waves-light" menuObjId="<%=menuObjid%>">
|
||||
<span><%=menuKorName%></span>
|
||||
</a>
|
||||
<%-- 하위 메뉴는 Materialize 드롭다운으로 동적 로드됨 --%>
|
||||
</li>
|
||||
<%
|
||||
}
|
||||
|
||||
@@ -28,13 +28,46 @@
|
||||
*/
|
||||
color:#373740; /* dark gray로 변경 */
|
||||
font-size:13px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.menus_on{
|
||||
color:#B3A7A7;
|
||||
font-size:13.1px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.smenu{
|
||||
font-weight:bold;
|
||||
font-weight:bold;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 메뉴 hover 효과 */
|
||||
.main_menu:hover .smenu,
|
||||
.menu2:hover .smenu {
|
||||
color: #1159bc !important;
|
||||
background-color: rgba(17, 89, 188, 0.1);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* 메뉴 컨테이너 스타일 */
|
||||
#menu {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
/* 메뉴 아이템 애니메이션 */
|
||||
.main_menu, .menu2 {
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.main_menu:hover, .menu2:hover {
|
||||
background-color: rgba(245, 245, 245, 0.8);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* 메뉴 영역 전체 스타일 */
|
||||
body {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -85,6 +118,31 @@ $(function(){
|
||||
//var firstLink = $('#menu a').first();
|
||||
fnm_changeContentsLocation($(this).attr("url"), $(this).attr("menuObjId"), this);
|
||||
});
|
||||
|
||||
// 메뉴 영역에서 마우스가 벗어났을 때 자동 숨김 (애니메이션 적용)
|
||||
var hideMenuTimer;
|
||||
$(document).mouseleave(function(e) {
|
||||
// 마우스가 메뉴 프레임을 벗어났을 때
|
||||
clearTimeout(hideMenuTimer);
|
||||
hideMenuTimer = setTimeout(function() {
|
||||
try {
|
||||
if(parent && parent.frames && parent.frames["toggle_page"]) {
|
||||
var toggleFrame = parent.frames["toggle_page"];
|
||||
if(toggleFrame.fntg_changeSizeWithAnimation) {
|
||||
toggleFrame.fntg_changeSizeWithAnimation();
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Toggle frame not accessible:", e);
|
||||
}
|
||||
}, 500); // 1.5초 후 자동 숨김
|
||||
});
|
||||
|
||||
// 메뉴 영역에 마우스가 다시 들어왔을 때 타이머 취소
|
||||
$(document).mouseenter(function() {
|
||||
clearTimeout(hideMenuTimer);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,6 +151,7 @@ function fn_alert(){
|
||||
}
|
||||
function fn_initMenuArea(){
|
||||
$("#menu").empty();
|
||||
$('#forced-menu').remove(); // 강제로 추가된 메뉴도 제거
|
||||
}
|
||||
|
||||
function fnm_changeContentsLocation(url, menuObjId, obj){
|
||||
@@ -124,6 +183,7 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
|
||||
var menu ="";
|
||||
if(fnc_isNotEmpty(objid)){
|
||||
//console.log("objid가 비어있지 않음, AJAX 호출 시작");
|
||||
$.ajax({
|
||||
url:"/main/getmenu.do",
|
||||
type:"POST",
|
||||
@@ -131,7 +191,9 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
dataType:"json",
|
||||
async:false,
|
||||
success:function(data){
|
||||
if(data.RESULT.length>0){
|
||||
//console.log("AJAX 응답 성공:", data);
|
||||
if(data.RESULT && data.RESULT.length>0){
|
||||
//console.log("메뉴 아이템 개수:", data.RESULT.length);
|
||||
for(var i=0;i<data.RESULT.length;i++){
|
||||
//menu +="<div class='main_menu' menuObjId="+data.RESULT[i].OBJID+"><span><a href='javascript:fnm_changeContentsLocation(\""+data.RESULT[i].MENU_URL+"\",\""+data.RESULT[i].OBJID+"\")' url='"+data.RESULT[i].MENU_URL+"' objType='menuObj' menuObjId='"+data.RESULT[i].OBJID+"'>"+data.RESULT[i].MENU_NAME_KOR+"</a></span></div>";
|
||||
/*
|
||||
@@ -141,30 +203,145 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
}else{
|
||||
*/
|
||||
var lev = data.RESULT[i].LEVEL;
|
||||
var menuClass = "main_menu";
|
||||
var menuClass = "main_menu"; // 모든 메뉴를 main_menu로 생성
|
||||
var menuUrl = fnc_checkNull(data.RESULT[i].MENU_URL);
|
||||
|
||||
//console.log(lev);
|
||||
|
||||
|
||||
if(fnc_isNotEmpty(lev) && Number(lev) < 2){
|
||||
menuClass = "main_menu";
|
||||
menu +="<div class='"+menuClass+"' menuObjId="+data.RESULT[i].OBJID+" parentObjid="+data.RESULT[i].PARENT_OBJ_ID+"><span><a href='javascript:fnm_changeContentsLocation(\""+data.RESULT[i].MENU_URL+"\",\""+data.RESULT[i].OBJID+"\", this)' class='smenu menus_off' url='"+data.RESULT[i].MENU_URL+"' objType='menuObj' menuObjId='"+data.RESULT[i].OBJID+"'>"+data.RESULT[i].MENU_NAME_KOR+"</a></span></div>";
|
||||
}else{
|
||||
menuClass = "menu2";
|
||||
menu +="<div class='"+menuClass+"' menuObjId="+data.RESULT[i].OBJID+" parentObjid="+data.RESULT[i].PARENT_OBJ_ID+"><span><a href='javascript:fnm_changeContentsLocation(\""+data.RESULT[i].MENU_URL+"\",\""+data.RESULT[i].OBJID+"\", this)' class='smenu menus_off' url='"+data.RESULT[i].MENU_URL+"' objType='menuObj' menuObjId='"+data.RESULT[i].OBJID+"'>"+data.RESULT[i].MENU_NAME_KOR+"</a></span></div>";
|
||||
menu +="<div class='"+menuClass+"' menuObjId="+data.RESULT[i].OBJID+" parentObjid="+data.RESULT[i].PARENT_OBJ_ID+"><span><a href='javascript:fnm_changeContentsLocation(\""+data.RESULT[i].MENU_URL+"\",\""+data.RESULT[i].OBJID+"\", this)' class='smenu menus_off' url='"+data.RESULT[i].MENU_URL+"' objType='menuObj' menuObjId='"+data.RESULT[i].OBJID+"'>"+data.RESULT[i].MENU_NAME_KOR+"</a></span></div>";
|
||||
}
|
||||
|
||||
// console.log("메뉴 생성:", data.RESULT[i].MENU_NAME_KOR, "Level:", lev);
|
||||
//menu +="<div class='main_menu' menuObjId="+data.RESULT[i].OBJID+"><span><a href='' class='smenu menus_off' url='"+data.RESULT[i].MENU_URL+"' objType='menuObj' menuObjId='"+data.RESULT[i].OBJID+"'>"+data.RESULT[i].MENU_NAME_KOR+"</a></span></div>";
|
||||
//}
|
||||
}
|
||||
}
|
||||
//console.log("생성된 메뉴 HTML 길이:", menu.length);
|
||||
//console.log("생성된 메뉴 HTML:", menu.substring(0, 200) + "...");
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.log("AJAX 오류:", error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//console.log("objid가 비어있음, sel_menu 호출");
|
||||
}
|
||||
|
||||
console.log("DOM 추가 전 - 메뉴 HTML 길이:", menu.length);
|
||||
|
||||
// 기존 메뉴 완전히 제거
|
||||
$("#menu").empty();
|
||||
$('#forced-menu').remove(); // 강제로 추가된 메뉴도 제거
|
||||
|
||||
$('#menu').addClass('clickable');
|
||||
$("#menu").append(menu);
|
||||
|
||||
// 메뉴를 강제로 표시 (원래 위치에 맞게)
|
||||
if(menu.length > 0) {
|
||||
// 기존 강제 메뉴가 있다면 제거
|
||||
$('#forced-menu').remove();
|
||||
|
||||
// 기존 메뉴 프레임의 위치 정보 가져오기
|
||||
var menuFrame = window.frameElement;
|
||||
var frameRect = menuFrame ? menuFrame.getBoundingClientRect() : {left: 0, top: 0};
|
||||
|
||||
// body에 메뉴 추가 (원래 디자인에 맞게)
|
||||
$('body').append('<div id="forced-menu" style="position:absolute; top:10px; left:25px; background:white; padding:0; z-index:1000; width:170px; border:none;">' + menu + '</div>');
|
||||
|
||||
// 메뉴 아이템 스타일 적용 (원래 디자인)
|
||||
$('#forced-menu .main_menu').css({
|
||||
'display': 'block',
|
||||
'padding': '0',
|
||||
'margin': '0',
|
||||
'cursor': 'pointer',
|
||||
'border': 'none',
|
||||
'background': 'transparent',
|
||||
'width': '100%'
|
||||
});
|
||||
|
||||
// 메뉴 앞에 화살표 아이콘 추가
|
||||
$('#forced-menu .main_menu').each(function() {
|
||||
var $link = $(this).find('.smenu');
|
||||
var linkText = $link.text();
|
||||
$link.html('▶ ' + linkText);
|
||||
});
|
||||
|
||||
// 메뉴 링크 스타일 (원래 디자인)
|
||||
$('#forced-menu .main_menu .smenu').css({
|
||||
'display': 'block',
|
||||
'padding': '8px 10px',
|
||||
'color': '#373740',
|
||||
'font-size': '13px',
|
||||
'text-decoration': 'none',
|
||||
'border-bottom': '1px solid #eee',
|
||||
'transition': 'color 0.3s ease'
|
||||
});
|
||||
|
||||
// 메뉴 hover 효과 (원래 디자인)
|
||||
$('#forced-menu .main_menu').hover(
|
||||
function() {
|
||||
$(this).find('.smenu').css({
|
||||
'color': '#1159bc',
|
||||
'background-color': 'rgba(17, 89, 188, 0.1)'
|
||||
});
|
||||
},
|
||||
function() {
|
||||
$(this).find('.smenu').css({
|
||||
'color': '#373740',
|
||||
'background-color': 'transparent'
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
console.log("강제 메뉴 표시 완료");
|
||||
}
|
||||
|
||||
console.log("DOM 추가 완료");
|
||||
|
||||
// 메뉴 컨테이너도 보이도록 설정
|
||||
$('#menu').css({
|
||||
'display': 'block !important',
|
||||
'visibility': 'visible !important',
|
||||
'opacity': '1 !important',
|
||||
'position': 'static !important',
|
||||
'top': 'auto !important',
|
||||
'left': 'auto !important',
|
||||
'margin-top': '10px !important',
|
||||
'height': 'auto !important',
|
||||
'min-height': '200px !important',
|
||||
'overflow': 'visible !important',
|
||||
'z-index': '9999 !important'
|
||||
});
|
||||
console.log("메뉴 컨테이너 CSS 설정 완료");
|
||||
|
||||
// 메뉴가 그려진 후 main_menu는 보이게 하고, menu2는 숨김
|
||||
$(".main_menu").show().css({
|
||||
'display': 'block !important',
|
||||
'visibility': 'visible !important',
|
||||
'opacity': '1 !important',
|
||||
'position': 'relative !important',
|
||||
'margin': '2px 0 !important',
|
||||
'padding': '5px !important',
|
||||
'height': 'auto !important',
|
||||
'width': '100% !important',
|
||||
'cursor': 'pointer !important'
|
||||
});
|
||||
$(".menu2").hide();
|
||||
|
||||
console.log("메뉴 요소 개수 확인:");
|
||||
console.log("- #menu 요소:", $('#menu').length);
|
||||
console.log("- .main_menu 요소:", $('.main_menu').length);
|
||||
console.log("- .menu2 요소:", $('.menu2').length);
|
||||
console.log("메뉴 가시성 확인:");
|
||||
console.log("- #menu visible:", $('#menu').is(':visible'));
|
||||
console.log("- .main_menu visible:", $('.main_menu').is(':visible'));
|
||||
console.log("메뉴 위치 정보:", $('#menu').offset());
|
||||
console.log("메뉴 크기:", $('#menu').width(), "x", $('#menu').height());
|
||||
|
||||
//var firstLink = $('#menu a').first();
|
||||
//fnm_changeContentsLocation(firstLink.attr("url"));
|
||||
|
||||
@@ -191,13 +368,31 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
fnm_changeContentsLocation(url, menuObjId, this);
|
||||
|
||||
if(url.toUpperCase().indexOf('/DASHBOARD.DO') > -1){ //대시보드 전체화면
|
||||
parent.frames["fToggle"].fntg_changeSizeS();
|
||||
try {
|
||||
if(parent && parent.frames && parent.frames["toggle_page"]) {
|
||||
parent.frames["toggle_page"].fntg_changeSizeS();
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Toggle frame error:", e);
|
||||
}
|
||||
}else{
|
||||
parent.frames["fToggle"].fntg_changeSizeM();
|
||||
try {
|
||||
if(parent && parent.frames && parent.frames["toggle_page"]) {
|
||||
parent.frames["toggle_page"].fntg_changeSizeM();
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Toggle frame error:", e);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//alert('bb');
|
||||
parent.frames["fToggle"].fntg_changeSizeM();
|
||||
try {
|
||||
if(parent && parent.frames && parent.frames["toggle_page"]) {
|
||||
parent.frames["toggle_page"].fntg_changeSizeM();
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Toggle frame error:", e);
|
||||
}
|
||||
var menu2 = $("[parentObjid="+menuObjId+"]")[0];
|
||||
smenu = $(menu2).find(".smenu");
|
||||
$(menu2).trigger("click");
|
||||
@@ -232,8 +427,23 @@ function add_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
}else{
|
||||
sel_menu(objid, subMenuObjid, onlyViewMenu);
|
||||
}
|
||||
|
||||
// 메뉴 그리기 완료 후 자동 숨김 처리 (애니메이션 적용)
|
||||
setTimeout(function() {
|
||||
try {
|
||||
if(parent && parent.frames && parent.frames["toggle_page"]) {
|
||||
var toggleFrame = parent.frames["toggle_page"];
|
||||
if(toggleFrame.fntg_changeSizeWithAnimation) {
|
||||
toggleFrame.fntg_changeSizeWithAnimation();
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.log("Toggle frame not accessible:", e);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
|
||||
function sel_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
|
||||
//Swal.fire("sel_menu - " + objid + ":" + subMenuObjid + ":" + onlyViewMenu);
|
||||
@@ -254,6 +464,7 @@ function sel_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body id="menuback_w" style="height:100%;overflow-y: hidden;">
|
||||
@@ -276,31 +487,8 @@ function sel_menu(objid, subMenuObjid, onlyViewMenu){
|
||||
<div style="float:left;width:20px;height:100%;background:#606060;">
|
||||
</div>
|
||||
|
||||
<div id="menu" style="float:;width:100%;margin-left:5px">
|
||||
<%-- <%
|
||||
for(int i=0;i<userMenuList.size();i++){
|
||||
HashMap menuMap = (HashMap)userMenuList.get(i);
|
||||
String menuDesc = CommonUtils.checkNull(menuMap.get("menu_desc"));
|
||||
String menuKorName = CommonUtils.checkNull(menuMap.get("menu_name_kor"));
|
||||
String menuObjid = CommonUtils.checkNull(menuMap.get("objid"));
|
||||
String parentObjid = CommonUtils.checkNull(menuMap.get("parent_obj_id"));
|
||||
String menuUrl = CommonUtils.checkNull(menuMap.get("menu_url"));
|
||||
String lev = CommonUtils.checkNull(menuMap.get("lev"));
|
||||
/* String menuSeq = CommonUtils.checkNull(menuMap.get("SEQ")); */
|
||||
/* String menuMaxSeq = CommonUtils.checkNull(menuMap.get("MAX_SEQ"));
|
||||
String menuMinSeq = CommonUtils.checkNull(menuMap.get("MIN_SEQ")); */
|
||||
|
||||
if("2".equals(lev)){
|
||||
%>
|
||||
<div class="main_menu" menuObjId="<%=menuObjid%>"><span><a href="#" url="<%=menuUrl%>" objType="menuObj" menuObjId="<%=menuObjid%>"><%=menuKorName%></a></span></div>
|
||||
<%
|
||||
}else if("3".equals(lev)){
|
||||
%>
|
||||
<div class="menu2" parentObjid="<%=parentObjid%>" menuType="12"><a href="#" url="<%=menuUrl%>" objType="menuObj" menuObjId="<%=menuObjid%>"><%=menuKorName%></a></div>
|
||||
<%
|
||||
}
|
||||
}
|
||||
%> --%>
|
||||
<div id="menu" style="float:left;width:100%;margin-left:5px">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -9,15 +9,45 @@
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<script>
|
||||
function fntg_changeSize(){
|
||||
var frameset = parent.document.getElementById('parentsObj');
|
||||
var frameVal = frameset.cols;
|
||||
var animating = false;
|
||||
|
||||
var frameVal = parent.document.getElementById('parentsObj').cols;
|
||||
if (animating) return;
|
||||
animating = true;
|
||||
|
||||
if("0px,8px,*" == frameVal){
|
||||
parent.document.getElementById('parentsObj').cols = "197px,8px,*";
|
||||
}else{
|
||||
parent.document.getElementById('parentsObj').cols = "0px,8px,*";
|
||||
var startWidth, endWidth;
|
||||
if("0px,14px,*" == frameVal || "0px,8px,*" == frameVal){
|
||||
startWidth = 0;
|
||||
endWidth = 197;
|
||||
} else {
|
||||
startWidth = 197;
|
||||
endWidth = 0;
|
||||
}
|
||||
|
||||
var duration = 300;
|
||||
var startTime = Date.now();
|
||||
|
||||
function animate() {
|
||||
var elapsed = Date.now() - startTime;
|
||||
var progress = Math.min(elapsed / duration, 1);
|
||||
|
||||
// easeInOut 이징
|
||||
progress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
|
||||
|
||||
var currentWidth = Math.round(startWidth + (endWidth - startWidth) * progress);
|
||||
var cols = currentWidth === 0 ? '0px,14px,*' : currentWidth + 'px,14px,*';
|
||||
|
||||
frameset.cols = cols;
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate);
|
||||
} else {
|
||||
animating = false;
|
||||
}
|
||||
}
|
||||
|
||||
animate();
|
||||
}
|
||||
|
||||
function fntg_changeSizeS(){
|
||||
@@ -28,6 +58,86 @@
|
||||
parent.document.getElementById('parentsObj').cols = "197px,1px,*";
|
||||
}
|
||||
|
||||
// 애니메이션과 함께 메뉴 숨기기
|
||||
function fntg_changeSizeWithAnimation(){
|
||||
var frameset = parent.document.getElementById('parentsObj');
|
||||
var frameVal = frameset.cols;
|
||||
var animating = false;
|
||||
|
||||
if (animating) return;
|
||||
animating = true;
|
||||
|
||||
// 현재 메뉴가 보이는 상태라면 숨김
|
||||
if(frameVal !== "0px,14px,*" && frameVal !== "0px,1px,*") {
|
||||
var startWidth = 197;
|
||||
var endWidth = 0;
|
||||
|
||||
var duration = 400;
|
||||
var startTime = Date.now();
|
||||
|
||||
function animate() {
|
||||
var elapsed = Date.now() - startTime;
|
||||
var progress = Math.min(elapsed / duration, 1);
|
||||
|
||||
// easeInOut 이징
|
||||
progress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
|
||||
|
||||
var currentWidth = Math.round(startWidth + (endWidth - startWidth) * progress);
|
||||
var cols = currentWidth === 0 ? '0px,14px,*' : currentWidth + 'px,14px,*';
|
||||
|
||||
frameset.cols = cols;
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate);
|
||||
} else {
|
||||
animating = false;
|
||||
}
|
||||
}
|
||||
|
||||
animate();
|
||||
}
|
||||
}
|
||||
|
||||
// 애니메이션과 함께 메뉴 보이기
|
||||
function fntg_showMenuWithAnimation(){
|
||||
var frameset = parent.document.getElementById('parentsObj');
|
||||
var frameVal = frameset.cols;
|
||||
var animating = false;
|
||||
|
||||
if (animating) return;
|
||||
animating = true;
|
||||
|
||||
// 현재 메뉴가 숨겨진 상태라면 보임
|
||||
if(frameVal === "0px,14px,*" || frameVal === "0px,1px,*") {
|
||||
var startWidth = 0;
|
||||
var endWidth = 197;
|
||||
|
||||
var duration = 400;
|
||||
var startTime = Date.now();
|
||||
|
||||
function animate() {
|
||||
var elapsed = Date.now() - startTime;
|
||||
var progress = Math.min(elapsed / duration, 1);
|
||||
|
||||
// easeInOut 이징
|
||||
progress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
|
||||
|
||||
var currentWidth = Math.round(startWidth + (endWidth - startWidth) * progress);
|
||||
var cols = currentWidth === 0 ? '0px,14px,*' : currentWidth + 'px,14px,*';
|
||||
|
||||
frameset.cols = cols;
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animate);
|
||||
} else {
|
||||
animating = false;
|
||||
}
|
||||
}
|
||||
|
||||
animate();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
$("#side1 img").hover(function() {
|
||||
@@ -36,6 +146,24 @@
|
||||
$(this).css("opacity","1").stop().attr("src", "/images/toggle.png");
|
||||
});
|
||||
|
||||
// 토글 영역에 마우스 오버 시 메뉴 표시 (애니메이션 적용)
|
||||
$("#side1").mouseenter(function() {
|
||||
fntg_showMenuWithAnimation();
|
||||
});
|
||||
|
||||
// 메뉴 영역에서 마우스가 벗어났을 때 다시 숨김 (선택적)
|
||||
// 필요에 따라 주석 해제하여 사용
|
||||
/*
|
||||
$(document).mouseleave(function(e) {
|
||||
// 마우스가 메뉴 영역을 완전히 벗어났을 때 숨김
|
||||
if(e.pageX < 220) return; // 메뉴 영역 너비 고려
|
||||
|
||||
setTimeout(function() {
|
||||
fntg_changeSizeS();
|
||||
}, 1000); // 1초 후 자동 숨김
|
||||
});
|
||||
*/
|
||||
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<frameset rows="78px,*" border="0">
|
||||
<frame src="/main/header.do" id="headerFS" name="headerFS">
|
||||
<frame src="/main/contentsFS.do" id="contentsFS" name="contentsFS">
|
||||
<frameset rows="51px,*" border="0" frameborder="0" framespacing="0">
|
||||
<frame src="/main/header.do" id="headerFS" name="headerFS" frameborder="0" marginwidth="0" marginheight="0" scrolling="no">
|
||||
<frame src="/main/contentsFS.do" id="contentsFS" name="contentsFS" frameborder="0" marginwidth="0" marginheight="0">
|
||||
</frameset>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
WebContent/images/company_stamp.png
Normal file
BIN
WebContent/images/company_stamp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
@@ -42,7 +42,6 @@ pageContext.setAttribute("newLineChar", "\n");
|
||||
<c:set var="isAdmin" value="<%=isAdmin%>" />
|
||||
<c:set var="menuObjId" value="${empty param.menuObjId?'':param.menuObjId}" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=11">
|
||||
|
||||
|
||||
<!-- //basic -->
|
||||
|
||||
86
database/estimate_template_tables.sql
Normal file
86
database/estimate_template_tables.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
-- 견적서 템플릿 테이블 생성 SQL
|
||||
|
||||
-- 1. 견적서 템플릿 메인 테이블
|
||||
CREATE TABLE IF NOT EXISTS ESTIMATE_TEMPLATE (
|
||||
OBJID SERIAL PRIMARY KEY,
|
||||
CONTRACT_OBJID NUMERIC NOT NULL, -- CONTRACT_MGMT 테이블의 OBJID 참조
|
||||
TEMPLATE_TYPE VARCHAR(10) NOT NULL, -- '1': 일반 견적서, '2': 장비 견적서
|
||||
|
||||
-- 일반 견적서 필드 (Template 1)
|
||||
EXECUTOR VARCHAR(200), -- 시행일자
|
||||
RECIPIENT VARCHAR(200), -- 수신처
|
||||
ESTIMATE_NO VARCHAR(100), -- 견적번호
|
||||
CONTACT_PERSON VARCHAR(100), -- 수신인
|
||||
GREETING_TEXT TEXT, -- 인사말
|
||||
|
||||
-- 장비 견적서 필드 (Template 2)
|
||||
MODEL_NAME VARCHAR(200), -- 설비 Model 품명
|
||||
MODEL_CODE VARCHAR(100), -- 설비 Model 코드
|
||||
EXECUTOR_DATE VARCHAR(50), -- 시행일자
|
||||
|
||||
-- 비고 필드 (공통)
|
||||
NOTE1 VARCHAR(500),
|
||||
NOTE2 VARCHAR(500),
|
||||
NOTE3 VARCHAR(500),
|
||||
NOTE4 VARCHAR(500),
|
||||
|
||||
-- 카테고리 정보 (장비 견적서용, JSON 형태로 저장)
|
||||
CATEGORIES_JSON TEXT,
|
||||
|
||||
-- 시스템 필드
|
||||
WRITER VARCHAR(50),
|
||||
REGDATE TIMESTAMP DEFAULT NOW(),
|
||||
CHG_USER_ID VARCHAR(50),
|
||||
CHGDATE TIMESTAMP DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT fk_estimate_contract FOREIGN KEY (CONTRACT_OBJID)
|
||||
REFERENCES CONTRACT_MGMT(OBJID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 인덱스 생성
|
||||
CREATE INDEX idx_estimate_contract ON ESTIMATE_TEMPLATE(CONTRACT_OBJID);
|
||||
CREATE INDEX idx_estimate_type ON ESTIMATE_TEMPLATE(TEMPLATE_TYPE);
|
||||
|
||||
-- 코멘트 추가
|
||||
COMMENT ON TABLE ESTIMATE_TEMPLATE IS '견적서 템플릿 정보';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.CONTRACT_OBJID IS '견적요청 OBJID (CONTRACT_MGMT 참조)';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.TEMPLATE_TYPE IS '템플릿 타입 (1:일반견적서, 2:장비견적서)';
|
||||
|
||||
|
||||
-- 2. 견적서 템플릿 품목 테이블
|
||||
CREATE TABLE IF NOT EXISTS ESTIMATE_TEMPLATE_ITEM (
|
||||
OBJID SERIAL PRIMARY KEY,
|
||||
TEMPLATE_OBJID NUMERIC NOT NULL, -- ESTIMATE_TEMPLATE 테이블의 OBJID 참조
|
||||
SEQ INTEGER NOT NULL, -- 순번
|
||||
CATEGORY VARCHAR(100), -- 카테고리 (장비 견적서용)
|
||||
DESCRIPTION VARCHAR(500), -- 품명
|
||||
SPECIFICATION TEXT, -- 규격/사양
|
||||
QUANTITY VARCHAR(50), -- 수량
|
||||
UNIT VARCHAR(50), -- 단위
|
||||
UNIT_PRICE NUMERIC(15,2), -- 단가
|
||||
AMOUNT NUMERIC(15,2), -- 금액
|
||||
NOTE VARCHAR(500), -- 비고
|
||||
REMARK VARCHAR(500), -- 특이사항
|
||||
|
||||
CONSTRAINT fk_item_template FOREIGN KEY (TEMPLATE_OBJID)
|
||||
REFERENCES ESTIMATE_TEMPLATE(OBJID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 인덱스 생성
|
||||
CREATE INDEX idx_item_template ON ESTIMATE_TEMPLATE_ITEM(TEMPLATE_OBJID);
|
||||
CREATE INDEX idx_item_seq ON ESTIMATE_TEMPLATE_ITEM(TEMPLATE_OBJID, SEQ);
|
||||
|
||||
-- 코멘트 추가
|
||||
COMMENT ON TABLE ESTIMATE_TEMPLATE_ITEM IS '견적서 템플릿 품목 정보';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE_ITEM.TEMPLATE_OBJID IS '견적서 템플릿 OBJID';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE_ITEM.SEQ IS '품목 순번';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE_ITEM.CATEGORY IS '카테고리 (장비견적서: CNC Machine, UTILITY 등)';
|
||||
|
||||
|
||||
-- 3. CONTRACT_MGMT 테이블에 CATEGORIES_JSON 컬럼 추가 (이미 없는 경우)
|
||||
-- ALTER TABLE ESTIMATE_TEMPLATE ADD COLUMN IF NOT EXISTS CATEGORIES_JSON TEXT;
|
||||
|
||||
-- 샘플 데이터 조회 쿼리
|
||||
-- SELECT * FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = 123;
|
||||
-- SELECT * FROM ESTIMATE_TEMPLATE_ITEM WHERE TEMPLATE_OBJID = 456 ORDER BY SEQ;
|
||||
|
||||
@@ -1550,4 +1550,335 @@ public class ContractMgmtController {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적관리 리스트
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/contractMgmt/estimateList_new.do")
|
||||
public String estimateList_new(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
//List list = contractMgmtService.getcontractList(request,paramMap);
|
||||
String actionType = CommonUtils.checkNull(paramMap.get("actionType"));
|
||||
Map code_map = new HashMap();
|
||||
String returnUrl ="/contractMgmt/estimateList_new";
|
||||
|
||||
try{
|
||||
|
||||
if("excel".equals(actionType)){
|
||||
returnUrl = "/contractMgmt/contractListExcel";
|
||||
}
|
||||
|
||||
//구분
|
||||
code_map.put("category_cd" , commonService.bizMakeOptionList("0000167", CommonUtils.nullToEmpty((String)paramMap.get("category_cd")) , "common.getCodeselect"));
|
||||
|
||||
//고객사
|
||||
code_map.put("customer_cd",commonService.bizMakeOptionList("", CommonUtils.nullToEmpty((String)paramMap.get("customer_objid")),"common.getsupplyselect"));
|
||||
|
||||
//제품구분
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product")),"common.getCodeselect")); //공장
|
||||
|
||||
//진행상황
|
||||
code_map.put("status_cd" , commonService.bizMakeOptionList("0000932", CommonUtils.nullToEmpty((String)paramMap.get("status_cd")) , "common.getCodeselect"));
|
||||
|
||||
//결과
|
||||
code_map.put("result_cd", commonService.bizMakeOptionList("0000963", CommonUtils.nullToEmpty((String)paramMap.get("result_cd")), "common.getCodeselect"));
|
||||
|
||||
//PM
|
||||
code_map.put("pm_user_id", commonService.bizMakeOptionList("", CommonUtils.nullToEmpty((String)paramMap.get("pm_user_id")), "common.getUserselect")); //구매 PM
|
||||
|
||||
request.setAttribute("code_map",code_map);
|
||||
request.setAttribute("actionType",actionType);
|
||||
//request.setAttribute("LIST", list);
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return returnUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적관리 - 견적관리 목록 페이징
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/contractMgmt/estimateGridList.do")
|
||||
public Map getestimateListPaging(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
commonService.selectListPagingNew("contractMgmt.estimateGridList", request, paramMap);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적요청등록 Form
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@RequestMapping("/contractMgmt/estimateRegistFormPopup.do")
|
||||
public String estimateRegistFormPopup(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String actionType = CommonUtils.checkNull(paramMap.get("actionType"));
|
||||
Map code_map = new HashMap();
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
try{
|
||||
String category_cd = ""; //구분
|
||||
String customer_cd = ""; //고객사
|
||||
String product_cd = ""; //제품구분
|
||||
String status_cd = ""; //진행상황
|
||||
String facility = ""; //설비방향
|
||||
String bus_cal_cd = ""; //영업구분
|
||||
String category1_cd = ""; //구분1
|
||||
String result_cd = ""; //수주결과
|
||||
String pm_user_id =""; //PM
|
||||
String chg_user_id ="";//담당자
|
||||
String contract_result ="";//검토결과
|
||||
String contract_company ="";//수주회사
|
||||
String manufacture_plant ="";//제작공장
|
||||
String spec_user_id ="";//사양담당자
|
||||
String spec_result_cd ="";//사양결과
|
||||
String est_user_id ="";//제작공장
|
||||
String est_result_cd ="";//제작공장
|
||||
String area_cd ="";//제작공장
|
||||
String contract_currency ="";//통화
|
||||
String target_project_no ="";//대상프로젝트번호
|
||||
String mechanical_type ="";//기계형식
|
||||
String overhaul_order ="";//오버홀차수
|
||||
|
||||
Map info = null;
|
||||
if(paramMap.get("objId")!=null){
|
||||
paramMap.put("objId",objId);
|
||||
info = CommonUtils.keyChangeUpperMap(contractMgmtService.getContractMgmtInfo(paramMap));
|
||||
category_cd = CommonUtils.nullToEmpty((String)info.get("CATEGORY_CD"));
|
||||
customer_cd = CommonUtils.nullToEmpty((String)info.get("CUSTOMER_OBJID"));
|
||||
product_cd = CommonUtils.nullToEmpty((String)info.get("PRODUCT"));
|
||||
status_cd = CommonUtils.nullToEmpty((String)info.get("STATUS_CD"));
|
||||
facility = CommonUtils.nullToEmpty((String)info.get("FACILITY"));
|
||||
bus_cal_cd = CommonUtils.nullToEmpty((String)info.get("BUS_CAL_CD"));
|
||||
category1_cd = CommonUtils.nullToEmpty((String)info.get("CATEGORY1_CD"));
|
||||
result_cd = CommonUtils.nullToEmpty((String)info.get("RESULT_CD"));
|
||||
pm_user_id= CommonUtils.nullToEmpty((String)info.get("PM_USER_ID"));
|
||||
chg_user_id= CommonUtils.nullToEmpty((String)info.get("CHG_USER_ID"));
|
||||
contract_result = CommonUtils.nullToEmpty((String)info.get("CONTRACT_RESULT"));
|
||||
contract_company = CommonUtils.nullToEmpty((String)info.get("CONTRACT_COMPANY"));
|
||||
manufacture_plant = CommonUtils.nullToEmpty((String)info.get("MANUFACTURE_PLANT"));
|
||||
spec_result_cd = CommonUtils.nullToEmpty((String)info.get("SPEC_RESULT_CD"));
|
||||
spec_user_id = CommonUtils.nullToEmpty((String)info.get("SPEC_USER_ID"));
|
||||
est_user_id = CommonUtils.nullToEmpty((String)info.get("EST_USER_ID"));
|
||||
est_result_cd = CommonUtils.nullToEmpty((String)info.get("EST_RESULT_CD"));
|
||||
area_cd = CommonUtils.nullToEmpty((String)info.get("AREA_CD"));
|
||||
contract_currency = CommonUtils.nullToEmpty((String)info.get("CONTRACT_CURRENCY"));
|
||||
target_project_no = CommonUtils.nullToEmpty((String)info.get("TARGET_PROJECT_NO"));
|
||||
mechanical_type = CommonUtils.nullToEmpty((String)info.get("MECHANICAL_TYPE"));
|
||||
overhaul_order = CommonUtils.nullToEmpty((String)info.get("OVERHAUL_ORDER"));
|
||||
}
|
||||
|
||||
if("".equals(objId)) objId = CommonUtils.createObjId();
|
||||
|
||||
|
||||
//구분
|
||||
code_map.put("category_cd" , commonService.bizMakeOptionList("0000167", category_cd , "common.getCodeselect"));
|
||||
|
||||
//고객사
|
||||
code_map.put("customer_cd",commonService.bizMakeOptionList("", customer_cd,"common.getsupplyselect"));
|
||||
|
||||
//제품구분
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", product_cd,"common.getCodeselect")); //공장
|
||||
|
||||
//진행상황
|
||||
code_map.put("status_cd" , commonService.bizMakeOptionList("0000932", status_cd , "common.getCodeselect"));
|
||||
|
||||
//설비방향
|
||||
code_map.put("facility" , commonService.bizMakeOptionList("0000959", facility , "common.getCodeselect"));
|
||||
|
||||
//영업구분
|
||||
code_map.put("bus_cal_cd" , commonService.bizMakeOptionList("0000967", bus_cal_cd , "common.getCodeselect"));
|
||||
|
||||
//구분1
|
||||
//code_map.put("category1_cd", commonService.bizMakeOptionList("0000942", category1_cd, "common.getCodeselect"));
|
||||
|
||||
//검토결과
|
||||
code_map.put("result_cd", commonService.bizMakeOptionList("0001107", result_cd, "common.getCodeselect"));
|
||||
|
||||
//검토결과
|
||||
code_map.put("spec_result_cd", commonService.bizMakeOptionList("0001107", spec_result_cd, "common.getCodeselect"));
|
||||
|
||||
//검토결과
|
||||
code_map.put("est_result_cd", commonService.bizMakeOptionList("0001107", est_result_cd, "common.getCodeselect"));
|
||||
|
||||
//계약담당자
|
||||
code_map.put("chg_user_id", commonService.bizMakeOptionList("", chg_user_id, "common.getUserselect")); //구매 PM
|
||||
|
||||
//계약담당자
|
||||
code_map.put("spec_user_id", commonService.bizMakeOptionList("", spec_user_id, "common.getUserselect")); //구매 PM
|
||||
|
||||
//계약담당자
|
||||
code_map.put("est_user_id", commonService.bizMakeOptionList("", est_user_id, "common.getUserselect")); //구매 PM
|
||||
|
||||
//PM
|
||||
code_map.put("pm_user_id", commonService.bizMakeOptionList("", pm_user_id, "common.getUserselect")); //구매 PM
|
||||
|
||||
//수주결과
|
||||
code_map.put("contract_result", commonService.bizMakeOptionList("0000963", contract_result, "common.getCodeselect"));
|
||||
|
||||
//수주회사
|
||||
code_map.put("contract_company", commonService.bizMakeOptionList("0001098", contract_company, "common.getCodeselect"));
|
||||
|
||||
//제작공장
|
||||
code_map.put("manufacture_plant", commonService.bizMakeOptionList("0001101", manufacture_plant, "common.getCodeselect"));
|
||||
|
||||
//해외.국내
|
||||
code_map.put("area_cd", commonService.bizMakeOptionList("0001219", area_cd, "common.getCodeselect"));
|
||||
//통화
|
||||
code_map.put("contract_currency", commonService.bizMakeOptionList("0001533", contract_currency, "common.getCodeselect"));
|
||||
//당사프로젟트번호
|
||||
code_map.put("project_no",commonService.bizMakeOptionList("", target_project_no,"common.getCusProjectNoList"));
|
||||
//기계형식
|
||||
code_map.put("mechanical_type", commonService.bizMakeOptionList("", mechanical_type,"common.getMechanicalTypeList"));
|
||||
|
||||
|
||||
request.setAttribute("code_map",code_map);
|
||||
request.setAttribute("info", info);
|
||||
request.setAttribute("objId", objId);
|
||||
request.setAttribute("actionType", actionType);
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "/contractMgmt/estimateRegistFormPopup";
|
||||
}
|
||||
|
||||
@RequestMapping("/contractMgmt/saveEstimateInfo.do")
|
||||
public String saveEstimateInfo(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
try {
|
||||
request.setAttribute("RESULT", CommonUtils.getJsonMap(contractMgmtService.saveContractMgmtInfo(request, paramMap)) );
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/ajax/ajaxResult";
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 양식1 (일반 견적서) 팝업
|
||||
* @param session
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/contractMgmt/estimateTemplate1.do")
|
||||
public String estimateTemplate1(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
|
||||
try{
|
||||
Map estimate = null;
|
||||
List<Map> items = new ArrayList<Map>();
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// 기존 견적서 데이터 조회
|
||||
estimate = contractMgmtService.getEstimateTemplateInfo(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItems(paramMap);
|
||||
}
|
||||
|
||||
request.setAttribute("estimate", estimate);
|
||||
request.setAttribute("items", items);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "/contractMgmt/estimateTemplate1";
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 양식2 (장비 견적서) 팝업
|
||||
* @param session
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/contractMgmt/estimateTemplate2.do")
|
||||
public String estimateTemplate2(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
|
||||
try{
|
||||
Map estimate = null;
|
||||
List<Map> items = new ArrayList<Map>();
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// 기존 견적서 데이터 조회
|
||||
estimate = contractMgmtService.getEstimateTemplateInfo(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItems(paramMap);
|
||||
}
|
||||
|
||||
request.setAttribute("estimate", estimate);
|
||||
request.setAttribute("items", items);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "/contractMgmt/estimateTemplate2";
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 상세 정보 조회 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/getEstimateDetail.do", method=RequestMethod.POST)
|
||||
public Map getEstimateDetail(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
Map estimate = contractMgmtService.getEstimateTemplateInfo(paramMap);
|
||||
List<Map> items = contractMgmtService.getEstimateTemplateItems(paramMap);
|
||||
|
||||
resultMap.put("estimate", estimate);
|
||||
resultMap.put("items", items);
|
||||
resultMap.put("result", "success");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 저장 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/saveEstimate.do", method=RequestMethod.POST)
|
||||
public Map saveEstimate(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("userId", person.getUserId());
|
||||
|
||||
contractMgmtService.saveEstimateTemplate(request, paramMap);
|
||||
|
||||
resultMap.put("result", "success");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,8 +486,57 @@
|
||||
,CODE_NAME(AREA_CD) AS AREA_NAME
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
B.OBJID AS ROUTE_OBJID,
|
||||
CASE B.STATUS
|
||||
WHEN 'inProcess' THEN '결재중'
|
||||
WHEN 'complete' THEN '결재완료'
|
||||
WHEN 'reject' THEN '반려'
|
||||
ELSE ''
|
||||
END APPR_STATUS,
|
||||
A.OBJID AS APPROVAL_OBJID,
|
||||
A.TARGET_OBJID,
|
||||
B.ROUTE_SEQ
|
||||
FROM
|
||||
APPROVAL A,
|
||||
(
|
||||
select
|
||||
T1.*
|
||||
from
|
||||
(
|
||||
select
|
||||
TARGET_OBJID,
|
||||
max(T.ROUTE_SEQ) as ROUTE_SEQ
|
||||
from
|
||||
ROUTE T
|
||||
group by
|
||||
T.TARGET_OBJID
|
||||
) T,
|
||||
ROUTE T1
|
||||
where
|
||||
T.TARGET_OBJID = T1.TARGET_OBJID
|
||||
and T.ROUTE_SEQ = T1.ROUTE_SEQ
|
||||
) B
|
||||
WHERE
|
||||
A.OBJID = B.APPROVAL_OBJID
|
||||
AND TARGET_TYPE IN ('CONTRACT_ESTIMATE')
|
||||
) A
|
||||
ON T.OBJID::numeric = A.TARGET_OBJID
|
||||
)
|
||||
</sql>
|
||||
|
||||
@@ -519,21 +568,27 @@
|
||||
<if test="product != null and product !='' ">
|
||||
AND product = #{product}
|
||||
</if>
|
||||
|
||||
|
||||
<if test="status_cd !=null and status_cd !=''">
|
||||
AND status_cd = #{status_cd}
|
||||
</if>
|
||||
|
||||
|
||||
|
||||
<if test="result_cd !=null and result_cd !=''">
|
||||
AND result_cd = #{result_cd}
|
||||
</if>
|
||||
|
||||
<if test="contract_start_date != null and !''.equals(contract_start_date)">
|
||||
AND TO_DATE(CONTRACT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
<if test="receipt_start_date != null and !''.equals(receipt_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{receipt_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="contract_end_date != null and !''.equals(contract_end_date)">
|
||||
AND TO_DATE(CONTRACT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
<if test="receipt_end_date != null and !''.equals(receipt_end_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{receipt_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{due_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="due_end_date != null and !''.equals(due_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{due_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
@@ -600,7 +655,46 @@
|
||||
</if>
|
||||
<if test="contract_month != null and !''.equals(contract_month)">
|
||||
AND TO_DATE(TO_CHAR(TO_DATE(CONTRACT_DATE,'YYYY-MM-DD'),'YYYY-MM-DD'),'YYYY-MM') <![CDATA[ = ]]> TO_DATE(SUBSTRING(#{contract_month} FROM 1 FOR 4) || '-' || SUBSTRING(#{contract_month} FROM 5 FOR 2), 'YYYY-MM')
|
||||
</if>
|
||||
</if>
|
||||
|
||||
<!-- 견적관리 추가 검색조건 -->
|
||||
<if test="appr_status !=null and appr_status != '' ">
|
||||
AND APPR_STATUS = #{appr_status}
|
||||
</if>
|
||||
|
||||
<if test="area_cd != null and area_cd !='' ">
|
||||
AND AREA_CD = #{area_cd}
|
||||
</if>
|
||||
|
||||
<if test="paid_type != null and paid_type !='' ">
|
||||
AND PAID_TYPE = #{paid_type}
|
||||
</if>
|
||||
|
||||
<if test="search_partNo != null and search_partNo != ''">
|
||||
AND UPPER(PART_NO) LIKE UPPER('%${search_partNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_partName != null and search_partName != ''">
|
||||
AND UPPER(PART_NAME) LIKE UPPER('%${search_partName}%')
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="receipt_start_date != null and !''.equals(receipt_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{receipt_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="receipt_end_date != null and !''.equals(receipt_end_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{receipt_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(RECEIPT_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{due_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="due_end_date != null and !''.equals(due_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{due_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
@@ -724,9 +818,193 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<update id="saveContractMgmtInfo" parameterType="map">
|
||||
INSERT INTO CONTRACT_MGMT
|
||||
(
|
||||
OBJID
|
||||
,CATEGORY_CD
|
||||
,CUSTOMER_OBJID
|
||||
,PRODUCT
|
||||
,CUSTOMER_PROJECT_NAME
|
||||
,STATUS_CD
|
||||
,DUE_DATE
|
||||
,LOCATION
|
||||
,SETUP
|
||||
,FACILITY
|
||||
,FACILITY_QTY
|
||||
,FACILITY_TYPE
|
||||
,FACILITY_DEPTH
|
||||
,PRODUCTION_NO
|
||||
,BUS_CAL_CD
|
||||
,CATEGORY1_CD
|
||||
,CHG_USER_ID
|
||||
,PLAN_DATE
|
||||
,COMPLETE_DATE
|
||||
,RESULT_CD
|
||||
,PROJECT_NO
|
||||
,PM_USER_ID
|
||||
,CONTRACT_PRICE
|
||||
,CONTRACT_PRICE_CURRENCY
|
||||
,CONTRACT_CURRENCY
|
||||
,REGDATE
|
||||
,WRITER
|
||||
,CONTRACT_NO
|
||||
,CUSTOMER_EQUIP_NAME
|
||||
,REQ_DEL_DATE
|
||||
,CONTRACT_DEL_DATE
|
||||
,CONTRACT_COMPANY
|
||||
,CONTRACT_DATE
|
||||
,PO_NO
|
||||
,MANUFACTURE_PLANT
|
||||
,CONTRACT_RESULT
|
||||
,PROJECT_NAME
|
||||
,SPEC_USER_ID
|
||||
,SPEC_PLAN_DATE
|
||||
,SPEC_COMP_DATE
|
||||
,SPEC_RESULT_CD
|
||||
,EST_USER_ID
|
||||
,EST_PLAN_DATE
|
||||
,EST_COMP_DATE
|
||||
,EST_RESULT_CD
|
||||
,AREA_CD
|
||||
,TARGET_PROJECT_NO
|
||||
,TARGET_PROJECT_NO_DIRECT
|
||||
,CUSTOMER_PRODUCTION_NO
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
#{objId}
|
||||
,#{category_cd}
|
||||
,#{customer_objid}
|
||||
,#{product}
|
||||
,#{customer_project_name}
|
||||
,#{status_cd}
|
||||
,#{due_date}
|
||||
,#{location}
|
||||
,#{setup}
|
||||
,#{facility}
|
||||
,#{facility_qty}
|
||||
,#{facility_type}
|
||||
,#{facility_depth}
|
||||
,#{production_no}
|
||||
,#{bus_cal_cd}
|
||||
,#{category1_cd}
|
||||
,#{chg_user_id}
|
||||
,#{plan_date}
|
||||
,#{complete_date}
|
||||
,#{result_cd}
|
||||
,#{project_no}
|
||||
,#{pm_user_id}
|
||||
,#{contract_price}
|
||||
,#{contract_price_currency}
|
||||
,#{contract_currency}
|
||||
,NOW()
|
||||
,#{writer}
|
||||
,(SELECT TO_CHAR(NOW(),'yy')::VARCHAR ||'C-'||LPAD((SELECT NEXTVAL('contract_mgmt_seq'))::VARCHAR ,4,'0'))
|
||||
,#{customer_equip_name}
|
||||
,#{req_del_date}
|
||||
,#{contract_del_date}
|
||||
,#{contract_company}
|
||||
,#{contract_date}
|
||||
,#{po_no}
|
||||
,#{manufacture_plant}
|
||||
,#{contract_result}
|
||||
,#{project_name}
|
||||
,#{spec_user_id}
|
||||
,#{spec_plan_date}
|
||||
,#{spec_comp_date}
|
||||
,#{spec_result_cd}
|
||||
,#{est_user_id}
|
||||
,#{est_plan_date}
|
||||
,#{est_comp_date}
|
||||
,#{est_result_cd}
|
||||
,#{area_cd}
|
||||
,#{target_project_no}
|
||||
,#{target_project_no_direct}
|
||||
,#{customer_production_no}
|
||||
,#{mechanical_type}
|
||||
,#{overhaul_order}
|
||||
,#{paid_type}
|
||||
,#{receipt_date}
|
||||
,#{part_no}
|
||||
,#{part_name}
|
||||
,#{serial_no}
|
||||
,#{quantity}
|
||||
,#{customer_request}
|
||||
,#{exchange_rate}
|
||||
)
|
||||
ON CONFLICT (OBJID) DO
|
||||
UPDATE
|
||||
SET
|
||||
CATEGORY_CD = #{category_cd}
|
||||
,CUSTOMER_OBJID = #{customer_objid}
|
||||
,PRODUCT = #{product}
|
||||
,CUSTOMER_PROJECT_NAME = #{customer_project_name}
|
||||
,STATUS_CD = #{status_cd}
|
||||
,DUE_DATE = #{due_date}
|
||||
,LOCATION = #{location}
|
||||
,SETUP = #{setup}
|
||||
,FACILITY = #{facility}
|
||||
,FACILITY_QTY = #{facility_qty}
|
||||
,FACILITY_TYPE = #{facility_type}
|
||||
,FACILITY_DEPTH = #{facility_depth}
|
||||
,PRODUCTION_NO = #{production_no}
|
||||
,BUS_CAL_CD = #{bus_cal_cd}
|
||||
,CATEGORY1_CD = #{category1_cd}
|
||||
,CHG_USER_ID = #{chg_user_id}
|
||||
,PLAN_DATE = #{plan_date}
|
||||
,COMPLETE_DATE = #{complete_date}
|
||||
,RESULT_CD = #{result_cd}
|
||||
,PROJECT_NO = #{project_no}
|
||||
,PM_USER_ID = #{pm_user_id}
|
||||
,CONTRACT_PRICE = #{contract_price}
|
||||
,CONTRACT_PRICE_CURRENCY = #{contract_price_currency}
|
||||
,CONTRACT_CURRENCY = #{contract_currency}
|
||||
,CUSTOMER_EQUIP_NAME = #{customer_equip_name}
|
||||
,REQ_DEL_DATE = #{req_del_date}
|
||||
,CONTRACT_DEL_DATE = #{contract_del_date}
|
||||
,CONTRACT_COMPANY = #{contract_company}
|
||||
,CONTRACT_DATE = #{contract_date}
|
||||
,PO_NO = #{po_no}
|
||||
,MANUFACTURE_PLANT = #{manufacture_plant}
|
||||
,CONTRACT_RESULT = #{contract_result}
|
||||
,PROJECT_NAME = #{project_name}
|
||||
,SPEC_USER_ID = #{spec_user_id}
|
||||
,SPEC_PLAN_DATE = #{spec_plan_date}
|
||||
,SPEC_COMP_DATE = #{spec_comp_date}
|
||||
,SPEC_RESULT_CD = #{spec_result_cd}
|
||||
,EST_USER_ID = #{est_user_id}
|
||||
,EST_PLAN_DATE = #{est_plan_date}
|
||||
,EST_COMP_DATE = #{est_comp_date}
|
||||
,EST_RESULT_CD = #{est_result_cd}
|
||||
,AREA_CD = #{area_cd}
|
||||
,TARGET_PROJECT_NO = #{target_project_no}
|
||||
,TARGET_PROJECT_NO_DIRECT= #{target_project_no_direct}
|
||||
,CUSTOMER_PRODUCTION_NO = #{customer_production_no}
|
||||
,MECHANICAL_TYPE = #{mechanical_type}
|
||||
,OVERHAUL_ORDER = #{overhaul_order}
|
||||
,PAID_TYPE = #{paid_type}
|
||||
,RECEIPT_DATE = #{receipt_date}
|
||||
,PART_NO = #{part_no}
|
||||
,PART_NAME = #{part_name}
|
||||
,SERIAL_NO = #{serial_no}
|
||||
,QUANTITY = #{quantity}
|
||||
,CUSTOMER_REQUEST = #{customer_request}
|
||||
,EXCHANGE_RATE = #{exchange_rate}
|
||||
</update>
|
||||
|
||||
<update id="saveContractMgmtInfo_old" parameterType="map">
|
||||
INSERT INTO CONTRACT_MGMT
|
||||
(
|
||||
OBJID
|
||||
,CATEGORY_CD
|
||||
@@ -1096,6 +1374,14 @@
|
||||
,CUSTOMER_PRODUCTION_NO
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt01' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT1
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt02' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT2
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID::VARCHAR = A.OBJID AND DOC_TYPE='contractMgmt03' AND UPPER(STATUS) = 'ACTIVE') AS FILE_CNT3
|
||||
@@ -3376,5 +3662,218 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
-->
|
||||
FROM END_COUNT E, PROJECT_STATS P, ING_COUNT I, DELAY_COUNT D, HOLD_COUNT H, NOPLAN_COUNT N
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 관련 쿼리 -->
|
||||
|
||||
<!-- 견적서 기본 정보 조회 -->
|
||||
<select id="getEstimateTemplateInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CATEGORY_CD,
|
||||
CODE_NAME(CATEGORY_CD) AS CATEGORY_NAME,
|
||||
CUSTOMER_OBJID,
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG AS O WHERE O.OBJID = T.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME,
|
||||
PRODUCT,
|
||||
CODE_NAME(PRODUCT) AS PRODUCT_NAME,
|
||||
CUSTOMER_PROJECT_NAME,
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
PAID_TYPE,
|
||||
RECEIPT_DATE,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
SERIAL_NO,
|
||||
QUANTITY,
|
||||
CUSTOMER_REQUEST,
|
||||
CONTRACT_CURRENCY,
|
||||
CODE_NAME(CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
EXCHANGE_RATE,
|
||||
DUE_DATE,
|
||||
WRITER,
|
||||
(SELECT USER_NAME FROM USER_INFO AS O WHERE O.USER_ID = T.WRITER) AS WRITER_NAME,
|
||||
REGDATE,
|
||||
TO_CHAR(REGDATE,'YYYY-MM-DD') AS REG_DATE
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
WHERE
|
||||
OBJID = #{objId}::NUMERIC
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (ESTIMATE_TEMPLATE 테이블) -->
|
||||
<select id="getEstimateTemplateData" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 -->
|
||||
<select id="getEstimateTemplateItems" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 저장 -->
|
||||
<insert id="insertEstimateTemplate" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{objId}::NUMERIC,
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
#{estimate_no},
|
||||
#{contact_person},
|
||||
#{greeting_text},
|
||||
#{model_name},
|
||||
#{model_code},
|
||||
#{executor_date},
|
||||
#{note1},
|
||||
#{note2},
|
||||
#{note3},
|
||||
#{note4},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 수정 -->
|
||||
<update id="updateEstimateTemplate" parameterType="map">
|
||||
UPDATE ESTIMATE_TEMPLATE
|
||||
SET
|
||||
EXECUTOR = #{executor},
|
||||
RECIPIENT = #{recipient},
|
||||
ESTIMATE_NO = #{estimate_no},
|
||||
CONTACT_PERSON = #{contact_person},
|
||||
GREETING_TEXT = #{greeting_text},
|
||||
MODEL_NAME = #{model_name},
|
||||
MODEL_CODE = #{model_code},
|
||||
EXECUTOR_DATE = #{executor_date},
|
||||
NOTE1 = #{note1},
|
||||
NOTE2 = #{note2},
|
||||
NOTE3 = #{note3},
|
||||
NOTE4 = #{note4},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
<!-- 견적서 템플릿 품목 삭제 -->
|
||||
<delete id="deleteEstimateTemplateItems" parameterType="map">
|
||||
DELETE FROM ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
</delete>
|
||||
|
||||
<!-- 견적서 템플릿 품목 저장 -->
|
||||
<insert id="insertEstimateTemplateItems" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE_ITEM (
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = #{objId}::NUMERIC AND TEMPLATE_TYPE = #{template_type}),
|
||||
(json_array_elements(#{items_json}::json)->>'seq')::INTEGER,
|
||||
json_array_elements(#{items_json}::json)->>'category',
|
||||
json_array_elements(#{items_json}::json)->>'description',
|
||||
json_array_elements(#{items_json}::json)->>'specification',
|
||||
json_array_elements(#{items_json}::json)->>'quantity',
|
||||
json_array_elements(#{items_json}::json)->>'unit',
|
||||
(json_array_elements(#{items_json}::json)->>'unit_price')::NUMERIC,
|
||||
(json_array_elements(#{items_json}::json)->>'amount')::NUMERIC,
|
||||
json_array_elements(#{items_json}::json)->>'note',
|
||||
json_array_elements(#{items_json}::json)->>'remark'
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 카테고리 업데이트 (장비 견적서용) -->
|
||||
<update id="updateEstimateTemplateCategories" parameterType="map">
|
||||
UPDATE ESTIMATE_TEMPLATE
|
||||
SET
|
||||
CATEGORIES_JSON = #{categories_json},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -492,8 +492,35 @@ public class ContractMgmtService {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/** 견적등록 저장. 프로젝트 생성은 주문서 등록에서 처리 */
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Map saveContractMgmtInfo(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
Map resultList = null;
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("writer", person.getUserId());
|
||||
int cnt = sqlSession.update("contractMgmt.saveContractMgmtInfo", paramMap);
|
||||
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("msg", Message.SAVE_SUCCESS);
|
||||
sqlSession.commit();
|
||||
}catch(Exception e){
|
||||
sqlSession.rollback();
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", Message.SAVE_FAILED);
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Map saveContractMgmtInfo_old(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
Map resultList = null;
|
||||
@@ -1181,4 +1208,135 @@ public class ContractMgmtService {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 기본 정보 조회
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public Map getEstimateTemplateInfo(Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String templateType = CommonUtils.checkNull(paramMap.get("template_type"));
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// 견적서 기본 정보 조회 (CONTRACT_MGMT 테이블에서)
|
||||
resultMap = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateInfo", paramMap);
|
||||
|
||||
// 견적서 템플릿 정보 조회 (ESTIMATE_TEMPLATE 테이블에서, 있는 경우)
|
||||
Map templateInfo = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateData", paramMap);
|
||||
if(templateInfo != null && !templateInfo.isEmpty()){
|
||||
resultMap.putAll(templateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 품목 정보 조회
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public List<Map> getEstimateTemplateItems(Map paramMap){
|
||||
List<Map> resultList = new ArrayList<Map>();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
resultList = sqlSession.selectList("contractMgmt.getEstimateTemplateItems", paramMap);
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 저장
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public Map saveEstimateTemplate(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = person.getUserId();
|
||||
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String templateType = CommonUtils.checkNull(paramMap.get("template_type"));
|
||||
String itemsJson = CommonUtils.checkNull(paramMap.get("items"));
|
||||
String categoriesJson = CommonUtils.checkNull(paramMap.get("categories"));
|
||||
|
||||
paramMap.put("writer", userId);
|
||||
paramMap.put("chg_user_id", userId);
|
||||
|
||||
// 견적서 템플릿 정보 저장/수정
|
||||
Map existingTemplate = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateData", paramMap);
|
||||
|
||||
if(existingTemplate != null && !existingTemplate.isEmpty()){
|
||||
// 기존 데이터 업데이트
|
||||
sqlSession.update("contractMgmt.updateEstimateTemplate", paramMap);
|
||||
} else {
|
||||
// 신규 데이터 삽입
|
||||
sqlSession.insert("contractMgmt.insertEstimateTemplate", paramMap);
|
||||
}
|
||||
|
||||
// 기존 품목 삭제
|
||||
sqlSession.delete("contractMgmt.deleteEstimateTemplateItems", paramMap);
|
||||
|
||||
// 품목 정보 저장
|
||||
if(!"".equals(itemsJson)){
|
||||
// JSON 파싱 및 저장 로직 (실제 구현 시 JSON 라이브러리 사용)
|
||||
// 여기서는 간단히 파라미터로 받은 데이터를 저장
|
||||
paramMap.put("items_json", itemsJson);
|
||||
sqlSession.insert("contractMgmt.insertEstimateTemplateItems", paramMap);
|
||||
}
|
||||
|
||||
// 카테고리 정보 저장 (장비 견적서용)
|
||||
if(!"".equals(categoriesJson)){
|
||||
paramMap.put("categories_json", categoriesJson);
|
||||
sqlSession.update("contractMgmt.updateEstimateTemplateCategories", paramMap);
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("msg", Message.SAVE_SUCCESS);
|
||||
|
||||
}catch(Exception e){
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("msg", Message.SAVE_FAILED);
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,251 @@ if ! git reset --hard origin/main; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Java 개발 환경 확인 및 설치
|
||||
echo "Checking Java development environment..."
|
||||
|
||||
# JDK 7 우선 설치 및 설정
|
||||
if ! command -v javac &> /dev/null; then
|
||||
echo "Java compiler (javac) not found. Installing OpenJDK 7..."
|
||||
|
||||
# 패키지 목록 업데이트
|
||||
apt-get update
|
||||
|
||||
# OpenJDK 7 JDK 설치 (JRE가 아닌 JDK)
|
||||
apt-get install -y openjdk-7-jdk
|
||||
|
||||
# 설치 확인
|
||||
if ! command -v javac &> /dev/null; then
|
||||
echo "Failed to install OpenJDK 7. Trying alternative installation..."
|
||||
apt-get install -y default-jdk
|
||||
|
||||
if ! command -v javac &> /dev/null; then
|
||||
echo "Failed to install Java compiler. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# JAVA_HOME 설정 (JDK 7 우선)
|
||||
export JAVA_HOME=""
|
||||
JDK7_PATHS=(
|
||||
"/usr/lib/jvm/java-7-openjdk-amd64"
|
||||
"/usr/lib/jvm/java-1.7.0-openjdk-amd64"
|
||||
"/usr/lib/jvm/openjdk-7-jdk"
|
||||
"/usr/lib/jvm/default-java"
|
||||
)
|
||||
|
||||
for path in "${JDK7_PATHS[@]}"; do
|
||||
if [ -d "$path" ] && [ -f "$path/bin/javac" ]; then
|
||||
export JAVA_HOME="$path"
|
||||
export PATH="$JAVA_HOME/bin:$PATH"
|
||||
echo "Set JAVA_HOME to: $JAVA_HOME"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
echo "Warning: Could not find JDK 7 installation directory"
|
||||
fi
|
||||
|
||||
# Java 버전 확인
|
||||
echo "Java compiler version:"
|
||||
javac -version
|
||||
echo "Java runtime version:"
|
||||
java -version
|
||||
|
||||
# Java 소스 컴파일
|
||||
echo "Compiling Java sources..."
|
||||
|
||||
# Java 컴파일을 위한 디렉토리 생성 및 기존 클래스 파일 정리
|
||||
echo "Preparing compilation directory..."
|
||||
rm -rf WebContent/WEB-INF/classes
|
||||
mkdir -p WebContent/WEB-INF/classes
|
||||
|
||||
# 클래스패스 설정 (모든 jar 파일 포함)
|
||||
CLASSPATH=""
|
||||
for jar in WebContent/WEB-INF/lib/*.jar; do
|
||||
if [ -z "$CLASSPATH" ]; then
|
||||
CLASSPATH="$jar"
|
||||
else
|
||||
CLASSPATH="$CLASSPATH:$jar"
|
||||
fi
|
||||
done
|
||||
|
||||
# JDK 7 기본 라이브러리 추가
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
if [ -f "$JAVA_HOME/jre/lib/rt.jar" ]; then
|
||||
CLASSPATH="$CLASSPATH:$JAVA_HOME/jre/lib/rt.jar"
|
||||
echo "Added JDK 7 runtime: $JAVA_HOME/jre/lib/rt.jar"
|
||||
fi
|
||||
if [ -f "$JAVA_HOME/lib/tools.jar" ]; then
|
||||
CLASSPATH="$CLASSPATH:$JAVA_HOME/lib/tools.jar"
|
||||
echo "Added JDK 7 tools: $JAVA_HOME/lib/tools.jar"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Servlet API는 WEB-INF/lib에 있는 것을 사용 (이미 클래스패스에 포함됨)
|
||||
echo "Using Servlet API from WEB-INF/lib (javax.servlet-api-4.0.1.jar)"
|
||||
|
||||
echo "Classpath: $CLASSPATH"
|
||||
|
||||
# Java 소스 파일 찾기 및 컴파일
|
||||
if [ -d "src" ]; then
|
||||
echo "Found Java source directory: src"
|
||||
|
||||
# Java 소스 파일 목록 생성
|
||||
find src -name "*.java" > java_sources.txt
|
||||
|
||||
if [ -s java_sources.txt ]; then
|
||||
echo "Compiling Java files..."
|
||||
|
||||
# Java 컴파일 실행 (Java 7 호환성을 위해 source와 target 버전 명시)
|
||||
echo "Starting Java compilation with classpath..."
|
||||
echo "Number of Java files to compile: $(wc -l < java_sources.txt)"
|
||||
|
||||
# 컴파일 실행 및 결과 확인
|
||||
COMPILE_EXIT_CODE=0
|
||||
javac -cp "$CLASSPATH" -d WebContent/WEB-INF/classes -encoding UTF-8 -source 1.7 -target 1.7 @java_sources.txt 2>&1 | tee compile.log
|
||||
COMPILE_EXIT_CODE=${PIPESTATUS[0]}
|
||||
|
||||
if [ $COMPILE_EXIT_CODE -eq 0 ]; then
|
||||
echo "Java compilation successful!"
|
||||
|
||||
# 컴파일된 클래스 파일 수 확인
|
||||
CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l)
|
||||
echo "Successfully compiled $CLASS_COUNT class files"
|
||||
|
||||
# 컴파일된 패키지 구조 표시
|
||||
if [ $CLASS_COUNT -gt 0 ]; then
|
||||
echo "Compiled packages:"
|
||||
find WebContent/WEB-INF/classes -type d | grep -v "^WebContent/WEB-INF/classes$" | head -10
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Java compilation failed! (Exit code: $COMPILE_EXIT_CODE)"
|
||||
echo "Compilation errors:"
|
||||
if [ -f compile.log ]; then
|
||||
tail -50 compile.log
|
||||
fi
|
||||
|
||||
echo "Attempting compilation with extended classpath..."
|
||||
|
||||
# 이미 설정된 JAVA_HOME 사용하여 확장된 클래스패스 구성
|
||||
EXTENDED_CLASSPATH="$CLASSPATH"
|
||||
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
echo "Using JAVA_HOME: $JAVA_HOME"
|
||||
# JDK 7 필수 라이브러리들 추가
|
||||
for lib in "jre/lib/rt.jar" "lib/tools.jar" "jre/lib/jsse.jar" "jre/lib/jce.jar"; do
|
||||
if [ -f "$JAVA_HOME/$lib" ]; then
|
||||
EXTENDED_CLASSPATH="$EXTENDED_CLASSPATH:$JAVA_HOME/$lib"
|
||||
echo "Added: $JAVA_HOME/$lib"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "Warning: JAVA_HOME not set, using system default"
|
||||
fi
|
||||
|
||||
# 시스템 클래스패스로 재시도
|
||||
echo "Extended classpath: $EXTENDED_CLASSPATH"
|
||||
RETRY_EXIT_CODE=0
|
||||
javac -cp "$EXTENDED_CLASSPATH" -d WebContent/WEB-INF/classes -encoding UTF-8 -source 1.7 -target 1.7 @java_sources.txt 2>&1 | tee compile_retry.log
|
||||
RETRY_EXIT_CODE=${PIPESTATUS[0]}
|
||||
|
||||
if [ $RETRY_EXIT_CODE -eq 0 ]; then
|
||||
echo "Java compilation successful with extended classpath!"
|
||||
CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l)
|
||||
echo "Successfully compiled $CLASS_COUNT class files"
|
||||
|
||||
# 컴파일된 패키지 구조 표시
|
||||
if [ $CLASS_COUNT -gt 0 ]; then
|
||||
echo "Compiled packages:"
|
||||
find WebContent/WEB-INF/classes -type d | grep -v "^WebContent/WEB-INF/classes$" | head -10
|
||||
fi
|
||||
else
|
||||
echo "Java compilation failed even with extended classpath. (Exit code: $RETRY_EXIT_CODE)"
|
||||
echo "Retry compilation errors:"
|
||||
if [ -f compile_retry.log ]; then
|
||||
tail -50 compile_retry.log
|
||||
fi
|
||||
echo "WARNING: Continuing with deployment anyway. Some features may not work properly."
|
||||
fi
|
||||
fi
|
||||
|
||||
# 임시 파일 정리
|
||||
rm -f java_sources.txt compile.log compile_retry.log
|
||||
|
||||
# XML, properties 등 리소스 파일들을 classes 디렉토리에 복사
|
||||
echo "Copying resource files (XML, properties, etc.) to classes directory..."
|
||||
|
||||
# src 디렉토리에서 Java 파일이 아닌 모든 파일들을 찾아서 복사
|
||||
find src -type f ! -name "*.java" | while read resource_file; do
|
||||
# src/ 부분을 제거하여 상대 경로 생성
|
||||
relative_path=${resource_file#src/}
|
||||
target_dir="WebContent/WEB-INF/classes/$(dirname "$relative_path")"
|
||||
|
||||
# 대상 디렉토리 생성
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
# 파일 복사
|
||||
cp "$resource_file" "WebContent/WEB-INF/classes/$relative_path"
|
||||
echo "Copied: $resource_file -> WebContent/WEB-INF/classes/$relative_path"
|
||||
done
|
||||
|
||||
# 복사된 리소스 파일 수 확인
|
||||
RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l)
|
||||
echo "Copied $RESOURCE_COUNT resource files (XML, properties, etc.)"
|
||||
else
|
||||
echo "No Java source files found in src directory"
|
||||
|
||||
# Java 파일이 없어도 리소스 파일은 복사
|
||||
echo "Copying resource files (XML, properties, etc.) to classes directory..."
|
||||
find src -type f ! -name "*.java" | while read resource_file; do
|
||||
relative_path=${resource_file#src/}
|
||||
target_dir="WebContent/WEB-INF/classes/$(dirname "$relative_path")"
|
||||
mkdir -p "$target_dir"
|
||||
cp "$resource_file" "WebContent/WEB-INF/classes/$relative_path"
|
||||
echo "Copied: $resource_file -> WebContent/WEB-INF/classes/$relative_path"
|
||||
done
|
||||
|
||||
RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l)
|
||||
echo "Copied $RESOURCE_COUNT resource files (XML, properties, etc.)"
|
||||
fi
|
||||
else
|
||||
echo "No src directory found - skipping Java compilation and resource copying"
|
||||
fi
|
||||
|
||||
# 컴파일된 클래스 파일 권한 설정 및 최종 확인
|
||||
if [ -d "WebContent/WEB-INF/classes" ]; then
|
||||
chmod -R 644 WebContent/WEB-INF/classes
|
||||
find WebContent/WEB-INF/classes -type d -exec chmod 755 {} \;
|
||||
|
||||
FINAL_CLASS_COUNT=$(find WebContent/WEB-INF/classes -name "*.class" | wc -l)
|
||||
FINAL_RESOURCE_COUNT=$(find WebContent/WEB-INF/classes -type f ! -name "*.class" | wc -l)
|
||||
|
||||
if [ $FINAL_CLASS_COUNT -gt 0 ] || [ $FINAL_RESOURCE_COUNT -gt 0 ]; then
|
||||
echo "✓ Build completed successfully!"
|
||||
echo "✓ Total compiled class files: $FINAL_CLASS_COUNT"
|
||||
echo "✓ Total resource files (XML, properties, etc.): $FINAL_RESOURCE_COUNT"
|
||||
echo "✓ Set appropriate permissions for all files"
|
||||
|
||||
# 클래스 파일 크기 확인
|
||||
CLASSES_SIZE=$(du -sh WebContent/WEB-INF/classes 2>/dev/null | cut -f1)
|
||||
echo "✓ Classes directory size: $CLASSES_SIZE"
|
||||
|
||||
# 주요 리소스 파일 타입 확인
|
||||
if [ $FINAL_RESOURCE_COUNT -gt 0 ]; then
|
||||
echo "✓ Resource file types found:"
|
||||
find WebContent/WEB-INF/classes -type f ! -name "*.class" | sed 's/.*\.//' | sort | uniq -c | head -5
|
||||
fi
|
||||
else
|
||||
echo "⚠ WARNING: No compiled class files or resource files found in WebContent/WEB-INF/classes"
|
||||
echo "⚠ The application may not function properly without compiled Java classes and resources"
|
||||
fi
|
||||
else
|
||||
echo "⚠ WARNING: WebContent/WEB-INF/classes directory not found"
|
||||
fi
|
||||
|
||||
# 컨테이너 상태 확인
|
||||
echo "Checking container status..."
|
||||
docker-compose -f docker-compose.prod.yml up --build --force-recreate -d
|
||||
|
||||
Reference in New Issue
Block a user