Compare commits
37 Commits
feature/es
...
V202511170
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e21c83bf06 | ||
|
|
0b5b6a0d3f | ||
|
|
fd4283f3cf | ||
|
|
c1921855e6 | ||
| eff22bbc4c | |||
| 5a582862d6 | |||
|
|
61dbf15b0f | ||
| 789deac5da | |||
|
|
1f2bdee683 | ||
|
|
66968a4463 | ||
| ddcaf60e5e | |||
|
|
f2627d9683 | ||
| 514c360a78 | |||
|
|
08f5ba1cdb | ||
|
|
6432bab110 | ||
|
|
67f694be65 | ||
|
|
7195dfb5f1 | ||
|
|
c2f2350b83 | ||
|
|
849df44333 | ||
|
|
cf5806add5 | ||
|
|
b567dedcaa | ||
|
|
56aa05513c | ||
|
|
258ed89c84 | ||
|
|
32deed0726 | ||
|
|
76aeae96fc | ||
|
|
f9a6dd145a | ||
| 8e2092976c | |||
|
|
5d60957bca | ||
|
|
27daa36137 | ||
|
|
c394900a83 | ||
| 78281c5b86 | |||
|
|
479025bb79 | ||
|
|
606172fada | ||
|
|
fdd5346c99 | ||
| 68dc1f096a | |||
|
|
6b3a2c1cf1 | ||
| c366b71174 |
@@ -1,4 +1,4 @@
|
||||
FROM dockerhub.wace.me/tomcat:7.0.94-jre7-alpine.arm64 AS Development
|
||||
FROM dockerhub.wace.me/tomcat:7.0.94-jre8-alpine.arm64 AS Development
|
||||
|
||||
# Remove default webapps
|
||||
RUN rm -rf /usr/local/tomcat/webapps/*
|
||||
|
||||
@@ -2530,18 +2530,18 @@ SELECT option_objid::VARCHAR AS CODE
|
||||
AND PRODUCT_MGMT_OBJID::VARCHAR = #{codeId}::VARCHAR
|
||||
</select>
|
||||
|
||||
<select id="getRevNoselect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.OBJID::varchar AS CODE
|
||||
,T.REV AS NAME
|
||||
,T1.PRODUCT_CODE AS CODE_CD
|
||||
,'' AS STATUS
|
||||
,T.spec_name AS ID
|
||||
,'' AS EXT_VAL
|
||||
FROM PART_BOM_REPORT T,PRODUCT_MGMT T1
|
||||
WHERE T.PRODUCT_MGMT_OBJID = T1.OBJID
|
||||
AND T1.OBJID = #{code}::numeric
|
||||
ORDER BY T.REV
|
||||
<select id="getRevNoselect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.OBJID::varchar AS CODE
|
||||
,COALESCE(T.REVISION, T.REV, '1.0') AS NAME
|
||||
,T1.PRODUCT_CODE AS CODE_CD
|
||||
,'' AS STATUS
|
||||
,T.spec_name AS ID
|
||||
,'' AS EXT_VAL
|
||||
FROM PART_BOM_REPORT T,PRODUCT_MGMT T1
|
||||
WHERE T.PRODUCT_MGMT_OBJID = T1.OBJID
|
||||
AND T1.OBJID = #{code}::numeric
|
||||
ORDER BY COALESCE(T.REVISION, T.REV, '1.0')
|
||||
|
||||
</select>
|
||||
|
||||
@@ -3205,4 +3205,32 @@ SELECT option_objid::VARCHAR AS CODE
|
||||
WHERE USER_ID = #{userId}
|
||||
AND MASTER_OBJID::varchar = #{masterObjid}
|
||||
</select>
|
||||
|
||||
<!-- 고객사 정보 조회 -->
|
||||
<select id="getSupplyInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
SUPPLY_CODE,
|
||||
SUPPLY_NAME,
|
||||
REG_NO,
|
||||
SUPPLY_ADDRESS,
|
||||
SUPPLY_BUSNAME,
|
||||
SUPPLY_STOCKNAME,
|
||||
SUPPLY_TEL_NO,
|
||||
SUPPLY_FAX_NO,
|
||||
CHARGE_USER_NAME,
|
||||
PAYMENT_METHOD,
|
||||
MANAGER1_NAME,
|
||||
MANAGER1_EMAIL,
|
||||
MANAGER2_NAME,
|
||||
MANAGER2_EMAIL,
|
||||
MANAGER3_NAME,
|
||||
MANAGER3_EMAIL,
|
||||
MANAGER4_NAME,
|
||||
MANAGER4_EMAIL,
|
||||
MANAGER5_NAME,
|
||||
MANAGER5_EMAIL
|
||||
FROM SUPPLY_MNG
|
||||
WHERE OBJID = #{objId}::numeric
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -2870,8 +2870,9 @@
|
||||
ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 관리 목록 조회 -->
|
||||
<!-- M-BOM 관리 목록 조회 - 품목별로 나눠서 보이기 (판매관리와 동일) -->
|
||||
<select id="mBomMgmtGridList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
/* productionplanning.mBomMgmtGridList - 품목별로 나눠서 조회 (CONTRACT_ITEM 기준) */
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.CONTRACT_OBJID,
|
||||
@@ -2906,54 +2907,40 @@
|
||||
ELSE ''
|
||||
END
|
||||
) AS PAID_TYPE_NAME,
|
||||
COALESCE(PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PM.PART_NAME, '') AS PART_NAME,
|
||||
-- S/N: CONTRACT_ITEM_SERIAL에서 조회
|
||||
-- 품목 정보: CONTRACT_ITEM에서 가져오기 (품목별로 펼쳐서 보이기)
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
CI.PART_OBJID,
|
||||
-- S/N: 해당 품목의 시리얼 번호만 표시
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM CI
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
COALESCE(PM.QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 요청납기: CONTRACT_ITEM 우선, 없으면 PROJECT_MGMT, 없으면 CONTRACT_MGMT
|
||||
COALESCE(
|
||||
(SELECT CI.DUE_DATE
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE' LIMIT 1),
|
||||
PM.DUE_DATE,
|
||||
CM.req_del_date
|
||||
) AS REQ_DEL_DATE,
|
||||
-- 수량: CONTRACT_ITEM의 수량
|
||||
COALESCE(CI.ORDER_QUANTITY::numeric, PM.QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 요청납기: CONTRACT_ITEM 우선
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.req_del_date) AS REQ_DEL_DATE,
|
||||
-- 고객요청사항: CONTRACT_ITEM에서 가져옴
|
||||
COALESCE(
|
||||
(SELECT CI.CUSTOMER_REQUEST
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE' LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_REQUEST,
|
||||
-- E-BOM 정보: PM.PART_OBJID가 E-BOM OBJID를 직접 가리킴
|
||||
PM.PART_OBJID AS BOM_REPORT_OBJID,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- E-BOM 정보: CI.PART_OBJID가 E-BOM OBJID를 가리킴
|
||||
COALESCE(CI.PART_OBJID, PM.PART_OBJID) AS BOM_REPORT_OBJID,
|
||||
COALESCE(
|
||||
(SELECT PBR.STATUS
|
||||
FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = PM.PART_OBJID
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID)
|
||||
LIMIT 1),
|
||||
''
|
||||
) AS EBOM_STATUS,
|
||||
COALESCE(
|
||||
(SELECT TO_CHAR(PBR.REGDATE, 'YYYY-MM-DD')
|
||||
FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = PM.PART_OBJID
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID)
|
||||
LIMIT 1),
|
||||
''
|
||||
) AS EBOM_REGDATE,
|
||||
@@ -2963,18 +2950,27 @@
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
-- CONTRACT_ITEM과 LEFT JOIN하여 품목별로 펼쳐서 보이기
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 품번 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
AND (
|
||||
UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
OR UPPER(CI.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 품명 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
AND (
|
||||
UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
OR UPPER(CI.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
)
|
||||
</if>
|
||||
ORDER BY PM.REGDATE DESC
|
||||
ORDER BY PM.REGDATE DESC, CI.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- E-BOM을 PROJECT_MGMT에 할당 -->
|
||||
@@ -3003,4 +2999,299 @@
|
||||
LEFT JOIN USER_INFO UI ON UI.USER_ID = T.WRITER
|
||||
WHERE T.OBJID::VARCHAR = #{objid}
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 상세 조회 (PROJECT_MGMT + CONTRACT_MGMT 정보) -->
|
||||
<select id="getProjectMgmtDetail" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PROJECT_NO,
|
||||
PM.BOM_REPORT_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
CM.CATEGORY_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
''
|
||||
) AS CATEGORY_NAME,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.AREA_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.AREA_CD LIMIT 1),
|
||||
''
|
||||
) AS AREA_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID = CM.CUSTOMER_OBJID::NUMERIC LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
CM.PAID_TYPE,
|
||||
CM.REQ_DEL_DATE,
|
||||
TO_CHAR(PM.REGDATE, 'YYYY-MM-DD') AS RECEIPT_DATE,
|
||||
TO_CHAR(PM.REGDATE, 'YYYY-MM-DD') AS MBOM_REGDATE
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
PM.OBJID::VARCHAR = #{objId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- E-BOM 목록 조회 -->
|
||||
<select id="getEbomList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
T.OBJID,
|
||||
T.PRODUCT_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = T.PRODUCT_CD LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
T.PART_NO,
|
||||
T.PART_NAME,
|
||||
T.STATUS,
|
||||
T.REVISION,
|
||||
TO_CHAR(T.REGDATE, 'YYYY-MM-DD') AS REG_DATE,
|
||||
UI.USER_NAME AS WRITER_NAME,
|
||||
UI.DEPT_NAME,
|
||||
COALESCE(PM.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(PM.MAKER, '') AS SUPPLIER
|
||||
FROM
|
||||
PART_BOM_REPORT T
|
||||
LEFT JOIN USER_INFO UI ON UI.USER_ID = T.WRITER
|
||||
LEFT JOIN PART_MNG PM ON PM.PART_NO = T.PART_NO AND PM.STATUS = 'release'
|
||||
WHERE 1=1
|
||||
<!-- 품번, 품명이 비어있지 않은 것만 조회 -->
|
||||
AND T.PART_NO IS NOT NULL
|
||||
AND TRIM(T.PART_NO) != ''
|
||||
AND T.PART_NAME IS NOT NULL
|
||||
AND TRIM(T.PART_NAME) != ''
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(T.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
</if>
|
||||
<!-- 재료 검색 -->
|
||||
<if test="search_material != null and search_material != ''">
|
||||
AND UPPER(PM.MATERIAL) LIKE '%' || UPPER(#{search_material}) || '%'
|
||||
</if>
|
||||
<!-- 공급업체 검색 -->
|
||||
<if test="search_supplier != null and search_supplier != ''">
|
||||
AND UPPER(PM.MAKER) LIKE '%' || UPPER(#{search_supplier}) || '%'
|
||||
</if>
|
||||
ORDER BY T.REGDATE DESC
|
||||
LIMIT 100
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 목록 조회 -->
|
||||
<select id="getMbomList" resultType="map" parameterType="map">
|
||||
SELECT
|
||||
MH.OBJID,
|
||||
MH.MBOM_NO,
|
||||
MH.PART_NO,
|
||||
MH.PART_NAME,
|
||||
MH.SAVE_DATE,
|
||||
MH.CREATE_USER,
|
||||
MH.CREATE_DATE,
|
||||
MH.UPDATE_USER,
|
||||
MH.UPDATE_DATE
|
||||
FROM
|
||||
MBOM_HEADER MH
|
||||
WHERE 1=1
|
||||
<!-- 품번 검색 -->
|
||||
<if test="partNo != null and partNo != ''">
|
||||
AND UPPER(MH.PART_NO) LIKE '%' || UPPER(#{partNo}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="partName != null and partName != ''">
|
||||
AND UPPER(MH.PART_NAME) LIKE '%' || UPPER(#{partName}) || '%'
|
||||
</if>
|
||||
<!-- M-BOM 품번 검색 -->
|
||||
<if test="mbomPartNo != null and mbomPartNo != ''">
|
||||
AND UPPER(MH.MBOM_NO) LIKE '%' || UPPER(#{mbomPartNo}) || '%'
|
||||
</if>
|
||||
<!-- 저장일 검색 -->
|
||||
<if test="saveDate != null and saveDate != ''">
|
||||
AND DATE(MH.SAVE_DATE) = #{saveDate}
|
||||
</if>
|
||||
ORDER BY MH.SAVE_DATE DESC
|
||||
LIMIT 100
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 상세 데이터 조회 (프로젝트별) -->
|
||||
<select id="getMbomDetailByProject" resultType="map" parameterType="map">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.MBOM_HEADER_OBJID,
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
MD.QTY,
|
||||
MD.QTY_TEMP,
|
||||
MD.ITEM_QTY,
|
||||
MD.LEVEL,
|
||||
MD.REVISION,
|
||||
MD.SPEC,
|
||||
MD.PRODUCT_NAME,
|
||||
MD.STATUS_NAME,
|
||||
MD.LEVEL_1,
|
||||
MD.LEVEL_2,
|
||||
MD.LEVEL_3,
|
||||
MD.LEVEL_4,
|
||||
MD.LEVEL_5,
|
||||
MD.LEVEL_6,
|
||||
MD.LEVEL_7,
|
||||
MD.LEVEL_8,
|
||||
MD.LEVEL_9,
|
||||
MD.LEVEL_10
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
INNER JOIN
|
||||
MBOM_HEADER MH ON MD.MBOM_HEADER_OBJID = MH.OBJID
|
||||
WHERE
|
||||
MH.PROJECT_MGMT_OBJID = #{objId}
|
||||
ORDER BY
|
||||
MD.LEVEL, MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 헤더 저장 -->
|
||||
<insert id="insertMbomHeader" parameterType="map">
|
||||
<selectKey keyProperty="OBJID" resultType="string" order="BEFORE">
|
||||
SELECT REPLACE(UUID(),'-','') FROM DUAL
|
||||
</selectKey>
|
||||
INSERT INTO MBOM_HEADER (
|
||||
OBJID,
|
||||
MBOM_NO,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
SAVE_DATE,
|
||||
CREATE_USER,
|
||||
CREATE_DATE,
|
||||
UPDATE_USER,
|
||||
UPDATE_DATE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
CONCAT('MBOM-', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')),
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
NOW(),
|
||||
#{CREATE_USER},
|
||||
NOW(),
|
||||
#{UPDATE_USER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- M-BOM 상세 저장 -->
|
||||
<insert id="insertMbomDetail" parameterType="map">
|
||||
<selectKey keyProperty="OBJID" resultType="string" order="BEFORE">
|
||||
SELECT REPLACE(UUID(),'-','') FROM DUAL
|
||||
</selectKey>
|
||||
INSERT INTO MBOM_DETAIL (
|
||||
OBJID,
|
||||
MBOM_HEADER_OBJID,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
QTY,
|
||||
LEVEL,
|
||||
REVISION,
|
||||
SPEC,
|
||||
PRODUCT_NAME,
|
||||
STATUS_NAME,
|
||||
CREATE_USER,
|
||||
CREATE_DATE,
|
||||
UPDATE_USER,
|
||||
UPDATE_DATE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{MBOM_HEADER_OBJID},
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
#{QTY},
|
||||
#{LEVEL},
|
||||
#{REVISION},
|
||||
#{SPEC},
|
||||
#{PRODUCT_NAME},
|
||||
#{STATUS_NAME},
|
||||
#{CREATE_USER},
|
||||
NOW(),
|
||||
#{UPDATE_USER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- E-BOM을 M-BOM으로 복사 -->
|
||||
<insert id="saveMbomFromEbom" parameterType="map">
|
||||
/* productionplanning.saveMbomFromEbom - E-BOM을 M-BOM으로 복사 */
|
||||
/* 1. 새로운 PART_BOM_REPORT 생성 (M-BOM용) */
|
||||
WITH new_bom_report AS (
|
||||
INSERT INTO PART_BOM_REPORT (
|
||||
OBJID,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
STATUS
|
||||
) VALUES (
|
||||
(SELECT (FLOOR(RANDOM() * 1000000000) + 1000000000)::INTEGER),
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
#{USER_ID},
|
||||
NOW(),
|
||||
'Y'
|
||||
)
|
||||
RETURNING OBJID
|
||||
),
|
||||
/* 2. E-BOM의 BOM_PART_QTY 데이터를 새 M-BOM으로 복사 */
|
||||
copied_bom_data AS (
|
||||
INSERT INTO BOM_PART_QTY (
|
||||
BOM_REPORT_OBJID,
|
||||
OBJID,
|
||||
PARENT_OBJID,
|
||||
CHILD_OBJID,
|
||||
PARENT_PART_NO,
|
||||
PART_NO,
|
||||
QTY,
|
||||
ITEM_QTY,
|
||||
QTY_TEMP,
|
||||
REGDATE,
|
||||
WRITER,
|
||||
SEQ,
|
||||
STATUS,
|
||||
LAST_PART_OBJID
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM new_bom_report),
|
||||
(SELECT (FLOOR(RANDOM() * 1000000000) + 1000000000 + ROW_NUMBER() OVER (ORDER BY OBJID))::INTEGER),
|
||||
PARENT_OBJID,
|
||||
CHILD_OBJID,
|
||||
PARENT_PART_NO,
|
||||
PART_NO,
|
||||
QTY,
|
||||
ITEM_QTY,
|
||||
QTY_TEMP,
|
||||
NOW(),
|
||||
#{USER_ID},
|
||||
ROW_NUMBER() OVER (ORDER BY OBJID),
|
||||
'adding',
|
||||
LAST_PART_OBJID
|
||||
FROM BOM_PART_QTY
|
||||
WHERE BOM_REPORT_OBJID::VARCHAR = #{SOURCE_BOM_OBJID}
|
||||
AND COALESCE(STATUS, '') NOT IN ('deleting', 'deleted')
|
||||
RETURNING 1
|
||||
)
|
||||
/* 3. PROJECT_MGMT 업데이트 */
|
||||
UPDATE PROJECT_MGMT
|
||||
SET
|
||||
BOM_REPORT_OBJID = (SELECT OBJID FROM new_bom_report),
|
||||
MBOM_STATUS = 'Y',
|
||||
PART_NO = #{PART_NO},
|
||||
PART_NAME = #{PART_NAME}
|
||||
WHERE OBJID::VARCHAR = #{PROJECT_OBJID}
|
||||
</insert>
|
||||
</mapper>
|
||||
|
||||
@@ -7627,29 +7627,65 @@ SELECT
|
||||
<!-- //영업정보 수정시 프로젝트 정보 업데이트 -->
|
||||
<update id="ModifyProjectByContract" parameterType="map">
|
||||
UPDATE PROJECT_MGMT
|
||||
SET
|
||||
DUE_DATE = #{due_date}
|
||||
,CUSTOMER_PROJECT_NAME = #{customer_project_name}
|
||||
,LOCATION = #{location}
|
||||
,SETUP = #{setup}
|
||||
,FACILITY = #{facility}
|
||||
,FACILITY_TYPE = #{facility_type}
|
||||
,FACILITY_DEPTH = #{facility_depth}
|
||||
,CONTRACT_DATE = #{contract_date}
|
||||
,PO_NO = #{po_no}
|
||||
,PM_USER_ID = #{pm_user_id}
|
||||
,CONTRACT_CURRENCY = #{contract_currency}
|
||||
,CONTRACT_PRICE_CURRENCY = #{contract_price_currency}
|
||||
,CONTRACT_PRICE = #{contract_price}
|
||||
,PROJECT_NAME = #{project_name}
|
||||
,CONTRACT_DEL_DATE = #{contract_del_date}
|
||||
,REQ_DEL_DATE = #{req_del_date}
|
||||
,CONTRACT_COMPANY = #{contract_company}
|
||||
,MANUFACTURE_PLANT = #{manufacture_plant}
|
||||
,PART_OBJID = #{part_objid}
|
||||
,PART_NO = #{part_no}
|
||||
,PART_NAME = #{part_name}
|
||||
,QUANTITY = #{quantity}
|
||||
<set>
|
||||
<if test="due_date != null and due_date != ''">
|
||||
DUE_DATE = #{due_date},
|
||||
</if>
|
||||
<if test="customer_project_name != null and customer_project_name != ''">
|
||||
CUSTOMER_PROJECT_NAME = #{customer_project_name},
|
||||
</if>
|
||||
<if test="location != null and location != ''">
|
||||
LOCATION = #{location},
|
||||
</if>
|
||||
<if test="setup != null and setup != ''">
|
||||
SETUP = #{setup},
|
||||
</if>
|
||||
<if test="facility != null and facility != ''">
|
||||
FACILITY = #{facility},
|
||||
</if>
|
||||
<if test="facility_type != null and facility_type != ''">
|
||||
FACILITY_TYPE = #{facility_type},
|
||||
</if>
|
||||
<if test="facility_depth != null and facility_depth != ''">
|
||||
FACILITY_DEPTH = #{facility_depth},
|
||||
</if>
|
||||
<if test="contract_date != null and contract_date != ''">
|
||||
CONTRACT_DATE = #{contract_date},
|
||||
</if>
|
||||
<if test="po_no != null and po_no != ''">
|
||||
PO_NO = #{po_no},
|
||||
</if>
|
||||
<if test="pm_user_id != null and pm_user_id != ''">
|
||||
PM_USER_ID = #{pm_user_id},
|
||||
</if>
|
||||
<if test="contract_currency != null and contract_currency != ''">
|
||||
CONTRACT_CURRENCY = #{contract_currency},
|
||||
</if>
|
||||
<if test="contract_price_currency != null and contract_price_currency != ''">
|
||||
CONTRACT_PRICE_CURRENCY = #{contract_price_currency},
|
||||
</if>
|
||||
<if test="contract_price != null and contract_price != ''">
|
||||
CONTRACT_PRICE = #{contract_price},
|
||||
</if>
|
||||
<if test="project_name != null and project_name != ''">
|
||||
PROJECT_NAME = #{project_name},
|
||||
</if>
|
||||
<if test="contract_del_date != null and contract_del_date != ''">
|
||||
CONTRACT_DEL_DATE = #{contract_del_date},
|
||||
</if>
|
||||
<if test="req_del_date != null and req_del_date != ''">
|
||||
REQ_DEL_DATE = #{req_del_date},
|
||||
</if>
|
||||
<if test="contract_company != null and contract_company != ''">
|
||||
CONTRACT_COMPANY = #{contract_company},
|
||||
</if>
|
||||
<if test="manufacture_plant != null and manufacture_plant != ''">
|
||||
MANUFACTURE_PLANT = #{manufacture_plant},
|
||||
</if>
|
||||
<if test="quantity != null and quantity != ''">
|
||||
QUANTITY = #{quantity}
|
||||
</if>
|
||||
</set>
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
AND PART_OBJID = #{part_objid}
|
||||
</update>
|
||||
|
||||
@@ -523,13 +523,20 @@
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
,(SELECT objid FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID order by regdate desc limit 1) AS EST_OBJID
|
||||
-- 최근 차수 견적서 합계 정보
|
||||
,(SELECT TOTAL_AMOUNT FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT
|
||||
,(SELECT TOTAL_AMOUNT_KRW FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT_KRW
|
||||
-- 수주 합계 정보 (CONTRACT_MGMT 테이블에 저장된 값 사용)
|
||||
,T.ORDER_SUPPLY_PRICE AS ORDER_SUPPLY_PRICE_SUM
|
||||
,T.ORDER_VAT AS ORDER_VAT_SUM
|
||||
,T.ORDER_TOTAL_AMOUNT AS ORDER_TOTAL_AMOUNT_SUM
|
||||
-- 최근 차수 견적서 합계 정보
|
||||
,(SELECT TOTAL_AMOUNT FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT
|
||||
,(SELECT TOTAL_AMOUNT_KRW FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT_KRW
|
||||
-- 견적수량 (ESTIMATE_TEMPLATE_ITEM의 수량 합계)
|
||||
,(SELECT COALESCE(SUM(CAST(QUANTITY AS NUMERIC)), 0) FROM ESTIMATE_TEMPLATE_ITEM WHERE TEMPLATE_OBJID = (SELECT objid FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1)) AS ESTIMATE_QUANTITY
|
||||
-- 수주 합계 정보 (CONTRACT_MGMT 테이블에 저장된 값 사용)
|
||||
,T.ORDER_SUPPLY_PRICE AS ORDER_SUPPLY_PRICE_SUM
|
||||
,T.ORDER_VAT AS ORDER_VAT_SUM
|
||||
,T.ORDER_TOTAL_AMOUNT AS ORDER_TOTAL_AMOUNT_SUM
|
||||
-- 수주수량 (CONTRACT_MGMT의 QUANTITY 또는 CONTRACT_ITEM 합계)
|
||||
,COALESCE(
|
||||
NULLIF(T.QUANTITY, '')::NUMERIC,
|
||||
(SELECT COALESCE(SUM(CAST(QUANTITY AS NUMERIC)), 0) FROM CONTRACT_ITEM WHERE CONTRACT_OBJID = T.OBJID AND STATUS = 'ACTIVE')
|
||||
) AS ORDER_QUANTITY
|
||||
,CASE
|
||||
WHEN T.ORDER_TOTAL_AMOUNT IS NOT NULL AND T.ORDER_TOTAL_AMOUNT != ''
|
||||
AND T.EXCHANGE_RATE IS NOT NULL AND T.EXCHANGE_RATE != ''
|
||||
@@ -790,6 +797,102 @@
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 주문서관리 Total 합계 조회 (조회된 데이터 전체 합계) -->
|
||||
<select id="getContractGridTotalAmount" parameterType="map" resultType="map">
|
||||
/* contractMgmt.getContractGridTotalAmount */
|
||||
SELECT
|
||||
COALESCE(SUM(COALESCE(T.ORDER_TOTAL_AMOUNT_KRW, 0)), 0) AS "totalAmountKRW"
|
||||
FROM
|
||||
<include refid="contractBase"/> T
|
||||
WHERE 1=1
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND SUBSTR(CONTRACT_DATE,0,5) = #{Year}
|
||||
</if>
|
||||
|
||||
<if test="category_cd !=null and category_cd != '' ">
|
||||
AND category_cd = #{category_cd}
|
||||
</if>
|
||||
|
||||
<if test="customer_objid !=null and customer_objid != '' ">
|
||||
AND customer_objid = #{customer_objid}
|
||||
</if>
|
||||
|
||||
<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_result !=null and contract_result !=''">
|
||||
AND contract_result = #{contract_result}
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
AND pm_user_id = #{pm_user_id}
|
||||
</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 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>
|
||||
|
||||
<!-- 품번/품명 검색: PART_OBJID로 정확하게 검색 -->
|
||||
<if test="search_partObjId != null and search_partObjId != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = T.OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND CI.PART_OBJID = #{search_partObjId}
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_poNo != null and search_poNo != ''">
|
||||
AND UPPER(PO_NO) LIKE UPPER('%${search_poNo}%')
|
||||
</if>
|
||||
|
||||
<if test="order_start_date != null and !''.equals(order_start_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{order_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="order_end_date != null and !''.equals(order_end_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{order_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(DUE_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>
|
||||
</select>
|
||||
|
||||
<select id="contractList_bak" parameterType="map" resultType="map">
|
||||
SELECT *
|
||||
FROM (
|
||||
@@ -1411,8 +1514,11 @@
|
||||
SELECT
|
||||
A.OBJID
|
||||
,A.CATEGORY_CD
|
||||
,CODE_NAME(A.CATEGORY_CD) AS CATEGORY_NAME
|
||||
,A.CUSTOMER_OBJID
|
||||
,(SELECT SUPPLY_NAME FROM SUPPLY_MNG AS O WHERE O.OBJID = A.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME
|
||||
,A.PRODUCT
|
||||
,CODE_NAME(A.PRODUCT) AS PRODUCT_NAME
|
||||
,A.CUSTOMER_PROJECT_NAME
|
||||
,A.STATUS_CD
|
||||
,A.DUE_DATE
|
||||
@@ -1455,12 +1561,14 @@
|
||||
,A.EST_COMP_DATE
|
||||
,A.EST_RESULT_CD
|
||||
,A.AREA_CD
|
||||
,CODE_NAME(A.AREA_CD) AS AREA_NAME
|
||||
,A.TARGET_PROJECT_NO
|
||||
,A.TARGET_PROJECT_NO_DIRECT
|
||||
,A.CUSTOMER_PRODUCTION_NO
|
||||
,A.MECHANICAL_TYPE
|
||||
,A.OVERHAUL_ORDER
|
||||
,A.PAID_TYPE
|
||||
,(case when A.PAID_TYPE = 'paid' then '유상' when A.PAID_TYPE = 'free' then '무상' else A.PAID_TYPE end) AS PAID_TYPE_NAME
|
||||
,A.RECEIPT_DATE
|
||||
,A.PART_NO
|
||||
,A.PART_NAME
|
||||
@@ -3511,7 +3619,9 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
|
||||
<select id="getProjectListBycontractObjid" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
PROJECT_NAME
|
||||
OBJID,
|
||||
PROJECT_NAME,
|
||||
PROJECT_NO
|
||||
FROM
|
||||
PROJECT_MGMT
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
@@ -3870,7 +3980,14 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
WHERE
|
||||
OBJID::VARCHAR = #{objId}
|
||||
<choose>
|
||||
<when test="templateObjId != null and templateObjId != '' and templateObjId != '-1' and (objId == null or objId == '' or objId == '-1')">
|
||||
OBJID::VARCHAR = (SELECT CONTRACT_OBJID FROM ESTIMATE_TEMPLATE WHERE OBJID = #{templateObjId})
|
||||
</when>
|
||||
<otherwise>
|
||||
OBJID::VARCHAR = #{objId}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 목록 조회 (CONTRACT_OBJID 기준) -->
|
||||
@@ -3935,6 +4052,12 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
ET.TOTAL_AMOUNT_KRW,
|
||||
ET.MANAGER_NAME,
|
||||
ET.MANAGER_CONTACT,
|
||||
ET.PART_NAME,
|
||||
ET.PART_OBJID,
|
||||
ET.NOTES_CONTENT,
|
||||
ET.VALIDITY_PERIOD,
|
||||
ET.CATEGORIES_JSON,
|
||||
ET.GROUP1_SUBTOTAL,
|
||||
ET.WRITER,
|
||||
ET.REGDATE,
|
||||
ET.CHG_USER_ID,
|
||||
@@ -3960,12 +4083,19 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
ESTIMATE_TEMPLATE ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND ET.TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY ET.REGDATE DESC
|
||||
LIMIT 1
|
||||
<choose>
|
||||
<when test="templateObjId != null and templateObjId != '' and templateObjId != '-1'">
|
||||
ET.OBJID = #{templateObjId}
|
||||
</when>
|
||||
<otherwise>
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND ET.TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY ET.REGDATE DESC
|
||||
LIMIT 1
|
||||
</otherwise>
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (OBJID 기준) -->
|
||||
@@ -3991,6 +4121,13 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
ET.TOTAL_AMOUNT_KRW,
|
||||
ET.MANAGER_NAME,
|
||||
ET.MANAGER_CONTACT,
|
||||
ET.SHOW_TOTAL_ROW,
|
||||
ET.PART_NAME,
|
||||
ET.PART_OBJID,
|
||||
ET.NOTES_CONTENT,
|
||||
ET.VALIDITY_PERIOD,
|
||||
ET.CATEGORIES_JSON,
|
||||
ET.GROUP1_SUBTOTAL,
|
||||
ET.WRITER,
|
||||
TO_CHAR(ET.REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE,
|
||||
ET.CHG_USER_ID,
|
||||
@@ -4069,6 +4206,30 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 (PART_OBJID로) -->
|
||||
<select id="getEstimateTemplateItemByPartObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
PART_OBJID,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID = #{templateObjId}
|
||||
AND PART_OBJID = #{partObjId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 저장 -->
|
||||
<insert id="insertEstimateTemplate" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
@@ -4092,6 +4253,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
TOTAL_AMOUNT_KRW,
|
||||
MANAGER_NAME,
|
||||
MANAGER_CONTACT,
|
||||
SHOW_TOTAL_ROW,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
@@ -4117,6 +4279,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
#{total_amount_krw},
|
||||
#{manager_name},
|
||||
#{manager_contact},
|
||||
#{show_total_row},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
@@ -4145,6 +4308,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
TOTAL_AMOUNT_KRW = #{total_amount_krw},
|
||||
MANAGER_NAME = #{manager_name},
|
||||
MANAGER_CONTACT = #{manager_contact},
|
||||
SHOW_TOTAL_ROW = #{show_total_row},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
@@ -4202,6 +4366,67 @@ WHERE
|
||||
OBJID = #{template_objid}
|
||||
</update>
|
||||
|
||||
<!-- 장비 견적서 템플릿 신규 저장 (Template 2) -->
|
||||
<insert id="insertEstimateTemplate2" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR_DATE,
|
||||
RECIPIENT,
|
||||
PART_NAME,
|
||||
PART_OBJID,
|
||||
NOTES_CONTENT,
|
||||
VALIDITY_PERIOD,
|
||||
CATEGORIES_JSON,
|
||||
GROUP1_SUBTOTAL,
|
||||
TOTAL_AMOUNT,
|
||||
TOTAL_AMOUNT_KRW,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{template_objid},
|
||||
#{contract_objid},
|
||||
'2',
|
||||
#{executor_date},
|
||||
#{recipient},
|
||||
#{part_name},
|
||||
#{part_objid},
|
||||
#{notes_content},
|
||||
#{validity_period},
|
||||
#{categories_json},
|
||||
#{group1_subtotal},
|
||||
#{total_amount},
|
||||
#{total_amount_krw},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 장비 견적서 템플릿 수정 (Template 2) -->
|
||||
<update id="updateEstimateTemplate2" parameterType="map">
|
||||
UPDATE ESTIMATE_TEMPLATE
|
||||
SET
|
||||
EXECUTOR_DATE = #{executor_date},
|
||||
RECIPIENT = #{recipient},
|
||||
PART_NAME = #{part_name},
|
||||
PART_OBJID = #{part_objid},
|
||||
NOTES_CONTENT = #{notes_content},
|
||||
VALIDITY_PERIOD = #{validity_period},
|
||||
CATEGORIES_JSON = #{categories_json},
|
||||
GROUP1_SUBTOTAL = #{group1_subtotal},
|
||||
TOTAL_AMOUNT = #{total_amount},
|
||||
TOTAL_AMOUNT_KRW = #{total_amount_krw},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
OBJID = #{template_objid}
|
||||
</update>
|
||||
|
||||
<!-- 최종 차수 견적서 조회 (메일 발송용) -->
|
||||
<select id="getLatestEstimateTemplate" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
@@ -4359,14 +4584,130 @@ WHERE
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 주문서관리 Total 합계 조회 -->
|
||||
<select id="getOrderTotalAmount" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
COALESCE(SUM(COALESCE(T.ORDER_SUPPLY_PRICE_SUM, 0)), 0) AS TOTAL_SUPPLY_PRICE,
|
||||
COALESCE(SUM(COALESCE(T.ORDER_VAT_SUM, 0)), 0) AS TOTAL_VAT,
|
||||
COALESCE(SUM(COALESCE(T.ORDER_TOTAL_AMOUNT_SUM, 0)), 0) AS TOTAL_AMOUNT
|
||||
FROM
|
||||
<include refid="contractBase"/> T
|
||||
WHERE 1=1
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND SUBSTR(CONTRACT_DATE,0,5) = #{Year}
|
||||
</if>
|
||||
|
||||
<if test="category_cd !=null and category_cd != '' ">
|
||||
AND category_cd = #{category_cd}
|
||||
</if>
|
||||
|
||||
<if test="customer_objid !=null and customer_objid != '' ">
|
||||
AND customer_objid = #{customer_objid}
|
||||
</if>
|
||||
|
||||
<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_result !=null and contract_result !=''">
|
||||
AND contract_result = #{contract_result}
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
AND pm_user_id = #{pm_user_id}
|
||||
</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 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>
|
||||
|
||||
<!-- 품번/품명 검색: PART_OBJID로 정확하게 검색 -->
|
||||
<if test="search_partObjId != null and search_partObjId != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = T.OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND CI.PART_OBJID = #{search_partObjId}
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_poNo != null and search_poNo != ''">
|
||||
AND UPPER(PO_NO) LIKE UPPER('%${search_poNo}%')
|
||||
</if>
|
||||
|
||||
<if test="order_start_date != null and !''.equals(order_start_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{order_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="order_end_date != null and !''.equals(order_end_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{order_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(DUE_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>
|
||||
</select>
|
||||
|
||||
<!-- 영업정보 조회 (수주등록용) -->
|
||||
<select id="getContractInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_NO,
|
||||
CUSTOMER_OBJID,
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID = CONTRACT_MGMT.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME,
|
||||
-- 주문유형
|
||||
CATEGORY_CD,
|
||||
CODE_NAME(CATEGORY_CD) AS CATEGORY_NAME,
|
||||
-- 제품구분
|
||||
PRODUCT,
|
||||
CODE_NAME(PRODUCT) AS PRODUCT_NAME,
|
||||
-- 국내/해외
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
-- 유/무상
|
||||
PAID_TYPE,
|
||||
-- 접수일 (이미 날짜 형식이면 그대로, YYYYMMDD 형식이면 변환)
|
||||
CASE
|
||||
WHEN RECEIPT_DATE ~ '^\d{8}$' THEN TO_CHAR(TO_DATE(RECEIPT_DATE, 'YYYYMMDD'), 'YYYY-MM-DD')
|
||||
ELSE RECEIPT_DATE
|
||||
END AS RECEIPT_DATE,
|
||||
-- 환종/환율
|
||||
CONTRACT_CURRENCY,
|
||||
(SELECT CODE_NAME FROM TB_CODE WHERE CODE_ID = CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
EXCHANGE_RATE,
|
||||
QUANTITY,
|
||||
PART_NO,
|
||||
@@ -4592,8 +4933,8 @@ WHERE
|
||||
CI.CONTRACT_OBJID,
|
||||
CI.SEQ,
|
||||
CI.PART_OBJID,
|
||||
CI.PART_NO,
|
||||
CI.PART_NAME,
|
||||
COALESCE(NULLIF(CI.PART_NO, ''), PM.PART_NO) AS PART_NO,
|
||||
COALESCE(NULLIF(CI.PART_NAME, ''), PM.PART_NAME) AS PART_NAME,
|
||||
CI.QUANTITY,
|
||||
CI.DUE_DATE,
|
||||
CI.CUSTOMER_REQUEST,
|
||||
@@ -4607,6 +4948,8 @@ WHERE
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL CIS
|
||||
ON CI.OBJID = CIS.ITEM_OBJID
|
||||
AND CIS.STATUS = 'ACTIVE'
|
||||
LEFT JOIN PART_MNG PM
|
||||
ON CI.PART_OBJID = PM.OBJID
|
||||
WHERE
|
||||
CI.CONTRACT_OBJID = #{contractObjId}
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
@@ -4616,7 +4959,9 @@ WHERE
|
||||
CI.SEQ,
|
||||
CI.PART_OBJID,
|
||||
CI.PART_NO,
|
||||
CI.PART_NAME,
|
||||
CI.PART_NAME,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
CI.QUANTITY,
|
||||
CI.DUE_DATE,
|
||||
CI.CUSTOMER_REQUEST,
|
||||
|
||||
@@ -819,6 +819,7 @@
|
||||
T.OBJID,
|
||||
T.PROJECT_NO,
|
||||
T.CONTRACT_OBJID,
|
||||
T.SALES_DEADLINE_DATE,
|
||||
CODE_NAME(T.CATEGORY_CD) AS ORDER_TYPE,
|
||||
CODE_NAME(T.PRODUCT) AS PRODUCT_TYPE,
|
||||
CODE_NAME(T.AREA_CD) AS NATION,
|
||||
@@ -875,16 +876,32 @@
|
||||
(SELECT CM.PRODUCTION_STATUS FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PRODUCTION_STATUS,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 한 번에 가져오기)
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
-- 판매수량: 모든 분할 출하의 합계
|
||||
COALESCE(
|
||||
(SELECT SUM(sales_quantity)
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE T.PROJECT_NO || '%'),
|
||||
0
|
||||
) AS SALES_QUANTITY,
|
||||
COALESCE(SR.sales_unit_price, 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SR.sales_supply_price, 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SR.sales_vat, 0) AS SALES_VAT,
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT,
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT_KRW,
|
||||
-- 잔량 계산: 수주수량 - 판매수량
|
||||
COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0) AS REMAINING_QUANTITY,
|
||||
-- 잔량원화총액 계산: (수주수량 - 판매수량) * 판매단가
|
||||
(COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0)) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW,
|
||||
-- 잔량 계산: 수주수량 - shipment_log의 split_quantity 합계
|
||||
COALESCE(T.QUANTITY::numeric, 0) - COALESCE(
|
||||
(SELECT SUM(COALESCE(split_quantity, 0))
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.PROJECT_NO),
|
||||
0
|
||||
) AS REMAINING_QUANTITY,
|
||||
-- 잔량원화총액 계산: (수주수량 - shipment_log 합계) * 판매단가
|
||||
(COALESCE(T.QUANTITY::numeric, 0) - COALESCE(
|
||||
(SELECT SUM(COALESCE(split_quantity, 0))
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.PROJECT_NO),
|
||||
0
|
||||
)) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW,
|
||||
COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY) AS SALES_CURRENCY,
|
||||
CODE_NAME(COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY)) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(SR.sales_exchange_rate, T.CONTRACT_PRICE_CURRENCY::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
@@ -895,10 +912,10 @@
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT shipping_date) = 0 THEN ''
|
||||
WHEN COUNT(DISTINCT shipping_date) = 1 THEN TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD')
|
||||
ELSE TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD') || '외' || (COUNT(DISTINCT shipping_date) - 1)::TEXT
|
||||
ELSE TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD') || ' 외 ' || (COUNT(DISTINCT shipping_date) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.OBJID::VARCHAR
|
||||
WHERE target_objid = T.PROJECT_NO
|
||||
AND shipping_date IS NOT NULL
|
||||
AND UPPER(COALESCE(shipping_status, '')) != 'CANCELLED'),
|
||||
COALESCE(TO_CHAR(SR.shipping_date, 'YYYY-MM-DD'), '')
|
||||
@@ -910,12 +927,17 @@
|
||||
) AS MANAGER,
|
||||
COALESCE(SR.incoterms, '') AS INCOTERMS,
|
||||
T.SALES_STATUS,
|
||||
T.OBJID::VARCHAR AS SALE_NO,
|
||||
'ORIGINAL' AS RECORD_TYPE,
|
||||
'' AS SPLIT_LOG_ID
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
WHERE 1 = 1
|
||||
T.OBJID::VARCHAR AS SALE_NO,
|
||||
'ORIGINAL' AS RECORD_TYPE,
|
||||
'' AS SPLIT_LOG_ID,
|
||||
-- 거래명세서 존재 여부
|
||||
CASE WHEN EXISTS(
|
||||
SELECT 1 FROM NSWOS100_TBL
|
||||
WHERE OdOrderNo = T.PROJECT_NO
|
||||
) THEN 'Y' ELSE 'N' END AS HAS_TRANSACTION_STATEMENT
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
WHERE 1 = 1
|
||||
AND T.PROJECT_NO IS NOT NULL
|
||||
AND T.PROJECT_NO != ''
|
||||
<if test="orderType != null and orderType != ''">
|
||||
@@ -1397,29 +1419,12 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
NULL,
|
||||
</otherwise>
|
||||
</choose>
|
||||
#{shippingMethod},
|
||||
#{manager},
|
||||
#{incoterms},
|
||||
#{cretEmpNo}
|
||||
)
|
||||
ON CONFLICT (project_no)
|
||||
DO UPDATE SET
|
||||
shipping_order_status = EXCLUDED.shipping_order_status,
|
||||
serial_no = EXCLUDED.serial_no,
|
||||
sales_quantity = EXCLUDED.sales_quantity,
|
||||
sales_unit_price = EXCLUDED.sales_unit_price,
|
||||
sales_supply_price = EXCLUDED.sales_supply_price,
|
||||
sales_vat = EXCLUDED.sales_vat,
|
||||
sales_total_amount = EXCLUDED.sales_total_amount,
|
||||
sales_currency = EXCLUDED.sales_currency,
|
||||
sales_exchange_rate = EXCLUDED.sales_exchange_rate,
|
||||
shipping_date = EXCLUDED.shipping_date,
|
||||
shipping_method = EXCLUDED.shipping_method,
|
||||
manager_user_id = EXCLUDED.manager_user_id,
|
||||
incoterms = EXCLUDED.incoterms,
|
||||
upd_date = NOW(),
|
||||
upd_user_id = EXCLUDED.reg_user_id
|
||||
</insert>
|
||||
#{shippingMethod},
|
||||
#{manager},
|
||||
#{incoterms},
|
||||
#{cretEmpNo}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!--
|
||||
/**
|
||||
@@ -1488,9 +1493,15 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
AND UPPER(STATUS) = 'ACTIVE'
|
||||
) THEN 'Y' ELSE 'N' END AS ORDER_ATTACH,
|
||||
(SELECT CM.PRODUCTION_STATUS FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PRODUCTION_STATUS,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 가져오기)
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 가져오기)
|
||||
SR.sale_no AS SALE_NO,
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
|
||||
-- 주문수량 (PROJECT_MGMT에서 가져오기) - 잔량 계산용
|
||||
COALESCE(T.QUANTITY::NUMERIC, 0) AS ORDER_QUANTITY,
|
||||
|
||||
-- 판매수량 (sales_registration에서 가져오기) - 이미 판매한 수량
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
COALESCE(SR.sales_unit_price, 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SR.sales_supply_price, 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SR.sales_vat, 0) AS SALES_VAT,
|
||||
@@ -1498,13 +1509,16 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT_KRW,
|
||||
COALESCE(NULLIF(SR.sales_currency, ''), CM.CONTRACT_CURRENCY) AS SALES_CURRENCY,
|
||||
CODE_NAME(COALESCE(NULLIF(SR.sales_currency, ''), CM.CONTRACT_CURRENCY)) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(NULLIF(SR.sales_exchange_rate, 0), CM.EXCHANGE_RATE::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
COALESCE(NULLIF(SR.sales_exchange_rate, 0), NULLIF(CM.EXCHANGE_RATE, '')::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
COALESCE(TO_CHAR(SR.shipping_date, 'YYYY-MM-DD'), '') AS SHIPPING_DATE,
|
||||
COALESCE(SR.shipping_method, '') AS SHIPPING_METHOD,
|
||||
COALESCE(SR.manager_user_id, T.PM_USER_ID) AS MANAGER,
|
||||
COALESCE(SR.incoterms, '') AS INCOTERMS
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
<if test="saleNo != null and saleNo != ''">
|
||||
AND SR.sale_no = #{saleNo}::integer
|
||||
</if>
|
||||
LEFT JOIN CONTRACT_MGMT CM ON CM.OBJID::VARCHAR = T.CONTRACT_OBJID
|
||||
WHERE T.PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
@@ -1566,40 +1580,43 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
-->
|
||||
<select id="getOrderDataByOrderNo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getOrderDataByOrderNo - orderNo로 판매등록용 수주 데이터 조회 */
|
||||
SELECT
|
||||
-- 기본 정보
|
||||
CM.CONTRACT_NO AS ORDER_NO,
|
||||
CM.OBJID AS CONTRACT_OBJID,
|
||||
|
||||
-- 수주 금액 정보 (CONTRACT_ITEM 테이블에서 합산) - VARCHAR 타입이므로 NUMERIC으로 캐스팅
|
||||
COALESCE(SUM(CI.ORDER_QUANTITY::NUMERIC), 0) AS SALES_QUANTITY,
|
||||
COALESCE(ROUND(AVG(CI.ORDER_UNIT_PRICE::NUMERIC), 2), 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SUM(CI.ORDER_SUPPLY_PRICE::NUMERIC), 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SUM(CI.ORDER_VAT::NUMERIC), 0) AS SALES_VAT,
|
||||
COALESCE(SUM(CI.ORDER_TOTAL_AMOUNT::NUMERIC), 0) AS SALES_TOTAL_AMOUNT,
|
||||
|
||||
-- 환종 정보
|
||||
CM.CONTRACT_CURRENCY AS SALES_CURRENCY,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(CM.EXCHANGE_RATE::NUMERIC, 0) AS SALES_EXCHANGE_RATE,
|
||||
|
||||
-- 수주 날짜 - VARCHAR 타입이므로 그대로 사용
|
||||
CM.ORDER_DATE AS SHIPPING_DATE,
|
||||
|
||||
-- 담당자
|
||||
CM.PM_USER_ID AS MANAGER
|
||||
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID AND UPPER(CI.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
GROUP BY
|
||||
CM.CONTRACT_NO,
|
||||
CM.OBJID,
|
||||
CM.CONTRACT_CURRENCY,
|
||||
CM.EXCHANGE_RATE,
|
||||
CM.ORDER_DATE,
|
||||
CM.PM_USER_ID
|
||||
SELECT
|
||||
-- 기본 정보
|
||||
CM.CONTRACT_NO AS ORDER_NO,
|
||||
CM.OBJID AS CONTRACT_OBJID,
|
||||
|
||||
-- 수주 수량 정보 (PROJECT_MGMT에서 직접 가져오기)
|
||||
COALESCE(PM.QUANTITY::NUMERIC, 0) AS SALES_QUANTITY,
|
||||
|
||||
-- 수주 금액 정보 (CONTRACT_ITEM 테이블에서 합산) - VARCHAR 타입이므로 NULLIF로 빈 문자열 제거 후 NUMERIC 캐스팅
|
||||
COALESCE(ROUND(AVG(NULLIF(CI.ORDER_UNIT_PRICE, '')::NUMERIC), 2), 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_SUPPLY_PRICE, '')::NUMERIC), 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_VAT, '')::NUMERIC), 0) AS SALES_VAT,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_TOTAL_AMOUNT, '')::NUMERIC), 0) AS SALES_TOTAL_AMOUNT,
|
||||
|
||||
-- 환종 정보
|
||||
CM.CONTRACT_CURRENCY AS SALES_CURRENCY,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(NULLIF(CM.EXCHANGE_RATE, '')::NUMERIC, 0) AS SALES_EXCHANGE_RATE,
|
||||
|
||||
-- 수주 날짜 - VARCHAR 타입이므로 그대로 사용
|
||||
CM.ORDER_DATE AS SHIPPING_DATE,
|
||||
|
||||
-- 담당자
|
||||
CM.PM_USER_ID AS MANAGER
|
||||
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID AND UPPER(CI.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
GROUP BY
|
||||
CM.CONTRACT_NO,
|
||||
CM.OBJID,
|
||||
CM.CONTRACT_CURRENCY,
|
||||
CM.EXCHANGE_RATE,
|
||||
CM.ORDER_DATE,
|
||||
CM.PM_USER_ID,
|
||||
PM.QUANTITY
|
||||
</select>
|
||||
|
||||
<!--
|
||||
@@ -1619,5 +1636,342 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 모든 분할 출하의 총 판매 수량 조회 -->
|
||||
<select id="getTotalSalesQuantity" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getTotalSalesQuantity - project_no로 시작하는 모든 레코드의 판매 수량 합계 */
|
||||
SELECT COALESCE(SUM(
|
||||
CASE
|
||||
WHEN sales_quantity IS NULL THEN 0
|
||||
WHEN TRIM(CAST(sales_quantity AS TEXT)) = '' THEN 0
|
||||
ELSE CAST(sales_quantity AS NUMERIC)
|
||||
END
|
||||
), 0) as total
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE #{orderNo} || '%'
|
||||
</select>
|
||||
|
||||
<!-- shipment_log에서 총 출하 수량 조회 -->
|
||||
<select id="getTotalShippedQuantity" parameterType="map" resultType="int">
|
||||
/* salesNcollectMgmt.getTotalShippedQuantity - shipment_log의 split_quantity 합계 */
|
||||
SELECT COALESCE(SUM(split_quantity), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 기본 정보 조회 (CONTRACT_OBJID 포함) -->
|
||||
<select id="getProjectInfo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getProjectInfo - PROJECT_MGMT의 상세 정보 조회 (최신 1개) */
|
||||
SELECT
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
-- 요청납기 (CONTRACT_ITEM의 DUE_DATE 우선, 없으면 PROJECT_MGMT.DUE_DATE)
|
||||
COALESCE(
|
||||
(SELECT CI.DUE_DATE
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1),
|
||||
PM.DUE_DATE
|
||||
) AS REQ_DEL_DATE,
|
||||
-- S/N 조회 (CONTRACT_ITEM_SERIAL에서)
|
||||
(SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM CI
|
||||
JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
) AS SERIAL_NO,
|
||||
-- 고객요청사항 (CONTRACT_ITEM에서)
|
||||
(SELECT CI.CUSTOMER_REQUEST
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1
|
||||
) AS CUSTOMER_REQUEST,
|
||||
-- 반납사유 (CONTRACT_ITEM에서)
|
||||
(SELECT CI.RETURN_REASON
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1
|
||||
) AS RETURN_REASON
|
||||
FROM PROJECT_MGMT PM
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
ORDER BY PM.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- sales_registration 개수 조회 (분할 출하 순번용) -->
|
||||
<select id="getSaleRegistrationCount" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getSaleRegistrationCount - project_no로 시작하는 레코드 개수 */
|
||||
SELECT COUNT(*) as count
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE #{orderNo} || '%'
|
||||
</select>
|
||||
|
||||
<!-- sales_registration DELETE (기존 데이터 삭제) -->
|
||||
<delete id="deleteSaleRegistration" parameterType="map">
|
||||
/* salesNcollectMgmt.deleteSaleRegistration - sales_registration 삭제 */
|
||||
DELETE FROM sales_registration
|
||||
WHERE project_no = #{orderNo}
|
||||
</delete>
|
||||
|
||||
<!-- sales_registration UPDATE (기존 데이터 수정) -->
|
||||
<update id="updateSaleRegistration" parameterType="map">
|
||||
/* salesNcollectMgmt.updateSaleRegistration - sales_registration 업데이트 */
|
||||
UPDATE sales_registration
|
||||
SET
|
||||
shipping_order_status = <choose>
|
||||
<when test="shippingOrderStatus != null and shippingOrderStatus != ''">
|
||||
#{shippingOrderStatus},
|
||||
</when>
|
||||
<otherwise>
|
||||
'',
|
||||
</otherwise>
|
||||
</choose>
|
||||
serial_no = #{serialNo},
|
||||
sales_quantity = #{salesQuantity}::integer,
|
||||
sales_unit_price = #{salesUnitPrice}::numeric,
|
||||
sales_supply_price = #{salesSupplyPrice}::numeric,
|
||||
sales_vat = #{salesVat}::numeric,
|
||||
sales_total_amount = #{salesTotalAmount}::numeric,
|
||||
sales_currency = #{salesCurrency},
|
||||
sales_exchange_rate = #{salesExchangeRate}::numeric,
|
||||
shipping_date = <choose>
|
||||
<when test="shippingDate != null and shippingDate != ''">
|
||||
TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
|
||||
</when>
|
||||
<otherwise>
|
||||
NULL,
|
||||
</otherwise>
|
||||
</choose>
|
||||
shipping_method = #{shippingMethod},
|
||||
manager_user_id = #{manager},
|
||||
incoterms = #{incoterms},
|
||||
upd_date = NOW(),
|
||||
upd_user_id = #{cretEmpNo}
|
||||
WHERE project_no = #{orderNo}
|
||||
</update>
|
||||
|
||||
<!-- ========================================
|
||||
분할 출하 관련 쿼리 (shipment_log 테이블 활용)
|
||||
======================================== -->
|
||||
|
||||
<!-- shipment_log의 split_quantity 합산 조회 -->
|
||||
<select id="getShipmentLogTotal" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getShipmentLogTotal - shipment_log의 split_quantity 합산 */
|
||||
SELECT COALESCE(SUM(split_quantity), 0) as total
|
||||
FROM shipment_log SL
|
||||
INNER JOIN project_mgmt PM ON SL.target_objid = PM.OBJID::VARCHAR
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
|
||||
<!-- shipment_log에 분할 출하 기록 저장 -->
|
||||
<insert id="insertShipmentLog" parameterType="map">
|
||||
/* salesNcollectMgmt.insertShipmentLog - 분할 출하 기록 저장 */
|
||||
INSERT INTO shipment_log (
|
||||
target_objid, log_type, log_message, split_quantity, original_quantity,
|
||||
remaining_quantity, shipping_status, shipping_date, shipping_method,
|
||||
sales_unit_price, sales_supply_price, sales_vat, sales_total_amount,
|
||||
sales_currency, sales_exchange_rate, manager_user_id, incoterms,
|
||||
serial_no, parent_sale_no, reg_user_id
|
||||
) VALUES (
|
||||
#{targetObjid}, 'SPLIT_SHIPMENT', '분할 출하',
|
||||
#{salesQuantity}::integer, #{originalQuantity}::integer, #{remainingQuantity}::integer,
|
||||
#{shippingOrderStatus},
|
||||
<choose>
|
||||
<when test="shippingDate != null and shippingDate != ''">
|
||||
TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
|
||||
</when>
|
||||
<otherwise>NULL,</otherwise>
|
||||
</choose>
|
||||
#{shippingMethod}, #{salesUnitPrice}::numeric, #{salesSupplyPrice}::numeric,
|
||||
#{salesVat}::numeric, #{salesTotalAmount}::numeric, #{salesCurrency},
|
||||
#{salesExchangeRate}::numeric, #{managerUserId}, #{incoterms}, #{serialNo},
|
||||
#{parentSaleNo}::integer, #{cretEmpNo}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- sales_registration의 수량을 shipment_log 합계로 업데이트 -->
|
||||
<update id="updateSalesQuantityFromShipmentLog" parameterType="map">
|
||||
/* salesNcollectMgmt.updateSalesQuantityFromShipmentLog - shipment_log 합계로 sales_quantity 업데이트 */
|
||||
UPDATE sales_registration
|
||||
SET sales_quantity = (
|
||||
SELECT COALESCE(SUM(split_quantity), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_supply_price = (
|
||||
SELECT COALESCE(SUM(sales_supply_price), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_vat = (
|
||||
SELECT COALESCE(SUM(sales_vat), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_total_amount = (
|
||||
SELECT COALESCE(SUM(sales_total_amount), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
)
|
||||
WHERE sale_no = #{saleNo}
|
||||
</update>
|
||||
|
||||
<!-- PROJECT_MGMT의 OBJID 조회 (shipment_log의 target_objid로 사용) -->
|
||||
<select id="getProjectObjid" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getProjectObjid - PROJECT_MGMT의 OBJID 조회 */
|
||||
SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
|
||||
<!-- 출하일 상세 내역 조회 (모든 분할 출하 포함) -->
|
||||
<select id="getShippingDetailList" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getShippingDetailList - shipment_log에서 모든 분할 출하 조회 */
|
||||
SELECT
|
||||
COALESCE(TO_CHAR(SL.shipping_date, 'YYYY-MM-DD'), '미등록') AS shipping_date,
|
||||
COALESCE(SL.split_quantity, 0) AS shipping_quantity,
|
||||
COALESCE(SL.shipping_status, '미등록') AS shipping_order_status,
|
||||
COALESCE(SL.serial_no, '-') AS serial_no,
|
||||
SL.target_objid AS project_no,
|
||||
'분할 출하 ' || SL.log_id AS source,
|
||||
TO_CHAR(SL.reg_date, 'YYYY-MM-DD HH24:MI:SS') AS reg_date
|
||||
FROM shipment_log SL
|
||||
WHERE SL.target_objid = #{projectNo}
|
||||
ORDER BY SL.shipping_date DESC, SL.log_id DESC
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 - 고객 정보 조회 -->
|
||||
<select id="getCustomerInfoByProjectNo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getCustomerInfoByProjectNo - 프로젝트 번호로 고객 정보 조회 */
|
||||
SELECT
|
||||
SM.SUPPLY_NAME AS CUSTOMER_NAME,
|
||||
SM.BUSINESS_NO AS CUSTOMER_REG_NO,
|
||||
SM.ADDRESS AS CUSTOMER_ADDRESS,
|
||||
SM.BUSINESS_TYPE AS CUSTOMER_BUSINESS,
|
||||
SM.BUSINESS_ITEM AS CUSTOMER_TYPE,
|
||||
SM.TEL_NO AS CUSTOMER_CONTACT
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN SUPPLY_MNG SM ON PM.CUSTOMER_OBJID::NUMERIC = SM.OBJID
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 - 품목 정보 조회 -->
|
||||
<select id="getTransactionStatementItem" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getTransactionStatementItem - 프로젝트 번호로 품목 정보 조회 */
|
||||
SELECT
|
||||
PM.PART_NAME AS productName,
|
||||
PM.PART_NO AS spec,
|
||||
COALESCE(SR.sales_quantity, PM.QUANTITY) AS quantity,
|
||||
COALESCE(SR.sales_unit_price, 0) AS unitPrice,
|
||||
COALESCE(SR.sales_supply_price, 0) AS supplyPrice,
|
||||
COALESCE(SR.sales_vat, 0) AS vat
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN sales_registration SR ON PM.PROJECT_NO = SR.project_no
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 저장 - NSWOS100_TBL 테이블 사용 -->
|
||||
<insert id="saveTransactionStatement" parameterType="map">
|
||||
/* salesNcollectMgmt.saveTransactionStatement - 거래명세서 저장 */
|
||||
INSERT INTO NSWOS100_TBL (
|
||||
SuVndCd /* 업체코드 */
|
||||
,IssueDt /* 작성일자 */
|
||||
,IssueNo /* 거래명세서번호 */
|
||||
,IsNo /* 순번 */
|
||||
,ProdCd /* 기종코드 */
|
||||
,OdOrderNo /* 발주번호 */
|
||||
,ImItemId /* 품번 */
|
||||
,RmDueDt /* 납기일자 */
|
||||
,RmOrderQty /* 발주수량 */
|
||||
,RmRcptQty /* 입고처리수량 */
|
||||
,RmRemQty /* 잔량 */
|
||||
,IsDt /* 납기일자 */
|
||||
,IsQty /* 납품수량 */
|
||||
,IsPrice /* 납품단가 */
|
||||
,IsAmount /* 납품금액 */
|
||||
) VALUES (
|
||||
#{suVndCd} /* 업체코드 */
|
||||
,#{issueDt} /* 작성일자 */
|
||||
,#{issueNo}::integer /* 거래명세서번호 */
|
||||
,#{isNo}::integer /* 순번 */
|
||||
,COALESCE(#{prodCd}, '') /* 기종코드 */
|
||||
,COALESCE(#{odOrderNo}, '') /* 발주번호 */
|
||||
,COALESCE(#{imItemId}, '') /* 품번 */
|
||||
,COALESCE(#{rmDueDt}, '') /* 납기일자 */
|
||||
,COALESCE(#{rmOrderQty}, 0)::integer /* 발주수량 */
|
||||
,COALESCE(#{rmRcptQty}, 0)::integer /* 입고처리수량 */
|
||||
,COALESCE(#{rmRemQty}, 0)::integer /* 잔량 */
|
||||
,COALESCE(#{isDt}, '') /* 납기일자 */
|
||||
,COALESCE(#{isQty}, 0)::integer /* 납품수량 */
|
||||
,COALESCE(#{isPrice}, 0)::numeric /* 납품단가 */
|
||||
,COALESCE(#{isAmount}, 0)::numeric /* 납품금액 */
|
||||
) ON CONFLICT (SuVndCd, IssueDt, IssueNo, IsNo) DO
|
||||
UPDATE SET
|
||||
ProdCd = COALESCE(#{prodCd}, '')
|
||||
,OdOrderNo = COALESCE(#{odOrderNo}, '')
|
||||
,ImItemId = COALESCE(#{imItemId}, '')
|
||||
,RmDueDt = COALESCE(#{rmDueDt}, '')
|
||||
,RmOrderQty = COALESCE(#{rmOrderQty}, 0)::integer
|
||||
,RmRcptQty = COALESCE(#{rmRcptQty}, 0)::integer
|
||||
,RmRemQty = COALESCE(#{rmRemQty}, 0)::integer
|
||||
,IsDt = COALESCE(#{isDt}, '')
|
||||
,IsQty = COALESCE(#{isQty}, 0)::integer
|
||||
,IsPrice = COALESCE(#{isPrice}, 0)::numeric
|
||||
,IsAmount = COALESCE(#{isAmount}, 0)::numeric
|
||||
</insert>
|
||||
|
||||
<!-- 거래명세서 번호 생성 -->
|
||||
<select id="getNextTransactionStatementNo" parameterType="map" resultType="int">
|
||||
/* salesNcollectMgmt.getNextTransactionStatementNo - 거래명세서 번호 생성 */
|
||||
SELECT COALESCE(MAX(IssueNo), 0) + 1 AS nextNo
|
||||
FROM NSWOS100_TBL
|
||||
WHERE SuVndCd = #{suVndCd}
|
||||
AND IssueDt = #{issueDt}
|
||||
</select>
|
||||
|
||||
<select id="getAllSerialNumbers" parameterType="map" resultType="string">
|
||||
/* salesNcollectMgmt.getAllSerialNumbers - 프로젝트의 모든 S/N 조회 */
|
||||
SELECT CIS.SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
ORDER BY CIS.SERIAL_NO
|
||||
</select>
|
||||
|
||||
<select id="getSavedTransactionStatement" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getSavedTransactionStatement - 저장된 거래명세서 조회 */
|
||||
SELECT
|
||||
SuVndCd,
|
||||
IssueDt,
|
||||
IssueNo,
|
||||
IsNo,
|
||||
ProdCd,
|
||||
OdOrderNo,
|
||||
ImItemId,
|
||||
RmDueDt,
|
||||
RmOrderQty,
|
||||
RmRcptQty,
|
||||
RmRemQty,
|
||||
IsDt,
|
||||
IsQty,
|
||||
IsPrice,
|
||||
IsAmount
|
||||
FROM NSWOS100_TBL
|
||||
WHERE OdOrderNo = #{projectNo}
|
||||
ORDER BY IsNo
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
|
||||
@@ -246,9 +246,23 @@ var columns = [
|
||||
return dueDate;
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주수량', field : 'ORDER_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '88', title : '국내/해외', field : 'AREA_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
@@ -457,10 +471,19 @@ function _fnc_datepick(){
|
||||
function fn_delete(){
|
||||
var checkedObj = _tabulGrid.getSelectedData();
|
||||
if(0 < checkedObj.length){
|
||||
var objId = fnc_checkNull(checkedObj[0].OBJID);
|
||||
//if(confirm("선택한 정보를 삭제하시겠습니까?")){
|
||||
// 선택된 모든 항목의 OBJID를 배열로 수집
|
||||
var objIds = [];
|
||||
for(var i = 0; i < checkedObj.length; i++){
|
||||
objIds.push(fnc_checkNull(checkedObj[i].OBJID));
|
||||
}
|
||||
|
||||
var deleteCount = objIds.length;
|
||||
var confirmMessage = deleteCount === 1
|
||||
? '선택한 견적요청정보를 삭제하시겠습니까?'
|
||||
: '선택한 ' + deleteCount + '개의 견적요청정보를 삭제하시겠습니까?';
|
||||
|
||||
Swal.fire({
|
||||
title: '선택한 고객정보를 삭제하시겠습니까?',
|
||||
title: confirmMessage,
|
||||
text: '',
|
||||
icon: 'warning',
|
||||
|
||||
@@ -474,17 +497,21 @@ function fn_delete(){
|
||||
}).then(result => {
|
||||
// 만약 Promise리턴을 받으면,
|
||||
if (result.isConfirmed) { // 만약 모달창에서 confirm 버튼을 눌렀다면
|
||||
//var param = $("#form1").serialize();
|
||||
// 여러 개의 objId를 배열로 전송
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : "/contractMgmt/deleteContractMngInfo.do",
|
||||
data: {
|
||||
"objId":objId
|
||||
"objId": objIds
|
||||
},
|
||||
traditional: true, // 배열 파라미터를 올바르게 전송
|
||||
dataType:"json",
|
||||
success:function(data){
|
||||
if(data.result == 'true'){
|
||||
Swal.fire("삭제되었습니다.");
|
||||
var successMessage = deleteCount === 1
|
||||
? '삭제되었습니다.'
|
||||
: deleteCount + '개의 항목이 삭제되었습니다.';
|
||||
Swal.fire(successMessage);
|
||||
fn_search();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1993,21 +1993,21 @@
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 품목정보 영역 -->
|
||||
<div class="form_popup_title" style="margin-top:15px;">
|
||||
<span>품목정보</span>
|
||||
<button type="button" id="btnAddItem" class="plm_btns" style="float:right; margin-top:-5px;">품목 추가</button>
|
||||
</div>
|
||||
<table class="">
|
||||
<colgroup>
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="max-height:300px; overflow-y:auto;">
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
</table>
|
||||
|
||||
<!-- 품목정보 영역 -->
|
||||
<div class="form_popup_title" style="margin-top:15px;">
|
||||
<span>품목정보</span>
|
||||
<button type="button" id="btnAddItem" class="plm_btns" style="float:right; margin-top:-5px;">품목 추가</button>
|
||||
</div>
|
||||
<table class="">
|
||||
<colgroup>
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="max-height:300px; overflow-y:auto;">
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
<colgroup>
|
||||
<col width="4%" /> <!-- 번호 -->
|
||||
<col width="12%" /> <!-- 품번 -->
|
||||
|
||||
@@ -24,6 +24,11 @@ $(document).ready(function(){
|
||||
//날짜
|
||||
_fnc_datepick();
|
||||
|
||||
// 그리드 높이 동적 계산 (Total 합계 영역 + 여유 공간 80px)
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
$(window).resize(function() {
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
});
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
@@ -70,6 +75,32 @@ $(document).ready(function(){
|
||||
}
|
||||
});
|
||||
|
||||
//결재상신
|
||||
$("#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_ORDER&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//엔터 조회
|
||||
$("input").keyup(function(e){
|
||||
@@ -96,14 +127,14 @@ $(document).ready(function(){
|
||||
});
|
||||
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:40, frozen:true},
|
||||
{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);
|
||||
}
|
||||
},
|
||||
// rowSelection 제거 - fnc_tabul_search의 showCheck 파라미터로 자동 추가됨
|
||||
{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);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주일', field : 'ORDER_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주번호', field : 'PO_NO' },
|
||||
@@ -122,9 +153,23 @@ var columns = [
|
||||
return dueDate;
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주수량', field : 'ORDER_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '수주상태', field : 'CONTRACT_RESULT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '120', title : '공급가액', field : 'ORDER_SUPPLY_PRICE_SUM',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
@@ -182,64 +227,49 @@ var columns = [
|
||||
|
||||
//var grid;
|
||||
function fn_search(){
|
||||
// 그리드 조회 및 Total 합계 업데이트를 위한 커스텀 AJAX
|
||||
$.ajax({
|
||||
url: "/contractMgmt/contractGridList.do",
|
||||
type: "POST",
|
||||
data: $("#form1").serializeObject(),
|
||||
dataType: "json",
|
||||
beforeSend: function(){
|
||||
_startLoading("Loading...");
|
||||
},
|
||||
complete: function(){
|
||||
_endLoading();
|
||||
},
|
||||
success: function(response) {
|
||||
// 그리드 데이터 설정
|
||||
if(_tabulGrid){
|
||||
_tabulGrid.setData(response.RESULTLIST || []);
|
||||
} else {
|
||||
// 그리드 초기화
|
||||
_tabulGrid = new Tabulator("#mainGrid", {
|
||||
layout: _tabul_layout_fitColumns,
|
||||
columns: columns,
|
||||
data: response.RESULTLIST || [],
|
||||
selectable: true
|
||||
});
|
||||
}
|
||||
|
||||
// 조회된 전체 데이터의 합계 계산
|
||||
var totalSupplyPrice = 0;
|
||||
var totalVat = 0;
|
||||
var totalAmount = 0;
|
||||
|
||||
if(response.RESULTLIST && response.RESULTLIST.length > 0) {
|
||||
response.RESULTLIST.forEach(function(row) {
|
||||
var supplyPrice = parseFloat(row.ORDER_SUPPLY_PRICE_SUM || 0);
|
||||
var vat = parseFloat(row.ORDER_VAT_SUM || 0);
|
||||
var amount = parseFloat(row.ORDER_TOTAL_AMOUNT_SUM || 0);
|
||||
|
||||
totalSupplyPrice += supplyPrice;
|
||||
totalVat += vat;
|
||||
totalAmount += amount;
|
||||
});
|
||||
}
|
||||
|
||||
// 합계 표시
|
||||
$("#totalSupplyPrice").text(Number(totalSupplyPrice).toLocaleString());
|
||||
$("#totalVat").text(Number(totalVat).toLocaleString());
|
||||
$("#totalAmount").text(Number(totalAmount).toLocaleString());
|
||||
|
||||
// 페이징 HTML 업데이트
|
||||
if(response.PAGE_HTML){
|
||||
$(".table_paging_wrap").html(response.PAGE_HTML);
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
alert("데이터 조회 중 오류가 발생했습니다.");
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
// fnc_tabul_search로 페이징 처리
|
||||
_tabulGrid = fnc_tabul_search(
|
||||
_tabul_layout_fitColumns,
|
||||
_tabulGrid,
|
||||
"/contractMgmt/contractGridList.do",
|
||||
columns,
|
||||
true
|
||||
);
|
||||
|
||||
// 데이터 렌더링 완료 후 합계 계산 (한 번만 실행)
|
||||
if(_tabulGrid) {
|
||||
// 기존 이벤트 제거 후 재등록
|
||||
_tabulGrid.off("renderComplete");
|
||||
_tabulGrid.on("renderComplete", function(){
|
||||
fn_calculateTotalFromGrid();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 그리드에 표시된 데이터의 원화총액 합계 계산
|
||||
function fn_calculateTotalFromGrid(){
|
||||
if(!_tabulGrid) {
|
||||
console.log("⚠️ [주문서관리] 그리드가 초기화되지 않음");
|
||||
$("#totalAmount").text("0");
|
||||
return;
|
||||
}
|
||||
|
||||
// 현재 그리드에 표시된 데이터만 가져오기
|
||||
var data = _tabulGrid.getData();
|
||||
var totalAmountKRW = 0;
|
||||
|
||||
console.log("🔍 [주문서관리] 표시된 데이터 개수:", data.length);
|
||||
|
||||
if(data.length > 0) {
|
||||
// ORDER_TOTAL_AMOUNT_KRW 합산
|
||||
data.forEach(function(row) {
|
||||
var amountKRW = parseFloat(row.ORDER_TOTAL_AMOUNT_KRW || 0);
|
||||
totalAmountKRW += amountKRW;
|
||||
});
|
||||
}
|
||||
|
||||
console.log("✅ [주문서관리] 표시된 데이터 합계:", totalAmountKRW);
|
||||
$("#totalAmount").text(Number(totalAmountKRW).toLocaleString());
|
||||
}
|
||||
|
||||
function _fnc_datepick(){
|
||||
@@ -606,10 +636,11 @@ function openProjectFormPopUp(objId){
|
||||
<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 btnRegist">
|
||||
</div>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch" name="btnSearch">
|
||||
<input type="button" value="수주등록" class="plm_btns btnRegist">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval">
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
@@ -716,23 +747,17 @@ function openProjectFormPopUp(objId){
|
||||
<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>
|
||||
|
||||
<!-- Total 합계 표시 영역 -->
|
||||
<div style="padding: 3px 10px; background: #f5f5f5; border-radius: 3px; margin: 10px 0;">
|
||||
<span style="font-weight: bold; font-size: 12px; margin-right: 20px;">
|
||||
Total 공급가액: <span id="totalSupplyPrice" style="color: #2196F3;">0</span> 원
|
||||
</span>
|
||||
<span style="font-weight: bold; font-size: 12px; margin-right: 20px;">
|
||||
Total 부가세: <span id="totalVat" style="color: #FF9800;">0</span> 원
|
||||
</span>
|
||||
<span style="font-weight: bold; font-size: 12px;">
|
||||
Total 총액: <span id="totalAmount" style="color: #4CAF50;">0</span> 원
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Total 합계 표시 영역 (그리드 위) -->
|
||||
<div style="padding:5px 10px; background: #f5f5f5;">
|
||||
<span style="font-weight: bold; font-size: 13px;">
|
||||
수주 금액 : <span id="totalAmount" style="color: #4CAF50;">0</span> 원
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -7,212 +7,630 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
||||
<style>
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 상단 입력 영역 */
|
||||
.top-input-section {
|
||||
padding: 15px 20px;
|
||||
background: #f9f9f9;
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
|
||||
.input-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.input-table td {
|
||||
padding: 5px 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.input-table label {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.input-table input[type="text"] {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bom-select-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.bom-select-table td {
|
||||
padding: 5px 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.bom-select-table label {
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bom-select-table input[type="text"] {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 하단 버튼 영역 */
|
||||
.bottom-button-section {
|
||||
padding: 15px 20px;
|
||||
background: #f9f9f9;
|
||||
border-top: 2px solid #ddd;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* 그리드 영역 */
|
||||
#structureTableWrap1 {
|
||||
padding: 15px 20px;
|
||||
height: calc(100vh - 260px);
|
||||
overflow: auto;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
#structureName {
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#structureName2 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Tabulator 커스텀 스타일 */
|
||||
.tabulator-row.level-1 { background-color: #fde9d9 !important; }
|
||||
.tabulator-row.level-2 { background-color: #daeef3 !important; }
|
||||
.tabulator-row.level-3 { background-color: #e4dfec !important; }
|
||||
.tabulator-row.level-4 { background-color: #ebf1de !important; }
|
||||
.tabulator-row.level-5 { background-color: #f2f2f2 !important; }
|
||||
.tabulator-row.level-6 { background-color: #f2dcdb !important; }
|
||||
.tabulator-row.level-7 { background-color: #eeece1 !important; }
|
||||
.tabulator-row.level-8 { background-color: #dce6f1 !important; }
|
||||
.tabulator-row.level-9 { background-color: #FFFFEB !important; }
|
||||
.tabulator-row.level-10 { background-color: #ffffff !important; }
|
||||
</style>
|
||||
<script>
|
||||
var _tabulGrid;
|
||||
var selectedRowData = null;
|
||||
var selectedBomObjId = null; // 선택된 BOM의 OBJID
|
||||
var selectedBomType = null; // 'EBOM' 또는 'MBOM'
|
||||
var bomGridData = []; // BOM 그리드 데이터
|
||||
|
||||
$(function(){
|
||||
$(document).ready(function(){
|
||||
// 페이지 로드 시 프로젝트 정보가 있으면 품번/품명 자동 입력
|
||||
<c:if test="${not empty projectInfo}">
|
||||
console.log("projectInfo가 있습니다. 품번/품명 설정 중...");
|
||||
$("#COPY_PART_NO").val("${projectInfo.PART_NO}");
|
||||
$("#COPY_PART_NAME").val("${projectInfo.PART_NAME}");
|
||||
// E-BOM 품번은 사용자가 직접 입력하도록 비워둠 (M-BOM 품번과 다를 수 있음)
|
||||
</c:if>
|
||||
|
||||
// 담기 버튼 - 선택한 BOM을 복사 대상으로 설정
|
||||
$("#btnAddItem").click(function(){
|
||||
var partNo = $("#COPY_PART_NO").val().trim();
|
||||
var partName = $("#COPY_PART_NAME").val().trim();
|
||||
|
||||
|
||||
|
||||
|
||||
if(""!="${product_code}"){
|
||||
$("#TARGET_PRODUCT_MGMT_OBJID").val("${product_code}");
|
||||
fnc_getProductRevtList("TARGET_REV","${product_code}");
|
||||
if(!partNo || !partName) {
|
||||
Swal.fire('품번과 품명을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 BOM이 있는지 확인
|
||||
if(!selectedBomObjId) {
|
||||
Swal.fire('E-BOM 또는 M-BOM을 먼저 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$("#btnConfirm").click(function(){
|
||||
if(fnc_validate("form1")){
|
||||
|
||||
if($("#REV").val()==""){
|
||||
Swal.fire('Source Rev를 선택해 주세요');
|
||||
return;
|
||||
}
|
||||
|
||||
if($("#TARGET_PRODUCT_MGMT_OBJID").val()==""){
|
||||
Swal.fire('대상 기종명을 선택해 주세요');
|
||||
return;
|
||||
}
|
||||
|
||||
if($("#PRODUCT_MGMT_OBJID").val() == $("#TARGET_PRODUCT_MGMT_OBJID").val() && $("#REV").val() == $("#TARGET_REV").val()){
|
||||
Swal.fire("같은 기종 같은 REV로 복사 할수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(confirm("복사하시겠습니까?")){
|
||||
|
||||
$.ajax({
|
||||
url:"/partMng/saveBomCopy.do",
|
||||
type:"POST",
|
||||
data:$("#form1").serialize(),
|
||||
dataType:"json",
|
||||
success:function(data){
|
||||
if(data=="SUCCESS"){
|
||||
Swal.fire('복사되었습니다');
|
||||
}else{
|
||||
Swal.fire('복사에 실패하였습니다.');
|
||||
}
|
||||
opener.fn_search();
|
||||
self.close();
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Swal.fire({
|
||||
title: '담기 완료',
|
||||
text: '선택한 BOM이 복사 대상으로 설정되었습니다.',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
$("#btnClose").click(function(){
|
||||
self.close(0);
|
||||
});
|
||||
|
||||
/* $("#PRODUCT_MGMT_OBJID").change(function(){
|
||||
fn_productSpecList(this.value, "PRODUCT_MGMT_SPEC", "");
|
||||
}); */
|
||||
|
||||
$("#REV").change(function(){
|
||||
$("#SPEC_NAME").val("");
|
||||
var spec_name = $("#REV").find("option:selected").attr("id");
|
||||
$("#SPEC_NAME").val(spec_name);
|
||||
});
|
||||
|
||||
|
||||
$("#TARGET_REV").change(function(){
|
||||
$("#TARGET_SPEC_NAME").val("");
|
||||
var spec_name = $("#TARGET_REV").find("option:selected").attr("ids");
|
||||
$("#TARGET_SPEC_NAME").val(spec_name);
|
||||
if(this.value!=""){
|
||||
$("#TARGET_SPEC_NAME").attr("readonly",true);
|
||||
}else{
|
||||
$("#TARGET_SPEC_NAME").attr("readonly",false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
$("#TARGET_PRODUCT_MGMT_OBJID").change(function(){
|
||||
|
||||
fnc_getProductRevtList("TARGET_REV",this.value);
|
||||
});
|
||||
|
||||
|
||||
|
||||
fnc_getProductMgmtList("PRODUCT_MGMT_OBJID", "${product_code}");
|
||||
//fn_productSpecList("${product_code}", "PRODUCT_MGMT_SPEC", "${product_mgmt_spec}");
|
||||
//fnc_productUPGNEWList("","${product_mgmt_spec}","PRODUCT_MGMT_UPG", "${upg_no}");
|
||||
|
||||
$("#PRODUCT_MGMT_SPEC").change(function(){
|
||||
fnc_productUPGList("",this.value,"PRODUCT_MGMT_UPG", "${resultMap.PRODUCT_MGMT_UPG}");
|
||||
});
|
||||
|
||||
$('.select2').select2();
|
||||
});
|
||||
|
||||
// 저장 버튼 - E-BOM을 M-BOM으로 복사
|
||||
$("#btnSaveItem").click(function(){
|
||||
fn_saveBomCopy();
|
||||
});
|
||||
|
||||
// E-BOM 선택 버튼
|
||||
$("#btnSelectEbom").click(function(){
|
||||
var ebomPartNo = $("#EBOM_PART_NO").val().trim();
|
||||
if(!ebomPartNo) {
|
||||
Swal.fire('E-BOM 품번을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// E-BOM 조회 후 미리보기 로드
|
||||
fn_loadBomPreview(ebomPartNo, 'EBOM');
|
||||
});
|
||||
|
||||
// M-BOM 선택 버튼
|
||||
$("#btnSelectMbom").click(function(){
|
||||
var mbomPartNo = $("#MBOM_PART_NO").val().trim();
|
||||
if(!mbomPartNo) {
|
||||
Swal.fire('M-BOM 품번을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// M-BOM 조회 후 미리보기 로드
|
||||
fn_loadBomPreview(mbomPartNo, 'MBOM');
|
||||
});
|
||||
|
||||
// Excel 다운로드 버튼
|
||||
$("#btnExcel").click(function() {
|
||||
fn_excel();
|
||||
});
|
||||
|
||||
// 도면 업로드 버튼 클릭
|
||||
$("#btnDrawingUpload").click(function() {
|
||||
$("#drawingFiles").click();
|
||||
});
|
||||
|
||||
// 파일 선택 이벤트
|
||||
$("#drawingFiles").change(function() {
|
||||
fn_uploadDrawingFiles(this.files);
|
||||
});
|
||||
|
||||
// 초기 그리드 생성 (빈 그리드)
|
||||
fn_initGrid([], 3);
|
||||
});
|
||||
|
||||
// BOM 미리보기 로드
|
||||
function fn_loadBomPreview(partNo, bomType) {
|
||||
console.log("fn_loadBomPreview 호출:", partNo, bomType);
|
||||
|
||||
// 먼저 품번으로 BOM OBJID 조회
|
||||
$.ajax({
|
||||
url: "/partMng/getBomObjIdByPartNo.do",
|
||||
type: "POST",
|
||||
data: { partNo: partNo },
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
console.log("getBomObjIdByPartNo 응답:", response);
|
||||
|
||||
if(response && response.OBJID) {
|
||||
$("#bomPartName").text(partNo);
|
||||
// 전역 변수에 저장
|
||||
selectedBomObjId = response.OBJID;
|
||||
selectedBomType = bomType;
|
||||
// BOM 트리 데이터 로드
|
||||
fn_loadBomTree(response.OBJID);
|
||||
} else {
|
||||
console.error("BOM OBJID를 찾을 수 없음:", response);
|
||||
Swal.fire('해당 품번의 BOM을 찾을 수 없습니다.');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("getBomObjIdByPartNo 에러:", xhr, status, error);
|
||||
Swal.fire('BOM 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BOM 트리 데이터 로드
|
||||
function fn_loadBomTree(bomObjId) {
|
||||
console.log("fn_loadBomTree 호출:", bomObjId);
|
||||
|
||||
$.ajax({
|
||||
url: "/partMng/getStructureTreeJson.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
objId: bomObjId,
|
||||
bomReportObjid: bomObjId,
|
||||
search_type: "working"
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
console.log("getStructureTreeJson 응답:", response);
|
||||
|
||||
if(response && response.length > 0) {
|
||||
var maxLevel = response[0].MAX_LEVEL || 3;
|
||||
|
||||
// Level 필드 생성
|
||||
var processedData = [];
|
||||
response.forEach(function(item) {
|
||||
for(var i = 1; i <= maxLevel; i++) {
|
||||
item['LEVEL_' + i] = (item.LEVEL == i) ? '*' : '';
|
||||
}
|
||||
processedData.push(item);
|
||||
});
|
||||
|
||||
// 전역 변수에 저장
|
||||
bomGridData = processedData;
|
||||
|
||||
fn_initGrid(processedData, maxLevel);
|
||||
} else {
|
||||
console.warn("BOM 트리 데이터가 비어있음");
|
||||
bomGridData = [];
|
||||
fn_initGrid([], 3);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("getStructureTreeJson 에러:", xhr, status, error);
|
||||
Swal.fire('BOM 트리 조회 중 오류가 발생했습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 도면 파일 업로드
|
||||
function fn_uploadDrawingFiles(files) {
|
||||
if(!files || files.length === 0) {
|
||||
Swal.fire('파일을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
Swal.fire('도면 다중 업로드 기능은 구현 예정입니다.');
|
||||
}
|
||||
|
||||
// Tabulator 그리드 초기화
|
||||
function fn_initGrid(data, maxLevel) {
|
||||
maxLevel = maxLevel || 3; // 기본 3레벨
|
||||
|
||||
// 데이터에서 최대 레벨 계산
|
||||
if(data && data.length > 0) {
|
||||
data.forEach(function(row) {
|
||||
if(row.LEVEL && row.LEVEL > maxLevel) {
|
||||
maxLevel = row.LEVEL;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 컬럼 정의
|
||||
var columns = [
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
title: '선택',
|
||||
field: 'RADIO',
|
||||
formatter: function(cell) {
|
||||
var rowData = cell.getData();
|
||||
return '<input type="radio" name="checkedPartNo" value="' + (rowData.CHILD_OBJID || '') + '">';
|
||||
},
|
||||
cellClick: function(e, cell) {
|
||||
var radio = $(e.target);
|
||||
if(radio.is(':radio')) {
|
||||
selectedRowData = cell.getData();
|
||||
$('input[name=checkedPartNo]').not(radio).prop('checked', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 수준 컬럼 그룹
|
||||
var levelColumns = [];
|
||||
for(var i = 1; i <= maxLevel; i++) {
|
||||
levelColumns.push({
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 30,
|
||||
title: i,
|
||||
field: 'LEVEL_' + i,
|
||||
formatter: function(cell) {
|
||||
return cell.getValue() === '*' ? '*' : '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
columns.push({
|
||||
title: '수준',
|
||||
headerHozAlign: 'center',
|
||||
columns: levelColumns
|
||||
});
|
||||
|
||||
// 나머지 컬럼 추가
|
||||
columns.push(
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '품번',
|
||||
field: 'PART_NO'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 200,
|
||||
title: '품명',
|
||||
field: 'PART_NAME'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
title: '수량',
|
||||
field: 'QTY_TEMP'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '항목 수량',
|
||||
field: 'ITEM_QTY'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
title: '3D',
|
||||
field: 'CU01_CNT',
|
||||
formatter: function(cell) {
|
||||
var rowData = cell.getData();
|
||||
var iconClass = (rowData.CU01_CNT && rowData.CU01_CNT > 0) ? 'file_icon' : 'file_empty_icon';
|
||||
return '<a href="#" class="File ' + iconClass + '"></a>';
|
||||
}
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
title: '2D',
|
||||
field: 'CU02_CNT',
|
||||
formatter: function(cell) {
|
||||
var rowData = cell.getData();
|
||||
var iconClass = (rowData.CU02_CNT && rowData.CU02_CNT > 0) ? 'file_icon' : 'file_empty_icon';
|
||||
return '<a href="#" class="File ' + iconClass + '"></a>';
|
||||
}
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
title: 'PDF',
|
||||
field: 'CU03_CNT',
|
||||
formatter: function(cell) {
|
||||
var rowData = cell.getData();
|
||||
var iconClass = (rowData.CU03_CNT && rowData.CU03_CNT > 0) ? 'file_icon' : 'file_empty_icon';
|
||||
return '<a href="#" class="File ' + iconClass + '"></a>';
|
||||
}
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '재료',
|
||||
field: 'MATERIAL'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 120,
|
||||
title: '열처리경도',
|
||||
field: 'HEAT_TREATMENT_HARDNESS'
|
||||
}
|
||||
);
|
||||
|
||||
// 기존 그리드 제거
|
||||
if(_tabulGrid) {
|
||||
_tabulGrid.destroy();
|
||||
}
|
||||
|
||||
// Tabulator 생성
|
||||
_tabulGrid = new Tabulator("#structureGrid", {
|
||||
data: data,
|
||||
layout: "fitColumns",
|
||||
height: "calc(100vh - 360px)",
|
||||
columns: columns,
|
||||
rowFormatter: function(row) {
|
||||
var data = row.getData();
|
||||
if(data.LEVEL) {
|
||||
$(row.getElement()).addClass('level-' + data.LEVEL);
|
||||
}
|
||||
},
|
||||
placeholder: "BOM 데이터를 조회하려면 E-BOM 또는 M-BOM 품번을 입력하고 선택 버튼을 클릭하세요."
|
||||
});
|
||||
}
|
||||
|
||||
// BOM 복사 저장
|
||||
function fn_saveBomCopy() {
|
||||
var copyPartNo = $("#COPY_PART_NO").val().trim();
|
||||
var copyPartName = $("#COPY_PART_NAME").val().trim();
|
||||
var targetObjId = $("#TARGET_OBJID").val();
|
||||
|
||||
// 유효성 검사
|
||||
if(!copyPartNo || !copyPartName) {
|
||||
Swal.fire('품번과 품명을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if(!selectedBomObjId) {
|
||||
Swal.fire('복사할 BOM을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if(bomGridData.length === 0) {
|
||||
Swal.fire('복사할 BOM 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 확인 메시지
|
||||
var confirmMessage = targetObjId
|
||||
? '선택한 ' + selectedBomType + '을(를) M-BOM으로 복사하시겠습니까?\n기존 M-BOM이 있다면 초기화됩니다.'
|
||||
: '선택한 ' + selectedBomType + '을(를) 새로운 품번(' + copyPartNo + ')으로 복사하시겠습니까?';
|
||||
|
||||
Swal.fire({
|
||||
title: 'BOM 복사',
|
||||
text: confirmMessage,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '복사',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed) {
|
||||
// 저장 처리
|
||||
Swal.fire({
|
||||
title: '저장 중...',
|
||||
text: 'BOM을 복사하고 있습니다.',
|
||||
allowOutsideClick: false,
|
||||
didOpen: () => {
|
||||
Swal.showLoading();
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: "/partMng/saveBomCopy.do",
|
||||
type: "POST",
|
||||
data: JSON.stringify({
|
||||
targetObjId: targetObjId, // M-BOM 관리에서 선택한 프로젝트 OBJID
|
||||
sourceBomObjId: selectedBomObjId,
|
||||
sourceBomType: selectedBomType,
|
||||
targetPartNo: copyPartNo,
|
||||
targetPartName: copyPartName,
|
||||
bomData: bomGridData
|
||||
}),
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
Swal.close();
|
||||
if(response && response.result === 'success') {
|
||||
Swal.fire({
|
||||
title: '저장 완료',
|
||||
text: 'M-BOM이 성공적으로 생성되었습니다.',
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
// 부모 창(M-BOM 관리) 새로고침하여 아이콘 업데이트
|
||||
if(window.opener && !window.opener.closed) {
|
||||
window.opener.location.reload();
|
||||
}
|
||||
window.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '저장 실패',
|
||||
text: response.message || 'BOM 복사 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
Swal.close();
|
||||
console.error('Save error:', error);
|
||||
Swal.fire({
|
||||
title: '저장 실패',
|
||||
text: '서버 오류가 발생했습니다: ' + error,
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 닫기
|
||||
function fn_close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
// Excel 다운로드
|
||||
function fn_excel() {
|
||||
if(_tabulGrid) {
|
||||
_tabulGrid.download("xlsx", "BOM_Copy.xlsx", {sheetName: "BOM"});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="backcolor">
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<div class="plm_menu_name">
|
||||
<h2>
|
||||
<span>BOM COPY</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div id="businessPopupFormWrap">
|
||||
<table class="pmsPopupForm">
|
||||
<colgroup>
|
||||
<col width="48%;">
|
||||
<col width="*">
|
||||
<col width="48%;">
|
||||
</colgroup>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<h3>SOURCE</h3>
|
||||
<br>
|
||||
<font color="red">※복사할 Version 을 선택하세요.</font>
|
||||
|
||||
<table width="100%">
|
||||
<tr >
|
||||
<td class="input_title"><label for="">기종(모델)명</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<select style="width:100%;" name="PRODUCT_MGMT_OBJID" id="PRODUCT_MGMT_OBJID" class="select2" disabled="disabled"></select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="input_title"><label for="">Source Version</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<select style="width:100%;" name="REV" id="REV" class="select2" autocomplete="off" required reqTitle="원본Version">
|
||||
<option value="">선택</option>
|
||||
${code_map.rev}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="input_title"><label for="">사양명</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<input type="text" id="SPEC_NAME" name="SPEC_NAME" disabled="disabled" readonly>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<h3>TARGET</h3>
|
||||
<br>
|
||||
<font color="red">※Version 미선택시 새로운 Version으로 신규 생성 되며 기등록된 BOM구조는 삭제 됩니다.</font>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td class="input_title"><label for="">대상 기종명</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<select style="width:100%;" name="TARGET_PRODUCT_MGMT_OBJID" id="TARGET_PRODUCT_MGMT_OBJID" class="select2" autocomplete="off" required reqTitle="대상기종">
|
||||
<option value="">선택</option>
|
||||
${code_map.product_code}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="input_title"><label for="">Target Version</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<select style="width:100%;" name="TARGET_REV" id="TARGET_REV" class="select2"></select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="input_title"><label for="">대상 사양명</label></td>
|
||||
<td class="input_sub_title" >
|
||||
<input type="text" id="TARGET_SPEC_NAME" name="TARGET_SPEC_NAME" required reqTitle="대상사양명">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<div class="btn_wrap" style="clear:both;">
|
||||
<div class="plm_btn_wrap_center">
|
||||
<input type="button" value="복사" class="plm_btns" id="btnConfirm">
|
||||
<input type="button" value="닫기" class="plm_btns" id="btnClose">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<!-- Hidden fields -->
|
||||
<input type="hidden" id="TARGET_OBJID" name="TARGET_OBJID" value="${param.objId}">
|
||||
|
||||
<!-- 상단: 품번/품명 입력 및 BOM 선택 영역 -->
|
||||
<div class="top-input-section">
|
||||
<table class="pmsPopuptable" style="margin-bottom: 10px;">
|
||||
<colgroup>
|
||||
<col width="10%">
|
||||
<col width="25%">
|
||||
<col width="10%">
|
||||
<col width="25%">
|
||||
<col width="30%">
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td class="input_title"><label for="COPY_PART_NO">품번</label></td>
|
||||
<td>
|
||||
<input type="text" id="COPY_PART_NO" name="COPY_PART_NO" style="width: 100%;">
|
||||
</td>
|
||||
<td class="input_title"><label for="COPY_PART_NAME">품명</label></td>
|
||||
<td>
|
||||
<input type="text" id="COPY_PART_NAME" name="COPY_PART_NAME" style="width: 100%;">
|
||||
</td>
|
||||
<td style="text-align: center;">
|
||||
<input type="button" value="담기" class="plm_btns" id="btnAddItem">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSaveItem">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="pmsPopuptable">
|
||||
<colgroup>
|
||||
<col width="15%">
|
||||
<col width="85%">
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td class="input_title"><label for="EBOM_PART_NO">E-BOM 품번</label></td>
|
||||
<td>
|
||||
<input type="text" id="EBOM_PART_NO" name="EBOM_PART_NO" style="width: 400px; margin-right: 10px;">
|
||||
<input type="button" value="E-BOM 선택" class="plm_btns" id="btnSelectEbom">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="input_title"><label for="MBOM_PART_NO">M-BOM 품번</label></td>
|
||||
<td>
|
||||
<input type="text" id="MBOM_PART_NO" name="MBOM_PART_NO" style="width: 400px; margin-right: 10px;">
|
||||
<input type="button" value="M-BOM 선택" class="plm_btns" id="btnSelectMbom">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 중간: BOM 미리보기 그리드 -->
|
||||
<div id="structureTableWrap1">
|
||||
<div id="structureName">
|
||||
<span id="bomPartName" style="font-weight: bold; color: #333;"></span>
|
||||
<input type="button" value="Excel Download" class="plm_btns structure_btn" id="btnExcel" style="float:right;">
|
||||
<input type="button" value="도면 다중 업로드" class="plm_btns structure_btn" id="btnDrawingUpload" style="float:right; margin-right:5px;">
|
||||
<input type="file" id="drawingFiles" multiple style="display:none;" accept=".stp,.step,.dwg,.dxf,.pdf">
|
||||
</div>
|
||||
<div id="structureGrid"></div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -422,16 +422,14 @@ function fn_changeRelatePartInfo(objId,rightObjId,leftObjId,leftPartNoQty,leftPa
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="backcolor" style="border:border:1px solid #ccc;">
|
||||
<body>
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="objId" id="objId" value="${param.objId}" />
|
||||
|
||||
<div id="structurePopupBtnW" style="padding-top:20px;">
|
||||
<div id="structurePopupBtnW">
|
||||
<input type="button" value="변경" class="plm_btns" id="moveChange">
|
||||
<br>
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:0px;">
|
||||
<br>
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight" style="margin-left:0px;">
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft">
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight">
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
|
||||
<script>
|
||||
// confirm/alert 헬퍼 함수
|
||||
function showConfirm(options) {
|
||||
if(typeof options === 'string') {
|
||||
alert(options);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
|
||||
var message = '';
|
||||
if(options.title) message += options.title + '\n\n';
|
||||
if(options.html) {
|
||||
// HTML 태그 제거
|
||||
message += options.html.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]+>/g, '');
|
||||
} else if(options.text) {
|
||||
message += options.text;
|
||||
}
|
||||
|
||||
if(options.showCancelButton !== false && (options.icon === 'warning' || options.icon === 'question')) {
|
||||
var result = confirm(message);
|
||||
return Promise.resolve({isConfirmed: result});
|
||||
} else {
|
||||
alert(message);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
//Part 연결
|
||||
$("#moveLeft").click(function(){
|
||||
// Tabulator에서 선택된 오른쪽 행 데이터 가져오기
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
var rightSelectedRows = rightFrame.getSelectedRows ? rightFrame.getSelectedRows() : [];
|
||||
|
||||
if(rightSelectedRows.length === 0) {
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 왼쪽 프레임에서 선택된 행 데이터 가져오기
|
||||
var leftPartNoObj = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
|
||||
var leftPartChildObjId = null;
|
||||
var leftPartNo = null;
|
||||
var leftPartNoQty = null;
|
||||
var leftParentObjId = null;
|
||||
var leftPartLastObjId = null;
|
||||
var leftQtyParObjId = null;
|
||||
var leftParentParts = "";
|
||||
|
||||
if(leftPartNoObj.length > 0) {
|
||||
leftPartChildObjId = leftPartNoObj.val();
|
||||
leftPartNo = leftPartNoObj.attr("data-PART_NO");
|
||||
leftPartNoQty = leftPartNoObj.attr("data-PART_NO_QTY");
|
||||
leftParentObjId = leftPartNoObj.attr("data-OBJID");
|
||||
leftPartLastObjId = leftPartNoObj.attr("data-LAST_PART_OBJID");
|
||||
leftQtyParObjId = leftPartNoObj.attr("data-PART_OBJID");
|
||||
leftParentParts = leftPartNoObj.attr("data-PARENT_PARTS") || "";
|
||||
}
|
||||
|
||||
// 같은 Part를 연결한건지 체크
|
||||
var isSamePart = false;
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
var rightPartNo = rowData.PART_NO;
|
||||
if(rightPartNo == leftPartNo){
|
||||
showConfirm({
|
||||
title: '연결 불가',
|
||||
html: '오류 Part No : <strong>['+rightPartNo+']</strong><br>같은 Part No끼리 연결할 수 없습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
isSamePart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isSamePart) return false;
|
||||
|
||||
// 연결하려는 part가 상위에 있는 part인지 확인
|
||||
var deniedPartArr = [];
|
||||
if(fnc_checkNull(leftParentParts).indexOf(",") > 0){
|
||||
deniedPartArr = leftParentParts.split(",");
|
||||
}
|
||||
var isDeniedPart = false;
|
||||
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
var rightPartNo = rowData.PART_NO;
|
||||
var rightPartType = rowData.PART_TYPE;
|
||||
|
||||
if("unique" == rightPartType){
|
||||
for(var j = 0 ; j < deniedPartArr.length ; j++){
|
||||
if(rightPartNo == deniedPartArr[j]){
|
||||
showConfirm({
|
||||
title: '연결 불가',
|
||||
html: '오류 Part No : <strong>['+rightPartNo+']</strong><br>이미 상위에 등록된 Part No 입니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
isDeniedPart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isDeniedPart) break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isDeniedPart) return;
|
||||
|
||||
// 선택된 파트의 OBJID 배열 생성
|
||||
var rightCheckedArr = [];
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
rightCheckedArr.push(rowData.OBJID);
|
||||
}
|
||||
|
||||
if(fnc_checkNull(leftPartNo) == ""){
|
||||
var flag = fn_checkSameTopPartNo(rightCheckedArr);
|
||||
if(flag == "true"){
|
||||
showConfirm({
|
||||
title: '중복 등록 불가',
|
||||
text: '1레벨에 같은 Part No가 중복 등록될 수 없습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Part 연결 확인
|
||||
showConfirm({
|
||||
title: 'Part 연결',
|
||||
text: '선택한 Part를 연결하시겠습니까?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '연결',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_relatePartInfo(leftPartChildObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
});
|
||||
});
|
||||
//end of Part 연결
|
||||
|
||||
//연결된 part 삭제
|
||||
$("#moveRight").click(function(){
|
||||
var leftPartNoObj = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
var leftPartChildObjId = leftPartNoObj.val();
|
||||
var leftPartNo = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PART_NO");
|
||||
var leftParentPartNo = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PARENT_PART_NO");
|
||||
var leftParentObjId = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PARENT_OBJID");
|
||||
var leftPartLastObjId = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-LAST_PART_OBJID");
|
||||
|
||||
fn_deletePartRelateInfo(leftPartNoObj.val(), leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId);
|
||||
});
|
||||
//end of 연결된 part 삭제
|
||||
|
||||
//연결된 part 변경
|
||||
$("#moveChange").click(function(){
|
||||
var leftPartNoList = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
|
||||
if(leftPartNoList.length === 0){
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(leftPartNoList.length > 1){
|
||||
showConfirm("한번에 1개의 파트만 변경가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var leftPartNo = leftPartNoList.attr("data-PART_NO");
|
||||
var leftPartObjid = leftPartNoList.attr("data-BOM_LAST_PART_OBJID");
|
||||
var leftParentPartObjid = leftPartNoList.attr("data-PARENT_PART_NO");
|
||||
var leftPartChildObjId = leftPartNoList.val();
|
||||
var leftPartBomQtyObjId = leftPartNoList.attr("data-OBJID");
|
||||
|
||||
// Tabulator에서 선택된 오른쪽 행 데이터 가져오기
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
var rightSelectedRows = rightFrame.getSelectedRows ? rightFrame.getSelectedRows() : [];
|
||||
|
||||
if(rightSelectedRows.length === 0){
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rightSelectedRows.length > 1){
|
||||
showConfirm("한번에 1개의 파트만 변경가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var rightRowData = rightSelectedRows[0].getData();
|
||||
var rightPartNo = rightRowData.PART_NO;
|
||||
var rightPartRev = rightRowData.REVISION || "";
|
||||
var rightObjId = rightRowData.OBJID;
|
||||
|
||||
// Part 변경 확인
|
||||
showConfirm({
|
||||
title: 'Part 변경',
|
||||
html: '선택한 Part를 변경하시겠습니까?<br><br>' +
|
||||
'<strong>기존:</strong> ' + leftPartNo + '<br>' +
|
||||
'<strong>변경:</strong> ' + rightPartNo,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '변경',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_changeRelatePartInfo(leftPartBomQtyObjId, rightObjId, leftPartChildObjId, leftParentPartObjid, leftPartChildObjId, leftPartObjid, rightPartNo, rightPartRev);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//1레벨에 같은 Part No가 등록되어있는지 확인.
|
||||
function fn_checkSameTopPartNo(rightCheckedArr){
|
||||
var result = false;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/checkSameTopPartNo.do",
|
||||
method: 'post',
|
||||
traditional: true, // 배열 파라미터 처리를 위한 옵션
|
||||
data: {"OBJID":$("#objId").val(), "rightCheckedArr[]":rightCheckedArr}, // [] 추가
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
result = data.result;
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
//end of 1레벨에 같은 Part No가 등록되어있는지 확인.
|
||||
|
||||
//구조 연결 해제
|
||||
function fn_deletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId){
|
||||
if(leftObjId == null){
|
||||
showConfirm("연결 해제할 Part를 선택해 주시기 바랍니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
showConfirm({
|
||||
title: 'Part 연결 해제',
|
||||
text: '선택한 Part의 연결을 해제하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '연결 해제',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fn_executeDeletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId);
|
||||
});
|
||||
}
|
||||
|
||||
// 실제 Part 연결 해제 실행 함수
|
||||
function fn_executeDeletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId){
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/deleteStatusPartRelateInfo.do",
|
||||
method: 'post',
|
||||
data: {"OBJID":$("#objId").val(), "leftObjId":leftObjId, "partObjId":leftPartLastObjId, "BOM_REPORT_OBJID":$("#objId").val()
|
||||
, "leftPartChildObjId":leftPartChildObjId, "leftParentPartNo":leftParentPartNo, "leftParentObjId":leftParentObjId},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
//$(parent.frames['rightFrame'].fn_searchPart());
|
||||
|
||||
// 부모 창(M-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
//end of 구조 연결 해제
|
||||
|
||||
//구조 연결
|
||||
function fn_relatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId){
|
||||
if(typeof rightCheckedArr != "undefined" && rightCheckedArr.length == 0){
|
||||
showConfirm("선택된 Part가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(leftObjId == null){
|
||||
showConfirm({
|
||||
title: '1레벨 등록 확인',
|
||||
html: '좌측에 선택된 Part정보가 없습니다.<br>이대로 연결하면 1레벨로 등록됩니다.<br><br>진행하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '진행',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
|
||||
// 실제 Part 연결 실행 함수
|
||||
function fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId){
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/relatePartInfo.do",
|
||||
method: 'post',
|
||||
traditional: true, // 배열 파라미터 처리를 위한 옵션
|
||||
data: {
|
||||
"leftObjId": leftObjId,
|
||||
"leftPartNoQty": leftPartNoQty,
|
||||
"OBJID": $("#objId").val(),
|
||||
"rightCheckedArr[]": rightCheckedArr, // Spring의 @RequestParam(value = "rightCheckedArr[]") 형식
|
||||
"partObjId": leftPartLastObjId,
|
||||
"BOM_REPORT_OBJID": $("#objId").val(),
|
||||
"leftPartChildObjId": leftPartChildObjId,
|
||||
"leftQtyParObjId": leftQtyParObjId
|
||||
},
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
// 왼쪽 프레임 새로고침
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
|
||||
// 오른쪽 프레임 선택 해제 (Tabulator)
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
if(rightFrame.clearSelection) {
|
||||
rightFrame.clearSelection();
|
||||
}
|
||||
|
||||
// 부모 창(M-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
//end of 구조 연결
|
||||
|
||||
//구조 연결 변경
|
||||
function fn_changeRelatePartInfo(objId,rightObjId,leftObjId,leftPartNoQty,leftPartChildObjId,leftPartObjid,rightPartNo,rightPartRev){
|
||||
$.ajax({
|
||||
url: "/productionplanning/changeRelatePartInfo.do",
|
||||
method: 'post',
|
||||
data: {"rightObjId":rightObjId, "OBJID":objId,"BOM_REPORT_OBJID":$("#objId").val(),
|
||||
"leftObjId":leftObjId,"leftPartNoQty":leftPartNoQty,"leftPartChildObjId":leftPartChildObjId,
|
||||
"leftPartObjid":leftPartObjid, "rightPartNo":rightPartNo, "rightPartRev":rightPartRev},
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
// 왼쪽 프레임 새로고침
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
|
||||
// 오른쪽 프레임 검색 다시 수행
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
if(rightFrame.fn_searchPart) {
|
||||
rightFrame.fn_searchPart();
|
||||
}
|
||||
|
||||
// 오른쪽 프레임 선택 해제 (Tabulator)
|
||||
if(rightFrame.clearSelection) {
|
||||
rightFrame.clearSelection();
|
||||
}
|
||||
|
||||
// 부모 창(M-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="backcolor" style="border:border:1px solid #ccc;">
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="objId" id="objId" value="${param.objId}" />
|
||||
|
||||
<div id="structurePopupBtnW" style="padding-top:20px;">
|
||||
<input type="button" value="변경" class="plm_btns" id="moveChange">
|
||||
<br>
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:0px;">
|
||||
<br>
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight" style="margin-left:0px;">
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
584
WebContent/WEB-INF/view/productionplanning/mBomHeaderPopup.jsp
Normal file
584
WebContent/WEB-INF/view/productionplanning/mBomHeaderPopup.jsp
Normal file
@@ -0,0 +1,584 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
}
|
||||
#plmSearchZon td.label,
|
||||
#plmSearchZon td:first-child {
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// confirm/alert 헬퍼 함수
|
||||
function showConfirm(options) {
|
||||
if(typeof options === 'string') {
|
||||
alert(options);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
|
||||
var message = '';
|
||||
if(options.title) message += options.title + '\n\n';
|
||||
if(options.html) {
|
||||
// HTML 태그 제거
|
||||
message += options.html.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]+>/g, '');
|
||||
} else if(options.text) {
|
||||
message += options.text;
|
||||
}
|
||||
|
||||
if(options.showCancelButton !== false && (options.icon === 'warning' || options.icon === 'question')) {
|
||||
var result = confirm(message);
|
||||
return Promise.resolve({isConfirmed: result});
|
||||
} else {
|
||||
alert(message);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
//Part 연결
|
||||
$("#moveLeft").click(function(){
|
||||
// Tabulator에서 선택된 오른쪽 행 데이터 가져오기
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
var rightSelectedRows = rightFrame.getSelectedRows ? rightFrame.getSelectedRows() : [];
|
||||
|
||||
if(rightSelectedRows.length === 0) {
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 왼쪽 프레임에서 선택된 행 데이터 가져오기
|
||||
var leftPartNoObj = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
|
||||
var leftPartChildObjId = null;
|
||||
var leftPartNo = null;
|
||||
var leftPartNoQty = null;
|
||||
var leftParentObjId = null;
|
||||
var leftPartLastObjId = null;
|
||||
var leftQtyParObjId = null;
|
||||
var leftParentParts = "";
|
||||
|
||||
if(leftPartNoObj.length > 0) {
|
||||
leftPartChildObjId = leftPartNoObj.val();
|
||||
leftPartNo = leftPartNoObj.attr("data-PART_NO");
|
||||
leftPartNoQty = leftPartNoObj.attr("data-PART_NO_QTY");
|
||||
leftParentObjId = leftPartNoObj.attr("data-OBJID");
|
||||
leftPartLastObjId = leftPartNoObj.attr("data-LAST_PART_OBJID");
|
||||
leftQtyParObjId = leftPartNoObj.attr("data-PART_OBJID");
|
||||
leftParentParts = leftPartNoObj.attr("data-PARENT_PARTS") || "";
|
||||
}
|
||||
|
||||
// 같은 Part를 연결한건지 체크
|
||||
var isSamePart = false;
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
var rightPartNo = rowData.PART_NO;
|
||||
if(rightPartNo == leftPartNo){
|
||||
showConfirm({
|
||||
title: '연결 불가',
|
||||
html: '오류 Part No : <strong>['+rightPartNo+']</strong><br>같은 Part No끼리 연결할 수 없습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
isSamePart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isSamePart) return false;
|
||||
|
||||
// 연결하려는 part가 상위에 있는 part인지 확인
|
||||
var deniedPartArr = [];
|
||||
if(fnc_checkNull(leftParentParts).indexOf(",") > 0){
|
||||
deniedPartArr = leftParentParts.split(",");
|
||||
}
|
||||
var isDeniedPart = false;
|
||||
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
var rightPartNo = rowData.PART_NO;
|
||||
var rightPartType = rowData.PART_TYPE;
|
||||
|
||||
if("unique" == rightPartType){
|
||||
for(var j = 0 ; j < deniedPartArr.length ; j++){
|
||||
if(rightPartNo == deniedPartArr[j]){
|
||||
showConfirm({
|
||||
title: '연결 불가',
|
||||
html: '오류 Part No : <strong>['+rightPartNo+']</strong><br>이미 상위에 등록된 Part No 입니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
isDeniedPart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isDeniedPart) break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isDeniedPart) return;
|
||||
|
||||
// 선택된 파트의 OBJID 배열 생성
|
||||
var rightCheckedArr = [];
|
||||
for(var i = 0; i < rightSelectedRows.length; i++){
|
||||
var rowData = rightSelectedRows[i].getData();
|
||||
rightCheckedArr.push(rowData.OBJID);
|
||||
}
|
||||
|
||||
if(fnc_checkNull(leftPartNo) == ""){
|
||||
var flag = fn_checkSameTopPartNo(rightCheckedArr);
|
||||
if(flag == "true"){
|
||||
showConfirm({
|
||||
title: '중복 등록 불가',
|
||||
text: '1레벨에 같은 Part No가 중복 등록될 수 없습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Part 연결 확인
|
||||
showConfirm({
|
||||
title: 'Part 연결',
|
||||
text: '선택한 Part를 연결하시겠습니까?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '연결',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_relatePartInfo(leftPartChildObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
});
|
||||
});
|
||||
//end of Part 연결
|
||||
|
||||
//연결된 part 삭제
|
||||
$("#moveRight").click(function(){
|
||||
var leftPartNoObj = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
var leftPartChildObjId = leftPartNoObj.val();
|
||||
var leftPartNo = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PART_NO");
|
||||
var leftParentPartNo = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PARENT_PART_NO");
|
||||
var leftParentObjId = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-PARENT_OBJID");
|
||||
var leftPartLastObjId = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document).attr("data-LAST_PART_OBJID");
|
||||
|
||||
fn_deletePartRelateInfo(leftPartNoObj.val(), leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId);
|
||||
});
|
||||
//end of 연결된 part 삭제
|
||||
|
||||
//연결된 part 변경
|
||||
$("#moveChange").click(function(){
|
||||
var leftPartNoList = $("input[name=checkedPartNo]:checked", parent.frames['leftFrame'].document);
|
||||
|
||||
if(leftPartNoList.length === 0){
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(leftPartNoList.length > 1){
|
||||
showConfirm("한번에 1개의 파트만 변경가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var leftPartNo = leftPartNoList.attr("data-PART_NO");
|
||||
var leftPartObjid = leftPartNoList.attr("data-BOM_LAST_PART_OBJID");
|
||||
var leftParentPartObjid = leftPartNoList.attr("data-PARENT_PART_NO");
|
||||
var leftPartChildObjId = leftPartNoList.val();
|
||||
var leftPartBomQtyObjId = leftPartNoList.attr("data-OBJID");
|
||||
|
||||
// Tabulator에서 선택된 오른쪽 행 데이터 가져오기
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
var rightSelectedRows = rightFrame.getSelectedRows ? rightFrame.getSelectedRows() : [];
|
||||
|
||||
if(rightSelectedRows.length === 0){
|
||||
showConfirm("선택된 파트가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rightSelectedRows.length > 1){
|
||||
showConfirm("한번에 1개의 파트만 변경가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var rightRowData = rightSelectedRows[0].getData();
|
||||
var rightPartNo = rightRowData.PART_NO;
|
||||
var rightPartRev = rightRowData.REVISION || "";
|
||||
var rightObjId = rightRowData.OBJID;
|
||||
|
||||
// Part 변경 확인
|
||||
showConfirm({
|
||||
title: 'Part 변경',
|
||||
html: '선택한 Part를 변경하시겠습니까?<br><br>' +
|
||||
'<strong>기존:</strong> ' + leftPartNo + '<br>' +
|
||||
'<strong>변경:</strong> ' + rightPartNo,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '변경',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_changeRelatePartInfo(leftPartBomQtyObjId, rightObjId, leftPartChildObjId, leftParentPartObjid, leftPartChildObjId, leftPartObjid, rightPartNo, rightPartRev);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 조회 버튼 클릭
|
||||
$("#btnSearch").click(function(){
|
||||
fn_searchMbom();
|
||||
});
|
||||
|
||||
// 저장 버튼 클릭
|
||||
$("#btnSave").click(function(){
|
||||
fn_saveMbom();
|
||||
});
|
||||
|
||||
// BOM 복사 버튼 클릭
|
||||
$("#btnBomCopy").click(function(){
|
||||
fn_openBomCopyPopup();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//1레벨에 같은 Part No가 등록되어있는지 확인.
|
||||
function fn_checkSameTopPartNo(rightCheckedArr){
|
||||
var result = false;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/checkSameTopPartNo.do",
|
||||
method: 'post',
|
||||
traditional: true, // 배열 파라미터 처리를 위한 옵션
|
||||
data: {"OBJID":$("#objId").val(), "rightCheckedArr[]":rightCheckedArr}, // [] 추가
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
result = data.result;
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
//end of 1레벨에 같은 Part No가 등록되어있는지 확인.
|
||||
|
||||
//구조 연결 해제
|
||||
function fn_deletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId){
|
||||
if(leftObjId == null){
|
||||
showConfirm("연결 해제할 Part를 선택해 주시기 바랍니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
showConfirm({
|
||||
title: 'Part 연결 해제',
|
||||
text: '선택한 Part의 연결을 해제하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '연결 해제',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (!result.isConfirmed) return;
|
||||
|
||||
fn_executeDeletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId);
|
||||
});
|
||||
}
|
||||
|
||||
// 실제 Part 연결 해제 실행 함수
|
||||
function fn_executeDeletePartRelateInfo(leftObjId, leftPartLastObjId, leftParentPartNo, leftParentObjId, leftPartChildObjId){
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/deleteStatusPartRelateInfo.do",
|
||||
method: 'post',
|
||||
data: {"OBJID":$("#objId").val(), "leftObjId":leftObjId, "partObjId":leftPartLastObjId, "BOM_REPORT_OBJID":$("#objId").val()
|
||||
, "leftPartChildObjId":leftPartChildObjId, "leftParentPartNo":leftParentPartNo, "leftParentObjId":leftParentObjId},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
//$(parent.frames['rightFrame'].fn_searchPart());
|
||||
|
||||
// 부모 창(E-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
//end of 구조 연결 해제
|
||||
|
||||
//구조 연결
|
||||
function fn_relatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId){
|
||||
if(typeof rightCheckedArr != "undefined" && rightCheckedArr.length == 0){
|
||||
showConfirm("선택된 Part가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(leftObjId == null){
|
||||
showConfirm({
|
||||
title: '1레벨 등록 확인',
|
||||
html: '좌측에 선택된 Part정보가 없습니다.<br>이대로 연결하면 1레벨로 등록됩니다.<br><br>진행하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '진행',
|
||||
cancelButtonText: '취소',
|
||||
reverseButtons: false
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId);
|
||||
}
|
||||
|
||||
// 실제 Part 연결 실행 함수
|
||||
function fn_executeRelatePartInfo(leftObjId, rightCheckedArr, leftPartNoQty, leftPartLastObjId, leftPartChildObjId, leftQtyParObjId){
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/relatePartInfo.do",
|
||||
method: 'post',
|
||||
traditional: true, // 배열 파라미터 처리를 위한 옵션
|
||||
data: {
|
||||
"leftObjId": leftObjId,
|
||||
"leftPartNoQty": leftPartNoQty,
|
||||
"OBJID": $("#objId").val(),
|
||||
"rightCheckedArr[]": rightCheckedArr, // Spring의 @RequestParam(value = "rightCheckedArr[]") 형식
|
||||
"partObjId": leftPartLastObjId,
|
||||
"BOM_REPORT_OBJID": $("#objId").val(),
|
||||
"leftPartChildObjId": leftPartChildObjId,
|
||||
"leftQtyParObjId": leftQtyParObjId
|
||||
},
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
// 왼쪽 프레임 새로고침
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
|
||||
// 오른쪽 프레임 선택 해제 (Tabulator)
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
if(rightFrame.clearSelection) {
|
||||
rightFrame.clearSelection();
|
||||
}
|
||||
|
||||
// 부모 창(E-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
//end of 구조 연결
|
||||
|
||||
//구조 연결 변경
|
||||
function fn_changeRelatePartInfo(objId,rightObjId,leftObjId,leftPartNoQty,leftPartChildObjId,leftPartObjid,rightPartNo,rightPartRev){
|
||||
$.ajax({
|
||||
url: "/productionplanning/changeRelatePartInfo.do",
|
||||
method: 'post',
|
||||
data: {"rightObjId":rightObjId, "OBJID":objId,"BOM_REPORT_OBJID":$("#objId").val(),
|
||||
"leftObjId":leftObjId,"leftPartNoQty":leftPartNoQty,"leftPartChildObjId":leftPartChildObjId,
|
||||
"leftPartObjid":leftPartObjid, "rightPartNo":rightPartNo, "rightPartRev":rightPartRev},
|
||||
dataType: 'json',
|
||||
async:false,
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
// 왼쪽 프레임 새로고침
|
||||
$(parent.frames['leftFrame'].document.location.reload());
|
||||
|
||||
// 오른쪽 프레임 검색 다시 수행
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
if(rightFrame.fn_searchPart) {
|
||||
rightFrame.fn_searchPart();
|
||||
}
|
||||
|
||||
// 오른쪽 프레임 선택 해제 (Tabulator)
|
||||
if(rightFrame.clearSelection) {
|
||||
rightFrame.clearSelection();
|
||||
}
|
||||
|
||||
// 부모 창(E-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
}
|
||||
}
|
||||
, error: function(jqxhr, status, error){
|
||||
/* alert(jqxhr.statusText + ", " + status + ", " + error);
|
||||
alert(jqxhr.status);
|
||||
alert(jqxhr.responseText); */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// M-BOM 조회
|
||||
function fn_searchMbom() {
|
||||
var partNo = $("#search_part_no").val().trim();
|
||||
var partName = $("#search_part_name").val().trim();
|
||||
var mbomPartNo = $("#search_mbom_part_no").val().trim();
|
||||
var saveDate = $("#search_save_date").val().trim();
|
||||
|
||||
// 왼쪽 프레임의 조회 함수 호출
|
||||
var leftFrame = parent.frames['leftFrame'];
|
||||
if(leftFrame && leftFrame.fn_searchMbom) {
|
||||
leftFrame.fn_searchMbom({
|
||||
partNo: partNo,
|
||||
partName: partName,
|
||||
mbomPartNo: mbomPartNo,
|
||||
saveDate: saveDate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// M-BOM 저장
|
||||
function fn_saveMbom() {
|
||||
// 왼쪽 프레임에서 M-BOM 트리 데이터 가져오기
|
||||
var leftFrame = parent.frames['leftFrame'];
|
||||
if(!leftFrame) {
|
||||
alert("M-BOM 데이터를 가져올 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 트리 데이터 수집 (leftFrame에서 구현 필요)
|
||||
var mbomData = leftFrame.getMbomTreeData ? leftFrame.getMbomTreeData() : null;
|
||||
|
||||
if(!mbomData || mbomData.length === 0) {
|
||||
alert("저장할 M-BOM 데이터가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 저장 확인
|
||||
if(!confirm("M-BOM을 저장하시겠습니까?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 저장 API 호출
|
||||
$.ajax({
|
||||
url: "/productionplanning/saveMbom.do",
|
||||
method: 'post',
|
||||
data: JSON.stringify({
|
||||
mbomData: mbomData,
|
||||
partNo: $("#search_part_no").val().trim(),
|
||||
partName: $("#search_part_name").val().trim()
|
||||
}),
|
||||
contentType: 'application/json',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data && data.result === "success") {
|
||||
alert("M-BOM이 저장되었습니다.");
|
||||
|
||||
// 조회 새로고침
|
||||
fn_searchMbom();
|
||||
|
||||
// 부모 창 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
} else {
|
||||
alert("M-BOM 저장에 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("M-BOM 저장 오류:", error);
|
||||
alert("M-BOM 저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// BOM 복사 팝업 열기
|
||||
function fn_openBomCopyPopup() {
|
||||
var objId = $("#objId").val();
|
||||
|
||||
if(!objId || objId === "-1") {
|
||||
alert("프로젝트 정보를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// BOM 복사 팝업 열기 (저번에 만든 화면)
|
||||
var url = "/partMng/structureBomCopyFormPopup.do?objId=" + objId;
|
||||
var popupName = "bomCopyPopup";
|
||||
var popupWidth = 1400;
|
||||
var popupHeight = 800;
|
||||
var left = (screen.width - popupWidth) / 2;
|
||||
var top = (screen.height - popupHeight) / 2;
|
||||
|
||||
window.open(url, popupName, "width=" + popupWidth + ",height=" + popupHeight + ",left=" + left + ",top=" + top + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="objId" id="objId" value="${param.objId}" />
|
||||
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="search_part_no">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_no" id="search_part_no" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_part_name">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_name" id="search_part_name" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="search_mbom_part_no">M-BOM 품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_mbom_part_no" id="search_mbom_part_no" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_save_date">저장일</label></td>
|
||||
<td>
|
||||
<input type="date" name="search_save_date" id="search_save_date" value="">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSave">
|
||||
<input type="button" value="BOM 복사" class="plm_btns" id="btnBomCopy">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -34,6 +34,11 @@ $(document).ready(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
// BOM 복사 버튼
|
||||
$("#btnBomCopy").click(function(){
|
||||
fn_openBomCopyPopup();
|
||||
});
|
||||
|
||||
// 전체 체크박스
|
||||
$(document).on('click', '#checkAll', function() {
|
||||
$('.rowCheck').prop('checked', $(this).prop('checked'));
|
||||
@@ -61,7 +66,7 @@ var columns = [
|
||||
{title:'CONTRACT_OBJID', field:'CONTRACT_OBJID', visible: false},
|
||||
{title:'BOM_REPORT_OBJID', field:'BOM_REPORT_OBJID', visible: false},
|
||||
|
||||
// 체크박스
|
||||
// 1. 체크박스
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -74,7 +79,7 @@ var columns = [
|
||||
headerSort: false
|
||||
},
|
||||
|
||||
// 프로젝트번호
|
||||
// 2. 프로젝트번호
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
@@ -83,7 +88,7 @@ var columns = [
|
||||
field: 'PROJECT_NO'
|
||||
},
|
||||
|
||||
// 주문유형
|
||||
// 3. 주문유형
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -92,7 +97,7 @@ var columns = [
|
||||
field: 'CATEGORY_NAME'
|
||||
},
|
||||
|
||||
// 제품구분
|
||||
// 4. 제품구분
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -101,7 +106,7 @@ var columns = [
|
||||
field: 'PRODUCT_NAME'
|
||||
},
|
||||
|
||||
// 국내/해외
|
||||
// 5. 국내/해외
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -110,7 +115,7 @@ var columns = [
|
||||
field: 'AREA_NAME'
|
||||
},
|
||||
|
||||
// 접수일
|
||||
// 6. 접수일
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -119,7 +124,7 @@ var columns = [
|
||||
field: 'RECEIPT_DATE'
|
||||
},
|
||||
|
||||
// 고객사
|
||||
// 7. 고객사
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
@@ -128,7 +133,7 @@ var columns = [
|
||||
field: 'CUSTOMER_NAME'
|
||||
},
|
||||
|
||||
// 유/무상
|
||||
// 8. 유/무상
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -137,7 +142,7 @@ var columns = [
|
||||
field: 'PAID_TYPE_NAME'
|
||||
},
|
||||
|
||||
// 품번
|
||||
// 9. 품번
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
@@ -146,7 +151,7 @@ var columns = [
|
||||
field: 'PART_NO'
|
||||
},
|
||||
|
||||
// 품명
|
||||
// 10. 품명
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
@@ -155,7 +160,7 @@ var columns = [
|
||||
field: 'PART_NAME'
|
||||
},
|
||||
|
||||
// S/N
|
||||
// 11. S/N
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -164,7 +169,7 @@ var columns = [
|
||||
field: 'SERIAL_NO'
|
||||
},
|
||||
|
||||
// 수주수량
|
||||
// 12. 수주수량
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
@@ -173,7 +178,7 @@ var columns = [
|
||||
field: 'QUANTITY'
|
||||
},
|
||||
|
||||
// 요청납기
|
||||
// 13. 요청납기
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -182,7 +187,7 @@ var columns = [
|
||||
field: 'REQ_DEL_DATE'
|
||||
},
|
||||
|
||||
// 고객사요청사항
|
||||
// 14. 고객사요청사항
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
@@ -191,35 +196,7 @@ var columns = [
|
||||
field: 'CUSTOMER_REQUEST'
|
||||
},
|
||||
|
||||
// E-BOM
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: 'E-BOM',
|
||||
field: 'EBOM_STATUS',
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var bomReportObjid = fnc_checkNull(cell.getData().BOM_REPORT_OBJID);
|
||||
var projectMgmtObjid = fnc_checkNull(cell.getData().OBJID);
|
||||
var partNo = fnc_checkNull(cell.getData().PART_NO);
|
||||
var partName = fnc_checkNull(cell.getData().PART_NAME);
|
||||
|
||||
// E-BOM이 있든 없든 선택 팝업 열기 (할당된 경우 상세 + 변경 가능)
|
||||
fn_openEBomSelectPopup(projectMgmtObjid, partNo, partName, bomReportObjid);
|
||||
}
|
||||
},
|
||||
|
||||
// E-BOM 작성일
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '작성일',
|
||||
field: 'EBOM_REGDATE'
|
||||
},
|
||||
|
||||
// M-BOM
|
||||
// 15. M-BOM
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
@@ -228,33 +205,58 @@ var columns = [
|
||||
field: 'MBOM_STATUS',
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_openMBomPopup(objid);
|
||||
var rowData = cell.getData();
|
||||
var objid = fnc_checkNull(rowData.OBJID);
|
||||
var mbomStatus = fnc_checkNull(rowData.MBOM_STATUS);
|
||||
|
||||
// 파란색(저장된 M-BOM)일 때만 팝업 열기
|
||||
if(mbomStatus !== '' && mbomStatus !== '0') {
|
||||
fn_openMBomFormPopup(objid);
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: 'M-BOM이 생성되지 않았습니다.\nBOM 복사 버튼을 통해 먼저 M-BOM을 생성해주세요.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// M-BOM Version
|
||||
// 16. 최종저장일 (M-BOM 작성일)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 80,
|
||||
title: 'Version',
|
||||
field: 'MBOM_VERSION'
|
||||
},
|
||||
|
||||
// M-BOM 작성일
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '작성일',
|
||||
width: 120,
|
||||
title: '최종저장일',
|
||||
field: 'MBOM_REGDATE'
|
||||
}
|
||||
];
|
||||
|
||||
// 검색 함수
|
||||
function fn_search(){
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/productionplanning/mBomMgmtGridList.do", columns, true);
|
||||
// showCheck를 false로 설정하여 자동 체크박스 제거 (columns에 이미 체크박스 정의되어 있음)
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/productionplanning/mBomMgmtGridList.do", columns, false);
|
||||
|
||||
// 그리드 로드 완료 후 행 클릭 이벤트 추가
|
||||
if(_tabulGrid) {
|
||||
_tabulGrid.on("rowClick", function(e, row){
|
||||
// 체크박스를 직접 클릭한 경우는 제외
|
||||
if($(e.target).is('input[type="checkbox"]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// M-BOM 아이콘을 클릭한 경우는 제외
|
||||
if($(e.target).closest('.clip_icon, .hyphen_icon').length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 행 클릭 시 체크박스 토글
|
||||
var checkbox = $(row.getElement()).find('.rowCheck');
|
||||
if(checkbox.length > 0) {
|
||||
checkbox.prop('checked', !checkbox.prop('checked'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// E-BOM 팝업
|
||||
@@ -281,12 +283,82 @@ function fn_openEBomSelectPopup(projectMgmtObjid, partNo, partName, bomReportObj
|
||||
fn_centerPopup(popup_width, popup_height, url, 'ebomSelectPopup');
|
||||
}
|
||||
|
||||
// M-BOM 팝업
|
||||
// M-BOM 조회 팝업 (읽기 전용)
|
||||
function fn_openMBomPopup(objId) {
|
||||
var popup_width = 1000;
|
||||
var popup_height = 700;
|
||||
var url = "/productionplanning/mBomViewPopup.do?objId=" + objId;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'mbomViewPopup');
|
||||
}
|
||||
|
||||
// M-BOM 편집 팝업 (왼쪽 트리 + 중앙 버튼 + 오른쪽 E-BOM)
|
||||
function fn_openMBomFormPopup(objId) {
|
||||
var popup_width = 1800;
|
||||
var popup_height = 800;
|
||||
var popup_height = 900;
|
||||
var url = "/productionplanning/mBomFormPopup.do?objId=" + objId;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'mbomPopup');
|
||||
fn_centerPopup(popup_width, popup_height, url, 'mbomFormPopup');
|
||||
}
|
||||
|
||||
// BOM 복사 팝업
|
||||
function fn_openBomCopyPopup() {
|
||||
// 체크된 행이 있는지 확인
|
||||
var checkedRows = $('.rowCheck:checked');
|
||||
|
||||
if(checkedRows.length === 0) {
|
||||
Swal.fire({
|
||||
title: '선택 필요',
|
||||
text: 'BOM을 복사할 프로젝트를 선택해주세요.',
|
||||
icon: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(checkedRows.length > 1) {
|
||||
Swal.fire({
|
||||
title: '선택 오류',
|
||||
text: '한 번에 하나의 프로젝트만 선택해주세요.',
|
||||
icon: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 행의 데이터 가져오기
|
||||
var selectedObjId = checkedRows.first().data('objid');
|
||||
var selectedRow = _tabulGrid.searchRows("OBJID", "=", selectedObjId);
|
||||
|
||||
if(selectedRow.length === 0) {
|
||||
Swal.fire('선택된 데이터를 찾을 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
var rowData = selectedRow[0].getData();
|
||||
var mbomStatus = fnc_checkNull(rowData.MBOM_STATUS);
|
||||
|
||||
// M-BOM이 이미 생성되어 있는 경우 경고
|
||||
if(mbomStatus !== '' && mbomStatus !== '0') {
|
||||
Swal.fire({
|
||||
title: '경고',
|
||||
text: '저장된 M-BOM이 초기화 됩니다.\n계속하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '확인',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed) {
|
||||
fn_openBomCopyPopupWindow(selectedObjId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fn_openBomCopyPopupWindow(selectedObjId);
|
||||
}
|
||||
}
|
||||
|
||||
// BOM 복사 팝업 창 열기
|
||||
function fn_openBomCopyPopupWindow(objId) {
|
||||
var popup_width = 1800;
|
||||
var popup_height = 900;
|
||||
var url = "/partMng/structureBomCopyFormPopup.do?objId=" + objId;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'bomCopyPopup');
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -300,6 +372,7 @@ function fn_openMBomPopup(objId) {
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns" value="BOM 복사" id="btnBomCopy">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
146
WebContent/WEB-INF/view/productionplanning/mBomPopupCenter.jsp
Normal file
146
WebContent/WEB-INF/view/productionplanning/mBomPopupCenter.jsp
Normal file
@@ -0,0 +1,146 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
|
||||
<script>
|
||||
// confirm/alert 헬퍼 함수
|
||||
function showConfirm(options) {
|
||||
if(typeof options === 'string') {
|
||||
alert(options);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
|
||||
var message = '';
|
||||
if(options.title) message += options.title + '\n\n';
|
||||
if(options.html) {
|
||||
// HTML 태그 제거
|
||||
message += options.html.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]+>/g, '');
|
||||
} else if(options.text) {
|
||||
message += options.text;
|
||||
}
|
||||
|
||||
if(options.showCancelButton !== false && (options.icon === 'warning' || options.icon === 'question')) {
|
||||
var result = confirm(message);
|
||||
return Promise.resolve({isConfirmed: result});
|
||||
} else {
|
||||
alert(message);
|
||||
return Promise.resolve({isConfirmed: true});
|
||||
}
|
||||
}
|
||||
|
||||
$(function(){
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// E-BOM 할당 버튼 (변경)
|
||||
$("#moveChange").click(function(){
|
||||
showConfirm({
|
||||
title: 'E-BOM 할당',
|
||||
text: 'E-BOM을 선택하여 이 프로젝트에 할당하시겠습니까?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '할당',
|
||||
cancelButtonText: '취소'
|
||||
}).then(result => {
|
||||
if (result.isConfirmed) {
|
||||
fn_assignEbom();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// << 버튼 (현재는 사용 안 함)
|
||||
$("#moveLeft").click(function(){
|
||||
showConfirm("이 기능은 현재 사용할 수 없습니다.");
|
||||
});
|
||||
|
||||
// >> 버튼 (현재는 사용 안 함)
|
||||
$("#moveRight").click(function(){
|
||||
showConfirm("이 기능은 현재 사용할 수 없습니다.");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// E-BOM 할당 함수
|
||||
function fn_assignEbom(){
|
||||
// 오른쪽 프레임에서 선택된 E-BOM 가져오기
|
||||
var rightFrame = parent.frames['rightFrame'];
|
||||
var rightSelectedRows = rightFrame.getSelectedRows ? rightFrame.getSelectedRows() : [];
|
||||
|
||||
if(rightSelectedRows.length === 0){
|
||||
showConfirm("할당할 E-BOM을 선택해주세요.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(rightSelectedRows.length > 1){
|
||||
showConfirm("한 번에 1개의 E-BOM만 할당할 수 있습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var rowData = rightSelectedRows[0].getData();
|
||||
var bomReportObjid = rowData.OBJID;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/assignEbomToMbom.do",
|
||||
method: 'post',
|
||||
data: {
|
||||
"projectMgmtObjid": $("#objId").val(),
|
||||
"bomReportObjid": bomReportObjid
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data.result){
|
||||
showConfirm({
|
||||
title: '할당 완료',
|
||||
text: 'E-BOM이 성공적으로 할당되었습니다.',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 왼쪽 프레임 새로고침
|
||||
parent.frames['leftFrame'].location.reload();
|
||||
|
||||
// 부모 창(M-BOM 목록) 새로고침
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
} else {
|
||||
showConfirm({
|
||||
title: '할당 실패',
|
||||
text: 'E-BOM 할당 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
showConfirm({
|
||||
title: '오류',
|
||||
text: 'E-BOM 할당 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="objId" id="objId" value="${param.objId}" />
|
||||
|
||||
<div id="structurePopupBtnW" style="padding-top:20px;">
|
||||
<input type="button" value="변경" class="plm_btns" id="moveChange">
|
||||
<br>
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:0px;">
|
||||
<br>
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight" style="margin-left:0px;">
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<%String objId = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("objId"));%>
|
||||
<frameset cols="*, 100px, *" border="0" noresize>
|
||||
<frame src="/productionplanning/mBomPopupLeft.do?objId=<%=objId%>" name="leftFrame">
|
||||
<frame src="/productionplanning/mBomPopupCenter.do?objId=<%=objId%>" name="centerFrame">
|
||||
<frame src="/productionplanning/mBomPopupRight.do?objId=<%=objId%>" name="rightFrame">
|
||||
</frameset><noframes></noframes>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%
|
||||
java.util.Map map = (java.util.HashMap)request.getAttribute("info");
|
||||
if(map == null || map.isEmpty()) {
|
||||
response.sendRedirect("/common/error500.do");
|
||||
return;
|
||||
}
|
||||
String objId = com.pms.common.utils.CommonUtils.checkNull(map.get("OBJID"));
|
||||
%>
|
||||
<frameset rows="100px, *" border="0" noresize>
|
||||
<frame src="/productionplanning/mBomHeaderPopup.do?objId=<%=objId%>">
|
||||
<frame src="/productionplanning/mBomBottomPopupFS.do?objId=<%=objId%>">
|
||||
</frameset><noframes></noframes>
|
||||
|
||||
231
WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp
Normal file
231
WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp
Normal file
@@ -0,0 +1,231 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
||||
<style>
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 15px;
|
||||
}
|
||||
#mBomTableWrap {
|
||||
width: 99%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
#mBomName {
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
/* Tabulator 커스텀 스타일 */
|
||||
.tabulator-row.level-1 { background-color: #fde9d9 !important; }
|
||||
.tabulator-row.level-2 { background-color: #daeef3 !important; }
|
||||
.tabulator-row.level-3 { background-color: #e4dfec !important; }
|
||||
.tabulator-row.level-4 { background-color: #ebf1de !important; }
|
||||
.tabulator-row.level-5 { background-color: #f2f2f2 !important; }
|
||||
.tabulator-row.level-6 { background-color: #f2dcdb !important; }
|
||||
.tabulator-row.level-7 { background-color: #eeece1 !important; }
|
||||
.tabulator-row.level-8 { background-color: #dce6f1 !important; }
|
||||
.tabulator-row.level-9 { background-color: #FFFFEB !important; }
|
||||
.tabulator-row.level-10 { background-color: #ffffff !important; }
|
||||
</style>
|
||||
<script>
|
||||
var _tabulGrid;
|
||||
|
||||
$(function(){
|
||||
// Tabulator 초기화
|
||||
fn_initGrid();
|
||||
});
|
||||
|
||||
// Tabulator 그리드 초기화
|
||||
function fn_initGrid() {
|
||||
var maxLevel = ${empty MAXLEV ? 1 : MAXLEV};
|
||||
|
||||
// 컬럼 정의
|
||||
var columns = [];
|
||||
|
||||
// 수준 컬럼 그룹
|
||||
var levelColumns = [];
|
||||
for(var i = 1; i <= maxLevel; i++) {
|
||||
levelColumns.push({
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 30,
|
||||
title: i,
|
||||
field: 'LEVEL_' + i,
|
||||
formatter: function(cell) {
|
||||
return cell.getValue() === '*' ? '*' : '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
columns.push({
|
||||
title: '수준',
|
||||
headerHozAlign: 'center',
|
||||
columns: levelColumns
|
||||
});
|
||||
|
||||
// 나머지 컬럼 추가
|
||||
columns.push(
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '품번',
|
||||
field: 'PART_NO'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 250,
|
||||
title: '품명',
|
||||
field: 'PART_NAME'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 80,
|
||||
title: '수량',
|
||||
field: 'QTY_TEMP'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '항목 수량',
|
||||
field: 'ITEM_QTY'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 80,
|
||||
title: 'Rev',
|
||||
field: 'REVISION'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '규격',
|
||||
field: 'SPEC'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '제품구분',
|
||||
field: 'PRODUCT_NAME'
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '상태',
|
||||
field: 'STATUS_NAME'
|
||||
}
|
||||
);
|
||||
|
||||
// Tabulator 생성
|
||||
_tabulGrid = new Tabulator("#mBomTableWrap", {
|
||||
layout: "fitColumns",
|
||||
height: "calc(100vh - 150px)",
|
||||
columns: columns,
|
||||
data: ${bomTreeListJson},
|
||||
rowFormatter: function(row) {
|
||||
var data = row.getData();
|
||||
var level = data.LEVEL || 1;
|
||||
row.getElement().classList.add('level-' + level);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 필터 적용 함수
|
||||
function fn_applyFilter() {
|
||||
var partNo = $("#filterPartNo").val().trim();
|
||||
var partName = $("#filterPartName").val().trim();
|
||||
|
||||
if(!partNo && !partName) {
|
||||
_tabulGrid.clearFilter();
|
||||
return;
|
||||
}
|
||||
|
||||
_tabulGrid.setFilter([
|
||||
[
|
||||
{field: "PART_NO", type: "like", value: partNo},
|
||||
{field: "PART_NAME", type: "like", value: partName}
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
// 필터 초기화 함수
|
||||
function fn_resetFilter() {
|
||||
$("#filterPartNo").val("");
|
||||
$("#filterPartName").val("");
|
||||
_tabulGrid.clearFilter();
|
||||
}
|
||||
|
||||
// M-BOM 조회 (헤더 프레임에서 호출)
|
||||
function fn_searchMbom(searchParams) {
|
||||
$.ajax({
|
||||
url: "/productionplanning/getMbomList.do",
|
||||
method: 'post',
|
||||
data: searchParams,
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data && data.list) {
|
||||
_tabulGrid.setData(data.list);
|
||||
} else {
|
||||
_tabulGrid.setData([]);
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("M-BOM 조회 오류:", error);
|
||||
_tabulGrid.setData([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// M-BOM 트리 데이터 수집 (저장용)
|
||||
function getMbomTreeData() {
|
||||
var allData = _tabulGrid.getData();
|
||||
|
||||
// 데이터 구조 변환 (필요한 필드만 추출)
|
||||
var mbomData = allData.map(function(row) {
|
||||
return {
|
||||
PART_NO: row.PART_NO,
|
||||
PART_NAME: row.PART_NAME,
|
||||
QTY: row.QTY_TEMP || row.ITEM_QTY,
|
||||
LEVEL: row.LEVEL,
|
||||
REVISION: row.REVISION,
|
||||
SPEC: row.SPEC,
|
||||
PRODUCT_NAME: row.PRODUCT_NAME,
|
||||
STATUS_NAME: row.STATUS_NAME,
|
||||
OBJID: row.OBJID
|
||||
};
|
||||
});
|
||||
|
||||
return mbomData;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mBomName">
|
||||
<c:choose>
|
||||
<c:when test="${not empty ebomInfo}">
|
||||
E-BOM: ${ebomInfo.PART_NO} - ${ebomInfo.PART_NAME}
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
할당된 E-BOM이 없습니다.
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
<div id="mBomTableWrap"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
161
WebContent/WEB-INF/view/productionplanning/mBomPopupRight.jsp
Normal file
161
WebContent/WEB-INF/view/productionplanning/mBomPopupRight.jsp
Normal file
@@ -0,0 +1,161 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#plmSearchZon {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#plmSearchZon table {
|
||||
width: 100%;
|
||||
}
|
||||
#plmSearchZon td {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
#plmSearchZon td.label,
|
||||
#plmSearchZon td:first-child {
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
}
|
||||
#ebomTable {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
</style>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
||||
</head>
|
||||
<body class="backcolor">
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="search_part_no">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_no" id="search_part_no" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_part_name">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_name" id="search_part_name" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="search_material">재료</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_material" id="search_material" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_supplier">공급업체</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_supplier" id="search_supplier" value="">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="ebomTable"></div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
var ebomTable;
|
||||
|
||||
$(document).ready(function(){
|
||||
initEbomTable();
|
||||
fn_searchEbom();
|
||||
|
||||
// 조회 버튼 클릭 이벤트
|
||||
$("#btnSearch").click(function(){
|
||||
fn_searchEbom();
|
||||
});
|
||||
|
||||
// 엔터키 이벤트
|
||||
$("#search_part_no, #search_part_name, #search_material, #search_supplier").on('keypress', function(e){
|
||||
if(e.keyCode == 13 || e.which == 13){
|
||||
e.preventDefault();
|
||||
fn_searchEbom();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Tabulator 초기화
|
||||
function initEbomTable() {
|
||||
ebomTable = new Tabulator("#ebomTable", {
|
||||
layout: "fitColumns",
|
||||
height: "100%",
|
||||
selectable: true,
|
||||
columns: [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", vertAlign:"middle", headerSort:false, width: 40},
|
||||
{title: "품번", field: "PART_NO", widthGrow: 1.5, vertAlign:"middle"},
|
||||
{title: "품명", field: "PART_NAME", widthGrow: 2, vertAlign:"middle"},
|
||||
{title: "재료", field: "MATERIAL", widthGrow: 1.2, vertAlign:"middle"},
|
||||
{title: "공급업체", field: "SUPPLIER", widthGrow: 1.5, vertAlign:"middle"}
|
||||
],
|
||||
placeholder: "검색 결과가 없습니다."
|
||||
});
|
||||
}
|
||||
|
||||
// E-BOM 검색
|
||||
function fn_searchEbom() {
|
||||
var partNo = $("#search_part_no").val().trim();
|
||||
var partName = $("#search_part_name").val().trim();
|
||||
var material = $("#search_material").val().trim();
|
||||
var supplier = $("#search_supplier").val().trim();
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/getEbomList.do",
|
||||
method: 'post',
|
||||
data: {
|
||||
"search_part_no": partNo,
|
||||
"search_part_name": partName,
|
||||
"search_material": material,
|
||||
"search_supplier": supplier
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data && data.list) {
|
||||
// 품번과 품명이 비어있지 않은 데이터만 필터링
|
||||
var filteredList = data.list.filter(function(item) {
|
||||
return item.PART_NO && item.PART_NO.trim() !== '' &&
|
||||
item.PART_NAME && item.PART_NAME.trim() !== '';
|
||||
});
|
||||
ebomTable.setData(filteredList);
|
||||
} else {
|
||||
ebomTable.setData([]);
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("E-BOM 조회 오류:", error);
|
||||
ebomTable.setData([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 선택된 행 가져오기 (중앙 프레임에서 호출)
|
||||
function getSelectedRows() {
|
||||
return ebomTable.getSelectedRows();
|
||||
}
|
||||
|
||||
// 선택 해제
|
||||
function clearSelection() {
|
||||
ebomTable.deselectRow();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
140
WebContent/WEB-INF/view/productionplanning/mBomPopupTop.jsp
Normal file
140
WebContent/WEB-INF/view/productionplanning/mBomPopupTop.jsp
Normal file
@@ -0,0 +1,140 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
height: auto;
|
||||
}
|
||||
.plm_menu_name {
|
||||
margin: 5px 15px 0 15px !important;
|
||||
}
|
||||
.plm_menu_name h2 {
|
||||
margin: 5px 0 !important;
|
||||
padding: 5px 0;
|
||||
}
|
||||
#plmSearchZon {
|
||||
margin-bottom: 0 !important;
|
||||
padding-bottom: 5px !important;
|
||||
overflow: visible !important;
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
}
|
||||
.select2-container {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
.select2-dropdown {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
// 엔터키 이벤트 바인딩
|
||||
$("#filterPartNo, #filterPartName").on('keypress', function(e){
|
||||
if(e.keyCode == 13 || e.which == 13){
|
||||
e.preventDefault();
|
||||
fn_applyFilter();
|
||||
}
|
||||
});
|
||||
|
||||
// 페이지 로드 시 품번/품명이 있으면 자동으로 필터 적용
|
||||
var partNo = $("#filterPartNo").val().trim();
|
||||
var partName = $("#filterPartName").val().trim();
|
||||
if(partNo || partName) {
|
||||
setTimeout(function() {
|
||||
fn_applyFilter();
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
// 필터 적용 함수
|
||||
function fn_applyFilter() {
|
||||
var partNo = $("#filterPartNo").val().trim();
|
||||
var partName = $("#filterPartName").val().trim();
|
||||
|
||||
try {
|
||||
// 프레임 구조: parent(headerFs) -> frames[1](bottomFs) -> frames[0](leftFrame)
|
||||
var leftFrame = parent.frames[1].frames['leftFrame'];
|
||||
|
||||
if(leftFrame && leftFrame.fn_applyFilter) {
|
||||
leftFrame.$("#filterPartNo").val(partNo);
|
||||
leftFrame.$("#filterPartName").val(partName);
|
||||
leftFrame.fn_applyFilter();
|
||||
} else {
|
||||
console.error("leftFrame not found or fn_applyFilter not available");
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Error accessing leftFrame:", e);
|
||||
alert("필터를 적용할 수 없습니다. 프레임 구조를 확인해주세요.");
|
||||
}
|
||||
}
|
||||
|
||||
// 필터 초기화 함수
|
||||
function fn_resetFilter() {
|
||||
$("#filterPartNo").val("");
|
||||
$("#filterPartName").val("");
|
||||
|
||||
try {
|
||||
var leftFrame = parent.frames[1].frames['leftFrame'];
|
||||
|
||||
if(leftFrame && leftFrame.fn_resetFilter) {
|
||||
leftFrame.fn_resetFilter();
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Error accessing leftFrame:", e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="backcolor">
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<div class="plm_menu_name">
|
||||
<h2>
|
||||
<span>M-BOM 확인</span>
|
||||
<c:if test="${not empty projectNo}">
|
||||
<span style="font-size: 14px; font-weight: normal; color: #666; margin-left: 20px;">
|
||||
프로젝트번호: <strong style="color: #333;">${projectNo}</strong>
|
||||
<c:if test="${not empty partNo}">
|
||||
/ 품번: <strong style="color: #333;">${partNo}</strong>
|
||||
</c:if>
|
||||
<c:if test="${not empty partName}">
|
||||
/ 품명: <strong style="color: #333;">${partName}</strong>
|
||||
</c:if>
|
||||
</span>
|
||||
</c:if>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- 검색 필터 영역 -->
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="label"><label for="filterPartNo">품번</label></td>
|
||||
<td>
|
||||
<input type="text" id="filterPartNo" name="filterPartNo" value="${partNo}">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="filterPartName">품명</label></td>
|
||||
<td>
|
||||
<input type="text" id="filterPartName" name="filterPartName" value="${partName}">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<button type="button" class="plm_btns" onclick="fn_applyFilter()">검색</button>
|
||||
<button type="button" class="plm_btns" onclick="fn_resetFilter()">초기화</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
183
WebContent/WEB-INF/view/productionplanning/mBomViewPopup.jsp
Normal file
183
WebContent/WEB-INF/view/productionplanning/mBomViewPopup.jsp
Normal file
@@ -0,0 +1,183 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.header {
|
||||
padding: 15px 20px;
|
||||
background: #f5f5f5;
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
.header h3 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #333;
|
||||
}
|
||||
.info-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.info-table td {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.info-table label {
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
}
|
||||
.tree-container {
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
background: white;
|
||||
min-height: 400px;
|
||||
}
|
||||
.tree-node {
|
||||
padding: 5px 0;
|
||||
cursor: default;
|
||||
}
|
||||
.tree-node-content {
|
||||
padding: 5px 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
.tree-node-content:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
.tree-children {
|
||||
margin-left: 30px;
|
||||
}
|
||||
.footer {
|
||||
padding: 15px 20px;
|
||||
background: #f5f5f5;
|
||||
border-top: 1px solid #ddd;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/themes/default/style.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/jstree.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h3>M-BOM 조회</h3>
|
||||
<table class="info-table">
|
||||
<tr>
|
||||
<td>
|
||||
<label>프로젝트 번호:</label>
|
||||
<span id="projectNo">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<label>품번:</label>
|
||||
<span id="partNo">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<label>품명:</label>
|
||||
<span id="partName">-</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div id="mbomTree" class="tree-container"></div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var objId = "${param.objId}";
|
||||
|
||||
$(document).ready(function(){
|
||||
loadProjectInfo();
|
||||
loadMBomTree();
|
||||
});
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
function loadProjectInfo() {
|
||||
$.ajax({
|
||||
url: "/productionplanning/getMBomHeaderInfo.do",
|
||||
method: 'post',
|
||||
data: { objId: objId },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data && data.info) {
|
||||
$("#projectNo").text(data.info.PROJECT_NO || '-');
|
||||
$("#partNo").text(data.info.PART_NO || '-');
|
||||
$("#partName").text(data.info.PART_NAME || '-');
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("프로젝트 정보 로드 오류:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// M-BOM 트리 로드
|
||||
function loadMBomTree() {
|
||||
$.ajax({
|
||||
url: "/productionplanning/getMBomTree.do",
|
||||
method: 'post',
|
||||
data: { objId: objId },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data && data.tree) {
|
||||
initTree(data.tree);
|
||||
} else {
|
||||
$("#mbomTree").html('<p style="padding: 20px; text-align: center; color: #999;">저장된 M-BOM이 없습니다.</p>');
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("M-BOM 트리 로드 오류:", error);
|
||||
$("#mbomTree").html('<p style="padding: 20px; text-align: center; color: #f00;">데이터 로드 중 오류가 발생했습니다.</p>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// jsTree 초기화
|
||||
function initTree(treeData) {
|
||||
$('#mbomTree').jstree({
|
||||
'core': {
|
||||
'data': treeData,
|
||||
'check_callback': false,
|
||||
'themes': {
|
||||
'responsive': true
|
||||
}
|
||||
},
|
||||
'plugins': ['types'],
|
||||
'types': {
|
||||
'default': {
|
||||
'icon': 'fa fa-folder'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 트리 로드 완료 후 모두 펼치기
|
||||
$('#mbomTree').on('ready.jstree', function() {
|
||||
$('#mbomTree').jstree('open_all');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@include file="/init_new.jsp"%>
|
||||
<%
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
.project-detail-container {
|
||||
padding: 20px;
|
||||
background: white;
|
||||
}
|
||||
.section-title {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #ddd;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.info-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.info-table td {
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.info-label {
|
||||
background: #f9f9f9;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
width: 120px;
|
||||
}
|
||||
.item-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.item-table th, .item-table td {
|
||||
padding: 8px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: center;
|
||||
}
|
||||
.item-table th {
|
||||
background: #f5f5f5;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<section class="business_popup_min_width">
|
||||
<div class="plm_menu_name">
|
||||
<h2><span>프로젝트 상세 정보</span></h2>
|
||||
</div>
|
||||
|
||||
<div class="project-detail-container">
|
||||
<!-- 프로젝트 정보 -->
|
||||
<div class="section-title">프로젝트정보</div>
|
||||
<table class="info-table">
|
||||
<tr>
|
||||
<td class="info-label">주문유형</td>
|
||||
<td>${info.CATEGORY_NAME}</td>
|
||||
<td class="info-label">제품구분</td>
|
||||
<td>${info.PRODUCT_NAME}</td>
|
||||
<td class="info-label">국내/해외</td>
|
||||
<td>${info.AREA_NAME}</td>
|
||||
<td class="info-label">고객사</td>
|
||||
<td>${info.CUSTOMER_NAME}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="info-label">유/무상</td>
|
||||
<td>
|
||||
<c:choose>
|
||||
<c:when test="${info.PAID_TYPE == 'paid'}">유상</c:when>
|
||||
<c:when test="${info.PAID_TYPE == 'free'}">무상</c:when>
|
||||
<c:otherwise>${info.PAID_TYPE}</c:otherwise>
|
||||
</c:choose>
|
||||
</td>
|
||||
<td class="info-label">접수일</td>
|
||||
<td>${info.RECEIPT_DATE}</td>
|
||||
<td class="info-label">견적환종</td>
|
||||
<td>${info.CONTRACT_CURRENCY_NAME}</td>
|
||||
<td class="info-label">견적환율</td>
|
||||
<td>${info.EXCHANGE_RATE}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 품목정보 -->
|
||||
<div class="section-title">품목정보</div>
|
||||
<table class="item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>품번</th>
|
||||
<th>품명</th>
|
||||
<th>S/N</th>
|
||||
<th>요청납기</th>
|
||||
<th>고객요청사항</th>
|
||||
<th>반납사유</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>${info.PART_NO}</td>
|
||||
<td>${info.PART_NAME}</td>
|
||||
<td>${info.SERIAL_NO}</td>
|
||||
<td>${info.REQ_DEL_DATE}</td>
|
||||
<td>${info.CUSTOMER_REQUEST}</td>
|
||||
<td>
|
||||
<c:choose>
|
||||
<c:when test="${not empty info.RETURN_REASON and info.RETURN_REASON != '-'}">
|
||||
${info.RETURN_REASON}
|
||||
</c:when>
|
||||
<c:otherwise>-</c:otherwise>
|
||||
</c:choose>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- 결재 라인 정보 -->
|
||||
<%--
|
||||
<c:if test="${not empty approvalLine}">
|
||||
<div class="section-title">결재 정보</div>
|
||||
<table class="item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>순번</th>
|
||||
<th>기안자</th>
|
||||
<th>기안일</th>
|
||||
<th>결재자</th>
|
||||
<th>결재일</th>
|
||||
<th>상태</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:forEach var="approval" items="${approvalLine}" varStatus="status">
|
||||
<tr>
|
||||
<td>${approval.SEQ}</td>
|
||||
<td>${approval.WRITER}</td>
|
||||
<td>${approval.REGDATE}</td>
|
||||
<td>${approval.TARGET_USER_NAME}</td>
|
||||
<td>${approval.PROC_DATE}</td>
|
||||
<td>
|
||||
<c:choose>
|
||||
<c:when test="${approval.STATUS == 'complete'}">승인</c:when>
|
||||
<c:when test="${approval.STATUS == 'reject'}">반려</c:when>
|
||||
<c:when test="${approval.STATUS == 'READY'}">대기</c:when>
|
||||
<c:otherwise>${approval.STATUS}</c:otherwise>
|
||||
</c:choose>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</tbody>
|
||||
</table>
|
||||
</c:if>
|
||||
--%>
|
||||
|
||||
<!-- 버튼 영역 -->
|
||||
<div style="text-align:center; margin-top:20px;">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="self.close();">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -33,6 +33,12 @@
|
||||
$(document).ready(function(){
|
||||
_fnc_datepick();
|
||||
|
||||
// 그리드 높이 동적 계산 (Total 합계 영역 + 여유 공간 80px)
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
$(window).resize(function() {
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
});
|
||||
|
||||
// select2가 로드되었을 때만 초기화
|
||||
if(typeof $.fn !== 'undefined' && typeof $.fn.select2 === 'function') {
|
||||
$('.select2').select2();
|
||||
@@ -255,14 +261,14 @@ function fn_search(){
|
||||
if(_tabulGrid){
|
||||
_tabulGrid.setData(response.RESULTLIST || []);
|
||||
} else {
|
||||
// 그리드 초기화
|
||||
_tabulGrid = new Tabulator("#mainGrid", {
|
||||
layout: _tabul_layout_fitColumns,
|
||||
height: "650px", // 그리드 고정 높이 설정
|
||||
columns: columns,
|
||||
data: response.RESULTLIST || [],
|
||||
selectable: "highlight" // 다중 선택 가능하도록 설정
|
||||
});
|
||||
// 그리드 초기화
|
||||
_tabulGrid = new Tabulator("#mainGrid", {
|
||||
layout: _tabul_layout_fitColumns,
|
||||
height: "100%", // 부모 컨테이너 높이에 맞춤
|
||||
columns: columns,
|
||||
data: response.RESULTLIST || [],
|
||||
selectable: "highlight" // 다중 선택 가능하도록 설정
|
||||
});
|
||||
|
||||
// 행 클릭으로 다중 선택
|
||||
_tabulGrid.on("rowClick", function(e, row){
|
||||
|
||||
@@ -30,6 +30,20 @@
|
||||
_fnc_datepick(); // 날짜 선택기 초기화
|
||||
$('.select2').select2(); // select2 초기화
|
||||
|
||||
// 그리드 높이 동적 계산 (Total 합계 영역 + 여유 공간 80px)
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
|
||||
// 디버그: 계산된 높이 확인
|
||||
console.log("=== 그리드 높이 디버그 ===");
|
||||
console.log("윈도우 높이:", $(window).height());
|
||||
console.log("#gridDiv 높이:", $('#gridDiv').height());
|
||||
console.log("#mainGrid 높이:", $('#mainGrid').height());
|
||||
|
||||
$(window).resize(function() {
|
||||
fnc_calculateContentHeight("gridDiv", 80);
|
||||
console.log("리사이즈 후 #gridDiv 높이:", $('#gridDiv').height());
|
||||
});
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#search_partNo", "#search_partName", "#search_partObjId", {
|
||||
debug: true
|
||||
@@ -53,6 +67,11 @@
|
||||
$("#btnBulkRegister").click(function(){
|
||||
fn_bulkRegister();
|
||||
});
|
||||
|
||||
// 거래명세서 출력 버튼
|
||||
$("#btnTransactionStatement").click(function(){
|
||||
fn_printTransactionStatement();
|
||||
});
|
||||
});
|
||||
|
||||
// 날짜 선택기 초기화 함수
|
||||
@@ -83,19 +102,28 @@
|
||||
// 현재 그리드 데이터 백업
|
||||
var currentData = _tabulGrid.getData();
|
||||
|
||||
console.log("=== 엑셀 다운로드 디버그 ===");
|
||||
console.log("첫 번째 행 데이터:", currentData[0]);
|
||||
console.log("SHIPPING_DATE:", currentData[0].SHIPPING_DATE);
|
||||
console.log("SHIPPING_DATE_WITH_COUNT:", currentData[0].SHIPPING_DATE_WITH_COUNT);
|
||||
|
||||
// 엑셀용 데이터 가공: 출하일을 분할출하 정보 포함하여 표시
|
||||
var excelData = currentData.map(function(row) {
|
||||
var excelRow = Object.assign({}, row);
|
||||
|
||||
// 출하일 가공: SHIPPING_DATE_WITH_COUNT 값을 SHIPPING_DATE에 덮어쓰기
|
||||
// 예: "2025-10-20외1" 형식
|
||||
if(excelRow.SHIPPING_DATE_WITH_COUNT) {
|
||||
// 예: "2025-10-20 외 1건" 형식
|
||||
if(excelRow.SHIPPING_DATE_WITH_COUNT && excelRow.SHIPPING_DATE_WITH_COUNT.trim() !== '') {
|
||||
console.log("출하일 변경:", excelRow.SHIPPING_DATE, "→", excelRow.SHIPPING_DATE_WITH_COUNT);
|
||||
excelRow.SHIPPING_DATE = excelRow.SHIPPING_DATE_WITH_COUNT;
|
||||
}
|
||||
|
||||
return excelRow;
|
||||
});
|
||||
|
||||
console.log("가공된 첫 번째 행:", excelData[0]);
|
||||
console.log("가공된 SHIPPING_DATE:", excelData[0].SHIPPING_DATE);
|
||||
|
||||
// 엑셀용 데이터로 임시 설정
|
||||
_tabulGrid.setData(excelData);
|
||||
|
||||
@@ -125,6 +153,70 @@
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
// 그리드 데이터를 전달하는 판매등록 팝업
|
||||
function fn_openSaleRegPopupWithData(rowData){
|
||||
console.log("=== fn_openSaleRegPopupWithData 호출 ===");
|
||||
console.log("rowData:", rowData);
|
||||
|
||||
var popup_width = 850;
|
||||
var popup_height = 550;
|
||||
|
||||
// 신규 판매등록: orderNo와 잔량 전달 (saleNo 없음)
|
||||
var params = "orderNo=" + encodeURIComponent(rowData.PROJECT_NO);
|
||||
// saleNo는 전달하지 않음 (신규 등록 모드)
|
||||
|
||||
// 그리드에서 계산된 잔량 전달
|
||||
if(rowData.REMAINING_QUANTITY != null) {
|
||||
params += "&remainingQuantity=" + encodeURIComponent(rowData.REMAINING_QUANTITY);
|
||||
}
|
||||
|
||||
// 금액 정보는 Controller에서 자동으로 불러옴 (수주 데이터 기반)
|
||||
// URL 파라미터로 전달하지 않음
|
||||
|
||||
var url = "/salesMgmt/salesRegForm.do?" + params;
|
||||
console.log("최종 URL:", url);
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
// 거래명세서 출력 함수
|
||||
function fn_printTransactionStatement() {
|
||||
var selectedData = _tabulGrid.getSelectedData();
|
||||
|
||||
if(selectedData.length === 0) {
|
||||
alert("거래명세서를 출력할 항목을 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 거래명세서 출력 버튼은 항상 새로 작성 (저장된 데이터 무시)
|
||||
localStorage.setItem('loadSavedStatement', 'false');
|
||||
|
||||
// 같은 거래처인지 확인
|
||||
var firstCustomer = selectedData[0].CUSTOMER;
|
||||
|
||||
for(var i = 1; i < selectedData.length; i++) {
|
||||
if(selectedData[i].CUSTOMER !== firstCustomer) {
|
||||
alert("같은 거래처만 선택 가능합니다.\n선택한 거래처: " + firstCustomer + ", " + selectedData[i].CUSTOMER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 그리드 데이터를 localStorage에 저장
|
||||
console.log("=== 거래명세서 출력 - 선택된 데이터 ===");
|
||||
console.log(selectedData);
|
||||
localStorage.setItem('transactionStatementData', JSON.stringify(selectedData));
|
||||
|
||||
// 프로젝트 번호들을 수집
|
||||
var projectNos = selectedData.map(function(row) {
|
||||
return row.PROJECT_NO;
|
||||
}).join(',');
|
||||
|
||||
// 새로 만든 거래명세서 팝업 열기
|
||||
var popup_width = 1000;
|
||||
var popup_height = 800;
|
||||
var url = "/salesMgmt/transactionStatementForm.do?projectNos=" + encodeURIComponent(projectNos);
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
function fn_FileRegist(objId, docType, docTypeName){
|
||||
var popup_width = 800;
|
||||
var popup_height = 680;
|
||||
@@ -155,19 +247,56 @@ var columns = [
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell){
|
||||
var orderNo = cell.getData().PROJECT_NO;
|
||||
var saleNo = cell.getData().SALE_NO;
|
||||
fn_openSaleRegPopup(orderNo, saleNo);
|
||||
// 프로젝트 번호 클릭 시: 결재 정보 조회 모드 (saleNo에 "detail" 전달)
|
||||
fn_openSaleRegPopup(orderNo, "detail");
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '주문유형', field : 'ORDER_TYPE'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주일', field : 'ORDER_DATE'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '발주번호', field : 'PO_NO'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기', field : 'REQUEST_DATE'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '출하일', field : 'SHIPPING_DATE'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '출하일', field : 'SHIPPING_DATE_WITH_COUNT',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
// SHIPPING_DATE_WITH_COUNT가 비어있으면 SHIPPING_DATE 사용
|
||||
if(!value || value.trim() === '') {
|
||||
var data = cell.getRow().getData();
|
||||
return data.SHIPPING_DATE || '';
|
||||
}
|
||||
return value;
|
||||
},
|
||||
cellClick: function(e, cell) {
|
||||
var projectNo = cell.getRow().getData().PROJECT_NO;
|
||||
if(projectNo) {
|
||||
fn_openShippingDetail(projectNo);
|
||||
}
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER'},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'PRODUCT_NAME'},
|
||||
// {headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY',
|
||||
// formatter: function(cell) {
|
||||
// var value = cell.getValue();
|
||||
// if(!value || value === '' || value === '0') return '';
|
||||
// // "X 외 Y건" 형식인지 확인
|
||||
// if(typeof value === 'string' && value.includes('외')) {
|
||||
// return value;
|
||||
// }
|
||||
// // 숫자인 경우 포맷팅
|
||||
// return Number(value).toLocaleString();
|
||||
// }
|
||||
// },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주수량', field : 'ORDER_QUANTITY',
|
||||
formatter: "money", formatterParams: {thousand: ",", symbolAfter: "", precision: false}
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
// "X 외 Y건" 형식인지 확인
|
||||
if(typeof value === 'string' && value.includes('외')) {
|
||||
return value;
|
||||
}
|
||||
// 숫자인 경우 포맷팅
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '판매수량', field : 'SALES_QUANTITY',
|
||||
formatter: "money", formatterParams: {thousand: ",", symbolAfter: "", precision: false}
|
||||
@@ -202,7 +331,32 @@ var columns = [
|
||||
formatter: "money", formatterParams: {thousand: ",", symbolAfter: "", precision: 2}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : 'S/N', field : 'SERIAL_NO'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '품번', field : 'PRODUCT_NO'}
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '품번', field : 'PRODUCT_NO'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '거래명세서', field : 'TRANSACTION_STATEMENT',
|
||||
formatter: function(cell) {
|
||||
var data = cell.getRow().getData();
|
||||
var projectNo = data.PROJECT_NO;
|
||||
var hasStatement = data.HAS_TRANSACTION_STATEMENT === 'Y';
|
||||
|
||||
if(projectNo) {
|
||||
if(hasStatement) {
|
||||
return '<img src="/images/folder_blue.png" height="25px" width="25px" style="cursor:pointer;" title="거래명세서 보기">';
|
||||
} else {
|
||||
return '<img src="/images/file_empty.png" height="25px" width="25px" style="cursor:pointer;" title="거래명세서 작성">';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
cellClick: function(e, cell) {
|
||||
var data = cell.getRow().getData();
|
||||
var projectNo = data.PROJECT_NO;
|
||||
var hasStatement = data.HAS_TRANSACTION_STATEMENT === 'Y';
|
||||
|
||||
if(projectNo) {
|
||||
fn_openTransactionStatementPopup(projectNo, hasStatement);
|
||||
}
|
||||
}
|
||||
}
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '제품구분', field : 'PRODUCT_TYPE'},
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '국내/해외', field : 'NATION'},
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '접수일', field : 'RECEIPT_DATE'},
|
||||
@@ -247,15 +401,22 @@ function fn_search(){
|
||||
// 그리드 데이터 설정
|
||||
if(_tabulGrid){
|
||||
_tabulGrid.setData(response.RESULTLIST || []);
|
||||
} else {
|
||||
// 그리드 초기화
|
||||
_tabulGrid = new Tabulator("#mainGrid", {
|
||||
layout: _tabul_layout_fitColumns,
|
||||
columns: columns,
|
||||
data: response.RESULTLIST || [],
|
||||
selectable: true
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 그리드 초기화
|
||||
_tabulGrid = new Tabulator("#mainGrid", {
|
||||
height: "100%",
|
||||
layout: _tabul_layout_fitColumns,
|
||||
columns: columns,
|
||||
data: response.RESULTLIST || [],
|
||||
selectable: true
|
||||
});
|
||||
|
||||
// 그리드 생성 후 높이 재계산
|
||||
setTimeout(function() {
|
||||
console.log("그리드 생성 후 #mainGrid 높이:", $('#mainGrid').height());
|
||||
console.log("그리드 생성 후 .tabulator 높이:", $('.tabulator').height());
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// 조회된 전체 데이터의 판매원화총액 합계 계산
|
||||
var totalSalesAmountKRW = 0;
|
||||
@@ -283,7 +444,7 @@ function fn_search(){
|
||||
|
||||
// 페이징 HTML 업데이트
|
||||
if(response.PAGE_HTML){
|
||||
$("#pagingArea").html(response.PAGE_HTML);
|
||||
$(".table_paging_wrap").html(response.PAGE_HTML);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
@@ -294,6 +455,74 @@ function fn_search(){
|
||||
});
|
||||
}
|
||||
|
||||
// 출하일 상세 내역 팝업
|
||||
// 거래명세서 팝업 열기 (단일 프로젝트)
|
||||
function fn_openTransactionStatementPopup(projectNo, hasStatement) {
|
||||
console.log("=== 거래명세서 팝업 열기 ===");
|
||||
console.log("projectNo:", projectNo);
|
||||
console.log("hasStatement:", hasStatement);
|
||||
|
||||
if(!projectNo) {
|
||||
alert("프로젝트 번호가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 흰색 폴더(저장 안 된 경우) 클릭 시 아무것도 안 함
|
||||
if(!hasStatement) {
|
||||
console.log("저장된 거래명세서가 없습니다. 팝업을 열지 않습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 해당 프로젝트의 데이터를 찾아서 localStorage에 저장
|
||||
var allData = _tabulGrid.getData();
|
||||
var projectData = allData.filter(function(row) {
|
||||
return row.PROJECT_NO === projectNo;
|
||||
});
|
||||
|
||||
if(projectData.length === 0) {
|
||||
alert("프로젝트 데이터를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem('transactionStatementData', JSON.stringify(projectData));
|
||||
// 파란폴더(저장된 경우)만 여기까지 도달 → DB 데이터 로드
|
||||
localStorage.setItem('loadSavedStatement', 'true');
|
||||
|
||||
// 거래명세서 팝업 열기
|
||||
var url = "/salesMgmt/transactionStatementForm.do?projectNos=" + encodeURIComponent(projectNo);
|
||||
var popup_width = 900;
|
||||
var popup_height = 800;
|
||||
var left = (screen.width - popup_width) / 2;
|
||||
var top = (screen.height - popup_height) / 2;
|
||||
|
||||
var popup = window.open(url, "transactionStatement", "width=" + popup_width + ",height=" + popup_height + ",left=" + left + ",top=" + top + ",scrollbars=yes,resizable=yes");
|
||||
|
||||
// 팝업이 닫힐 때 그리드 새로고침
|
||||
var checkPopup = setInterval(function() {
|
||||
if(popup.closed) {
|
||||
clearInterval(checkPopup);
|
||||
console.log("거래명세서 팝업 닫힘 - 그리드 새로고침");
|
||||
fn_search(); // 그리드 새로고침
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function fn_openShippingDetail(projectNo) {
|
||||
console.log("=== fn_openShippingDetail 호출 ===");
|
||||
console.log("전달받은 projectNo:", projectNo);
|
||||
console.log("projectNo 타입:", typeof projectNo);
|
||||
|
||||
if(!projectNo) {
|
||||
alert("프로젝트 번호가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var url = "/salesMgmt/shippingDetailPopup.do?projectNo=" + encodeURIComponent(projectNo);
|
||||
console.log("팝업 URL:", url);
|
||||
|
||||
window.open(url, "shippingDetailPopup", "width=800,height=600,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 출하지시/판매등록 함수 (1건만 선택 가능)
|
||||
function fn_bulkRegister(){
|
||||
if(!_tabulGrid){
|
||||
@@ -318,8 +547,8 @@ function fn_bulkRegister(){
|
||||
// 선택한 1건의 항목 가져오기
|
||||
var selectedRow = selectedRows[0];
|
||||
|
||||
// 판매등록 팝업 열기
|
||||
fn_openSaleRegPopup(selectedRow.PROJECT_NO, selectedRow.SALE_NO);
|
||||
// 판매등록 팝업 열기 (그리드 데이터 전달)
|
||||
fn_openSaleRegPopupWithData(selectedRow);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
@@ -335,6 +564,7 @@ function fn_bulkRegister(){
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="거래명세서 출력" class="plm_btns" id="btnTransactionStatement" style="background-color: #2196F3; color: white;">
|
||||
<input type="button" value="출하지시/판매등록" class="plm_btns" id="btnBulkRegister" style="background-color: #4CAF50; color: white;">
|
||||
</div>
|
||||
</div>
|
||||
@@ -444,16 +674,16 @@ function fn_bulkRegister(){
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Total 합계 표시 영역 (판매원화총액 기준) -->
|
||||
<div style="padding: 5px 10px; background: #f5f5f5; border-radius: 3px; margin: 10px 0;">
|
||||
<span style="font-weight: bold; font-size: 13px;">
|
||||
발주 금액 : <span id="totalSalesAmountKRW" style="color: #4CAF50;">0</span> 원
|
||||
<span style="margin-left: 10px; font-size: 12px;">
|
||||
(출고 : <span id="shippedAmountKRW" style="color: #2196F3;">0</span> 원,
|
||||
미출고 : <span id="notShippedAmountKRW" style="color: #FF9800;">0</span> 원)
|
||||
</span>
|
||||
<!-- Total 합계 표시 영역 (판매원화총액 기준) -->
|
||||
<div style=" background: #f5f5f5; border-radius: 3px; clear: both;">
|
||||
<span style="font-weight: bold; font-size: 13px;">
|
||||
발주 금액 : <span id="totalSalesAmountKRW" style="color: #4CAF50;">0</span> 원
|
||||
<span style="margin-left: 10px; font-size: 12px;">
|
||||
(출고 : <span id="shippedAmountKRW" style="color: #2196F3;">0</span> 원,
|
||||
미출고 : <span id="notShippedAmountKRW" style="color: #FF9800;">0</span> 원)
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
|
||||
<%@include file="/init_new.jsp"%>
|
||||
<%
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
@@ -13,12 +15,22 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
|
||||
<script type="text/javascript">
|
||||
// S/N 관리 전역 변수
|
||||
var snList = [];
|
||||
var snCounter = 1;
|
||||
|
||||
$(function() {
|
||||
console.log("=== salesRegForm.jsp 로드 ===");
|
||||
console.log("SALES_QUANTITY: ${saleInfo.SALES_QUANTITY}");
|
||||
console.log("SALES_UNIT_PRICE: ${saleInfo.SALES_UNIT_PRICE}");
|
||||
console.log("SALES_SUPPLY_PRICE: ${saleInfo.SALES_SUPPLY_PRICE}");
|
||||
console.log("SALES_VAT: ${saleInfo.SALES_VAT}");
|
||||
console.log("SALES_TOTAL_AMOUNT: ${saleInfo.SALES_TOTAL_AMOUNT}");
|
||||
console.log("SALES_CURRENCY: ${saleInfo.SALES_CURRENCY}");
|
||||
console.log("SALES_EXCHANGE_RATE: ${saleInfo.SALES_EXCHANGE_RATE}");
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// 날짜 선택기 초기화
|
||||
@@ -33,18 +45,6 @@
|
||||
// 판매환종 초기값 설정 (견적환종과 동기화)
|
||||
initializeSalesCurrency();
|
||||
|
||||
// 페이지 로드 시 금액 자동 계산 (수주 데이터가 있을 때)
|
||||
setTimeout(function() {
|
||||
var quantity = parseFloat($("#salesQuantity").val()) || 0;
|
||||
var unitPrice = parseFloat($("#salesUnitPrice").val()) || 0;
|
||||
|
||||
// 수주 데이터가 있으면 자동 계산
|
||||
if(quantity > 0 || unitPrice > 0) {
|
||||
fn_calculateSupplyPrice();
|
||||
console.log("페이지 로드 시 금액 자동 계산 완료");
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// S/N 필드 클릭 이벤트
|
||||
$("#serialNo").click(function() {
|
||||
fn_openSnManagePopup();
|
||||
@@ -75,13 +75,77 @@
|
||||
self.close();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function() {
|
||||
fn_save();
|
||||
});
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function() {
|
||||
fn_save();
|
||||
});
|
||||
|
||||
// 품목이 여러 개인 경우 자동으로 첫 번째 품목 선택 - 주석처리: 품목은 하나만 존재
|
||||
/*
|
||||
if($(".item-radio").length > 0) {
|
||||
$(".item-radio").first().prop("checked", true);
|
||||
fn_calculateSelectedItem();
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
// 판매공급가액 계산 함수
|
||||
// === Phase 2: 품목 선택 관련 함수 (단일 선택) - 주석처리: 품목은 하나만 존재 ===
|
||||
/*
|
||||
// 행 클릭 시 라디오 버튼 선택
|
||||
function fn_selectItem(itemObjid) {
|
||||
$(".item-radio[value='" + itemObjid + "']").prop("checked", true);
|
||||
fn_calculateSelectedItem();
|
||||
}
|
||||
|
||||
// 선택한 품목의 정보를 입력 필드에 반영
|
||||
function fn_calculateSelectedItem() {
|
||||
var selectedRadio = $(".item-radio:checked");
|
||||
|
||||
if(selectedRadio.length === 0) {
|
||||
$("#selectedItemInfo").text("품목을 선택하세요");
|
||||
return;
|
||||
}
|
||||
|
||||
var quantity = parseFloat(selectedRadio.data("quantity")) || 0;
|
||||
var unitPrice = parseFloat(selectedRadio.data("unit-price")) || 0;
|
||||
var supplyPrice = parseFloat(selectedRadio.data("supply-price")) || 0;
|
||||
var vat = parseFloat(selectedRadio.data("vat")) || 0;
|
||||
var totalAmount = parseFloat(selectedRadio.data("total")) || 0;
|
||||
|
||||
// 선택한 품목 정보 표시
|
||||
var itemObjid = selectedRadio.val();
|
||||
var itemRow = $("tr[data-item-objid='" + itemObjid + "']");
|
||||
var partNo = itemRow.find("td:eq(1)").text().trim();
|
||||
var partName = itemRow.find("td:eq(2)").text().trim();
|
||||
|
||||
$("#selectedItemInfo").html(
|
||||
"<strong>" + partName + "</strong> (" + partNo + ") - " +
|
||||
"수량: <strong>" + quantity.toLocaleString() + "</strong>개 | " +
|
||||
"공급가액: <strong>" + supplyPrice.toLocaleString() + "</strong>원"
|
||||
);
|
||||
|
||||
// 입력 필드에 자동 반영
|
||||
$("#salesQuantity").val(quantity);
|
||||
$("#salesUnitPrice").val(unitPrice);
|
||||
$("#salesSupplyPrice").val(supplyPrice);
|
||||
$("#salesVat").val(vat);
|
||||
$("#salesTotalAmount").val(totalAmount);
|
||||
|
||||
// hidden 필드에 선택한 품목 OBJID 저장
|
||||
if($("#selectedItemObjid").length === 0) {
|
||||
$("<input>").attr({
|
||||
type: "hidden",
|
||||
id: "selectedItemObjid",
|
||||
name: "selectedItemObjid"
|
||||
}).appendTo("form");
|
||||
}
|
||||
$("#selectedItemObjid").val(itemObjid);
|
||||
}
|
||||
*/
|
||||
|
||||
// === 기존 함수들 ===
|
||||
|
||||
// 판매공급가액 계산 함수
|
||||
function fn_calculateSupplyPrice() {
|
||||
var currency = $("#salesCurrency").val();
|
||||
var exchangeRate = parseFloat($("#salesExchangeRate").val()) || 1;
|
||||
@@ -120,6 +184,7 @@
|
||||
|
||||
// 판매환종 초기값 설정 (견적환종과 동기화하되, 사용자가 변경 가능)
|
||||
function initializeSalesCurrency() {
|
||||
// Controller에서 계산한 값 사용 (잔량 기반)
|
||||
var existingSalesCurrency = "${saleInfo.SALES_CURRENCY}";
|
||||
var contractCurrency = "${orderInfo.SALES_CURRENCY}"; // 견적환종 (SALES_CURRENCY로 통일)
|
||||
var contractExchangeRate = "${orderInfo.SALES_EXCHANGE_RATE}"; // 견적환율
|
||||
@@ -511,23 +576,78 @@
|
||||
}
|
||||
console.log("=== S/N 처리 완료 ===");
|
||||
|
||||
if (confirm("저장하시겠습니까?")) {
|
||||
if (confirm("저장하시겠습니까?")) {
|
||||
$.ajax({
|
||||
url : "/salesMgmt/saveSales.do",
|
||||
type : "POST",
|
||||
data : $("#form1").serialize(),
|
||||
dataType : "json",
|
||||
success : function(data) {
|
||||
alert(data.msg);
|
||||
|
||||
// 저장 후 잔량 확인을 위해 서버에 다시 조회
|
||||
$.ajax({
|
||||
url : "/salesMgmt/saveSales.do",
|
||||
type : "POST",
|
||||
data : $("#form1").serialize(),
|
||||
dataType : "json",
|
||||
success : function(data) {
|
||||
alert(data.msg);
|
||||
url: "/salesMgmt/salesRegForm.do",
|
||||
type: "GET",
|
||||
data: { orderNo: "${param.orderNo}" },
|
||||
dataType: "html",
|
||||
success: function(response) {
|
||||
// 응답에서 SALES_QUANTITY 추출 (잔량)
|
||||
var match = response.match(/SALES_QUANTITY:\s*(\d+)/);
|
||||
var remainingQuantity = match ? parseInt(match[1]) : 0;
|
||||
|
||||
console.log("서버에서 계산한 잔량:", remainingQuantity);
|
||||
|
||||
if(remainingQuantity > 0) {
|
||||
if(confirm("잔량 " + remainingQuantity + "개가 남았습니다. 계속 등록하시겠습니까?")) {
|
||||
// 부모 창 새로고침 후 팝업 새로고침
|
||||
if(opener && opener.fn_search) {
|
||||
console.log("분할 출하 계속 - 부모 창 fn_search 호출");
|
||||
opener.fn_search();
|
||||
}
|
||||
// 팝업 새로고침 (잔량으로 수량 자동 설정)
|
||||
location.reload();
|
||||
} else {
|
||||
// 목록 새로고침 후 팝업 닫기
|
||||
console.log("분할 출하 중단 - 팝업 닫기");
|
||||
if(opener && opener.fn_search) {
|
||||
console.log("부모 창 fn_search 호출");
|
||||
opener.fn_search();
|
||||
} else {
|
||||
console.log("부모 창 fn_search 없음!");
|
||||
}
|
||||
self.close();
|
||||
}
|
||||
} else {
|
||||
// 목록 새로고침 후 팝업 닫기
|
||||
console.log("잔량 없음 - 팝업 닫기");
|
||||
if(opener && opener.fn_search) {
|
||||
console.log("부모 창 fn_search 호출");
|
||||
opener.fn_search();
|
||||
} else {
|
||||
console.log("부모 창 fn_search 없음!");
|
||||
}
|
||||
self.close();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
// 에러 시 그냥 팝업 닫기
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
self.close();
|
||||
},
|
||||
error : function(jqxhr, status, error) {
|
||||
alert("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
},
|
||||
error : function(jqxhr, status, error) {
|
||||
console.log("=== AJAX 에러 ===");
|
||||
console.log("status:", status);
|
||||
console.log("error:", error);
|
||||
console.log("responseText:", jqxhr.responseText);
|
||||
console.log("status code:", jqxhr.status);
|
||||
alert("저장 중 오류가 발생했습니다.\n상태: " + status + "\n에러: " + error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,6 +729,67 @@
|
||||
<col width="35%" />
|
||||
</colgroup>
|
||||
|
||||
<!-- 품목 선택 영역 (Phase 2) - 주석처리: 품목은 하나만 존재 -->
|
||||
<%--
|
||||
<c:if test="${not empty projectItems and fn:length(projectItems) > 1}">
|
||||
<tr>
|
||||
<td colspan="4" style="padding:10px;">
|
||||
<div style="border:1px solid #ddd; padding:10px; background:#f9f9f9;">
|
||||
<strong style="display:block; margin-bottom:8px;">📦 품목 선택 (${fn:length(projectItems)}개) - 하나만 선택 가능</strong>
|
||||
<table style="width:100%; border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr style="background:#e9ecef; border-bottom:2px solid #dee2e6;">
|
||||
<th style="padding:8px; text-align:center; width:50px;">선택</th>
|
||||
<th style="padding:8px; text-align:left;">품번</th>
|
||||
<th style="padding:8px; text-align:left;">품명</th>
|
||||
<th style="padding:8px; text-align:right;">수량</th>
|
||||
<th style="padding:8px; text-align:right;">단가</th>
|
||||
<th style="padding:8px; text-align:right;">공급가액</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="itemListBody">
|
||||
<c:forEach var="item" items="${projectItems}" varStatus="status">
|
||||
<tr style="border-bottom:1px solid #dee2e6; cursor:pointer;"
|
||||
data-item-objid="${item.ITEM_OBJID}"
|
||||
onclick="fn_selectItem('${item.ITEM_OBJID}')">
|
||||
<td style="padding:8px; text-align:center;">
|
||||
<input type="radio" name="selectedItem" class="item-radio"
|
||||
value="${item.ITEM_OBJID}"
|
||||
data-objid="${item.ITEM_OBJID}"
|
||||
data-quantity="${item.QUANTITY}"
|
||||
data-unit-price="${item.UNIT_PRICE}"
|
||||
data-supply-price="${item.SUPPLY_PRICE}"
|
||||
data-vat="${item.VAT}"
|
||||
data-total="${item.TOTAL_AMOUNT}"
|
||||
onchange="fn_calculateSelectedItem()" />
|
||||
</td>
|
||||
<td style="padding:8px;">${item.PART_NO}</td>
|
||||
<td style="padding:8px;">${item.PART_NAME}</td>
|
||||
<td style="padding:8px; text-align:right;">
|
||||
<fmt:formatNumber value="${item.QUANTITY}" pattern="#,##0" />
|
||||
</td>
|
||||
<td style="padding:8px; text-align:right;">
|
||||
<fmt:formatNumber value="${item.UNIT_PRICE}" pattern="#,##0" />
|
||||
</td>
|
||||
<td style="padding:8px; text-align:right;">
|
||||
<fmt:formatNumber value="${item.SUPPLY_PRICE}" pattern="#,##0" />
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-top:10px; padding:8px; background:#d1ecf1; border:1px solid #0c5460; border-radius:4px;">
|
||||
<strong>💡 선택한 품목:</strong>
|
||||
<span id="selectedItemInfo" style="margin-left:10px; color:#0c5460;">
|
||||
품목을 선택하세요
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</c:if>
|
||||
--%>
|
||||
|
||||
<!-- 첫번째 행: S/N -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="serialNo">S/N</label></td>
|
||||
@@ -621,38 +802,75 @@
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 두번째 행: 판매수량, 출하일 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="salesQuantity">판매수량</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesQuantity" id="salesQuantity" value="${saleInfo.SALES_QUANTITY}" onchange="fn_calculateSupplyPrice()" />
|
||||
</td>
|
||||
<td class="input_title"><label for="shippingDate">출하일</label></td>
|
||||
<td>
|
||||
<input type="text" id="shippingDate" name="shippingDate" class="date_icon" value="${saleInfo.SHIPPING_DATE}" autocomplete="off" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 세번째 행: 출하방법, 담당자 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="shippingMethod">출하방법</label></td>
|
||||
<td>
|
||||
<select name="shippingMethod" id="shippingMethod" class="select2">
|
||||
<option value="">선택</option>
|
||||
<option value="내수/직납" ${saleInfo.SHIPPING_METHOD == '내수/직납' ? 'selected' : ''}>내수/직납</option>
|
||||
<option value="내수/택배" ${saleInfo.SHIPPING_METHOD == '내수/택배' ? 'selected' : ''}>내수/택배</option>
|
||||
<option value="내수/기타" ${saleInfo.SHIPPING_METHOD == '내수/기타' ? 'selected' : ''}>내수/기타</option>
|
||||
<option value="수출" ${saleInfo.SHIPPING_METHOD == '수출' ? 'selected' : ''}>수출</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="input_title"><label for="manager">담당자</label></td>
|
||||
<td>
|
||||
<select name="manager" id="manager" class="select2">
|
||||
<option value="">선택</option>
|
||||
${codeMap.managerList}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 두번째 행: 수주수량, 판매수량 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="orderQuantity">수주수량</label></td>
|
||||
<td>
|
||||
<input type="number" name="orderQuantity" id="orderQuantity"
|
||||
value="${saleInfo.ORDER_QUANTITY}"
|
||||
readonly style="background-color: #f5f5f5;" />
|
||||
</td>
|
||||
<c:choose>
|
||||
<c:when test="${param.saleNo != null && param.saleNo != ''}">
|
||||
<!-- 수정 모드: 판매수량만 표시 (읽기 전용) -->
|
||||
<td class="input_title"><label for="salesQuantity">판매수량</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesQuantity" id="salesQuantity"
|
||||
value="${saleInfo.SALES_QUANTITY}"
|
||||
readonly style="background-color: #f5f5f5;" />
|
||||
</td>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<!-- 신규 등록 모드: 판매수량 입력 가능 + 잔량 표시 -->
|
||||
<td class="input_title">
|
||||
<label for="salesQuantity">판매수량</label>
|
||||
<span style="color:#666; font-size:11px; display:block; margin-top:2px;">
|
||||
(잔량: ${saleInfo.REMAINING_QUANTITY != null ? saleInfo.REMAINING_QUANTITY : saleInfo.ORDER_QUANTITY}개)
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="number" name="salesQuantity" id="salesQuantity"
|
||||
value="${saleInfo.SALES_QUANTITY != null && saleInfo.SALES_QUANTITY != '' && saleInfo.SALES_QUANTITY != 0 ? saleInfo.SALES_QUANTITY : ''}"
|
||||
onchange="fn_calculateSupplyPrice()"
|
||||
placeholder="판매할 수량 입력 (잔량: ${saleInfo.REMAINING_QUANTITY != null ? saleInfo.REMAINING_QUANTITY : saleInfo.ORDER_QUANTITY}개)" />
|
||||
</td>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</tr>
|
||||
|
||||
<!-- 세번째 행: 출하일, 출하방법 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="shippingDate">출하일</label></td>
|
||||
<td>
|
||||
<input type="text" id="shippingDate" name="shippingDate" class="date_icon" value="${saleInfo.SHIPPING_DATE}" autocomplete="off" />
|
||||
</td>
|
||||
<td class="input_title"><label for="shippingMethod">출하방법</label></td>
|
||||
<td>
|
||||
<select name="shippingMethod" id="shippingMethod" class="select2">
|
||||
<option value="">선택</option>
|
||||
<option value="직접배송" ${saleInfo.SHIPPING_METHOD == '직접배송' ? 'selected' : ''}>직접배송</option>
|
||||
<option value="택배" ${saleInfo.SHIPPING_METHOD == '택배' ? 'selected' : ''}>택배</option>
|
||||
<option value="화물" ${saleInfo.SHIPPING_METHOD == '화물' ? 'selected' : ''}>화물</option>
|
||||
<option value="퀵서비스" ${saleInfo.SHIPPING_METHOD == '퀵서비스' ? 'selected' : ''}>퀵서비스</option>
|
||||
<option value="기타" ${saleInfo.SHIPPING_METHOD == '기타' ? 'selected' : ''}>기타</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 네번째 행: 담당자, INCOTERMS -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="manager">담당자</label></td>
|
||||
<td>
|
||||
<select name="manager" id="manager" class="select2">
|
||||
<option value="">선택</option>
|
||||
${codeMap.managerList}
|
||||
</select>
|
||||
</td>
|
||||
<td class="input_title"><label for="incoterms">INCOTERMS</label></td>
|
||||
<td>
|
||||
<input type="text" name="incoterms" id="incoterms" value="${saleInfo.INCOTERMS}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
@@ -681,11 +899,15 @@
|
||||
<tr>
|
||||
<td class="input_title"><label for="salesUnitPrice">판매단가</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesUnitPrice" id="salesUnitPrice" value="${saleInfo.SALES_UNIT_PRICE}" onchange="fn_calculateSupplyPrice()" />
|
||||
<input type="number" name="salesUnitPrice" id="salesUnitPrice"
|
||||
value="${saleInfo.SALES_UNIT_PRICE}"
|
||||
onchange="fn_calculateSupplyPrice()" />
|
||||
</td>
|
||||
<td class="input_title"><label for="salesSupplyPrice">판매공급가액</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesSupplyPrice" id="salesSupplyPrice" value="${saleInfo.SALES_SUPPLY_PRICE}" readonly style="background-color:#f5f5f5;" />
|
||||
<input type="number" name="salesSupplyPrice" id="salesSupplyPrice"
|
||||
value="${saleInfo.SALES_SUPPLY_PRICE}"
|
||||
readonly style="background-color:#f5f5f5;" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -693,11 +915,15 @@
|
||||
<tr>
|
||||
<td class="input_title"><label for="salesVat">판매부가세</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesVat" id="salesVat" value="${saleInfo.SALES_VAT}" onchange="fn_calculateTotalAmount()" />
|
||||
<input type="number" name="salesVat" id="salesVat"
|
||||
value="${saleInfo.SALES_VAT}"
|
||||
readonly style="background-color:#f5f5f5;" />
|
||||
</td>
|
||||
<td class="input_title"><label for="salesTotalAmount">판매총액</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesTotalAmount" id="salesTotalAmount" value="${saleInfo.SALES_TOTAL_AMOUNT}" readonly style="background-color:#f5f5f5;" />
|
||||
<input type="number" name="salesTotalAmount" id="salesTotalAmount"
|
||||
value="${saleInfo.SALES_TOTAL_AMOUNT}"
|
||||
readonly style="background-color:#f5f5f5;" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -712,7 +938,9 @@
|
||||
</td>
|
||||
<td class="input_title"><label for="salesExchangeRate">판매환율</label></td>
|
||||
<td>
|
||||
<input type="number" name="salesExchangeRate" id="salesExchangeRate" step="0.01" value="${saleInfo.SALES_EXCHANGE_RATE}" onchange="fn_recalculateByExchangeRate()" />
|
||||
<input type="number" name="salesExchangeRate" id="salesExchangeRate" step="0.01"
|
||||
value="${saleInfo.SALES_EXCHANGE_RATE}"
|
||||
onchange="fn_recalculateByExchangeRate()" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -745,7 +973,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>출하일 상세 내역</title>
|
||||
<link rel="stylesheet" href="/css/basic.css">
|
||||
<script src="/js/jquery-2.1.4.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
font-family: 'Malgun Gothic', sans-serif;
|
||||
}
|
||||
.popup-header {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid #333;
|
||||
}
|
||||
.shipping-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.shipping-table th {
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.shipping-table td {
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
text-align: center;
|
||||
}
|
||||
.btn-close {
|
||||
padding: 8px 20px;
|
||||
background-color: #666;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
.btn-close:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
.btn-wrap {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="popup-header">
|
||||
출하일 상세 내역 - ${projectNo}
|
||||
</div>
|
||||
|
||||
<table class="shipping-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>출하일</th>
|
||||
<th>출하수량</th>
|
||||
<th>출하지시상태</th>
|
||||
<th>S/N</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:choose>
|
||||
<c:when test="${empty shippingList}">
|
||||
<tr>
|
||||
<td colspan="4">출하 내역이 없습니다.</td>
|
||||
</tr>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<c:forEach items="${shippingList}" var="item">
|
||||
<tr>
|
||||
<td>${item.shipping_date}</td>
|
||||
<td>${item.shipping_quantity}</td>
|
||||
<td>${item.shipping_order_status}</td>
|
||||
<td>${item.serial_no}</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="btn-wrap">
|
||||
<button type="button" class="btn-close" onclick="window.close();">닫기</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
BIN
WebContent/images/stamp_seal.png
Normal file
BIN
WebContent/images/stamp_seal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 KiB |
@@ -59,7 +59,7 @@ function fnc_tabul_search(layoutParam, gridObj, searchURL, columnParam, showChec
|
||||
if(showApp) allColumns = allColumns.concat(_columnAppStatus);
|
||||
|
||||
gridObj = new Tabulator("#mainGrid", {
|
||||
height : "auto",//"640px",
|
||||
height : "100%",
|
||||
layout : fnc_checkNullDefaultValue(layoutParam, _tabul_layout_fitDataStretch), //fitDataFill fitDataStretch
|
||||
//selectable: true,
|
||||
placeholder : "조회된 정보가 없습니다.",
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -888,23 +889,110 @@ public class PartMngController {
|
||||
}
|
||||
|
||||
/**
|
||||
* bom copy 저장
|
||||
* BOM COPY (M-BOM 관리에서 호출)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/partMng/structureBomCopyFormPopup.do")
|
||||
public String structureBomCopyFormPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
try {
|
||||
String objId = CommonUtils.checkNull((String)paramMap.get("objId"));
|
||||
System.out.println("========== structureBomCopyFormPopup ==========");
|
||||
System.out.println("objId: " + objId);
|
||||
|
||||
// objId를 항상 설정 (음수 포함)
|
||||
request.setAttribute("TARGET_OBJID", objId);
|
||||
|
||||
// objId가 유효한 경우 프로젝트 정보 조회 (음수도 유효한 OBJID임)
|
||||
if(!"".equals(objId) && !"-1".equals(objId)) {
|
||||
try {
|
||||
long objIdLong = Long.parseLong(objId);
|
||||
System.out.println("objIdLong: " + objIdLong);
|
||||
|
||||
// PROJECT_MGMT 테이블에서 품번/품명 조회 (M-BOM 관리 리스트의 OBJID는 PROJECT_MGMT의 OBJID)
|
||||
Map<String, Object> projectInfo = commonService.selectOne("productionplanning.getProjectMgmtDetail", request, paramMap);
|
||||
System.out.println("projectInfo: " + projectInfo);
|
||||
|
||||
if(projectInfo != null) {
|
||||
System.out.println("PART_NO: " + projectInfo.get("PART_NO"));
|
||||
System.out.println("PART_NAME: " + projectInfo.get("PART_NAME"));
|
||||
request.setAttribute("projectInfo", projectInfo);
|
||||
} else {
|
||||
System.out.println("projectInfo is null!");
|
||||
}
|
||||
} catch(NumberFormatException nfe) {
|
||||
System.out.println("NumberFormatException: " + nfe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Map code_map = new HashMap();
|
||||
code_map.put("rev", commonService.bizMakeOptionList("", "", "common.getRevNoselect"));
|
||||
code_map.put("product_code", commonService.bizMakeOptionList("", "", "common.getProductNoselect"));
|
||||
request.setAttribute("code_map", code_map);
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "/partMng/structureBomCopyFormPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* bom copy 저장 (E-BOM을 M-BOM으로 복사)
|
||||
*/
|
||||
@RequestMapping("/partMng/saveBomCopy.do")
|
||||
@ResponseBody
|
||||
public String saveBomCopySave(HttpSession session, HttpServletRequest request, @RequestParam Map paramMap){
|
||||
String result = "";
|
||||
public Map<String, Object> saveBomCopySave(HttpSession session, HttpServletRequest request, @RequestBody Map<String, Object> paramMap){
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try{
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("CONNECTUSERID", CommonUtils.checkNull(person.getUserId()));
|
||||
System.out.println("========== saveBomCopy ==========");
|
||||
System.out.println("paramMap: " + paramMap);
|
||||
|
||||
partMngService.saveBomCopySave(request, paramMap);
|
||||
result = "SUCCESS";
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = person.getUserId();
|
||||
|
||||
// targetObjId: PROJECT_MGMT의 OBJID
|
||||
String targetObjId = CommonUtils.checkNull((String)paramMap.get("targetObjId"));
|
||||
String sourceBomObjId = CommonUtils.checkNull((String)paramMap.get("sourceBomObjId"));
|
||||
String targetPartNo = CommonUtils.checkNull((String)paramMap.get("targetPartNo"));
|
||||
String targetPartName = CommonUtils.checkNull((String)paramMap.get("targetPartName"));
|
||||
List<Map<String, Object>> bomData = (List<Map<String, Object>>)paramMap.get("bomData");
|
||||
|
||||
if(bomData == null || bomData.isEmpty()) {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "복사할 BOM 데이터가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// M-BOM 저장
|
||||
Map<String, Object> saveParam = new HashMap<String, Object>();
|
||||
saveParam.put("PROJECT_OBJID", targetObjId);
|
||||
saveParam.put("SOURCE_BOM_OBJID", sourceBomObjId);
|
||||
saveParam.put("PART_NO", targetPartNo);
|
||||
saveParam.put("PART_NAME", targetPartName);
|
||||
saveParam.put("BOM_DATA", bomData);
|
||||
saveParam.put("USER_ID", userId);
|
||||
|
||||
// SqlSession을 통해 직접 실행
|
||||
SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
try {
|
||||
sqlSession.insert("productionplanning.saveMbomFromEbom", saveParam);
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("message", "M-BOM이 성공적으로 생성되었습니다.");
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
result = "FAIL";
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "BOM 복사 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
return result;
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -1782,6 +1870,44 @@ public class PartMngController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품번으로 BOM OBJID 조회
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/partMng/getBomObjIdByPartNo.do")
|
||||
@ResponseBody
|
||||
public Map<String, Object> getBomObjIdByPartNo(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try{
|
||||
String partNo = CommonUtils.checkNull(paramMap.get("partNo"));
|
||||
|
||||
if(partNo.isEmpty()) {
|
||||
resultMap.put("OBJID", null);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 품번으로 BOM OBJID 조회
|
||||
Map<String, Object> bomInfo = partMngService.getBomObjIdByPartNo(paramMap);
|
||||
|
||||
if(bomInfo != null) {
|
||||
resultMap.put("OBJID", bomInfo.get("OBJID"));
|
||||
resultMap.put("PART_NO", bomInfo.get("PART_NO"));
|
||||
resultMap.put("PART_NAME", bomInfo.get("PART_NAME"));
|
||||
} else {
|
||||
resultMap.put("OBJID", null);
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
resultMap.put("OBJID", null);
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품번 중복 체크 (PART_BOM_REPORT 테이블)
|
||||
* @param request
|
||||
|
||||
@@ -9,10 +9,12 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.pms.common.service.BaseService;
|
||||
import com.pms.common.utils.CommonUtils;
|
||||
import com.pms.common.utils.Constants;
|
||||
@@ -933,6 +935,208 @@ public class ProductionPlanningController extends BaseService {
|
||||
return "/productionplanning/mBomEbomSelectPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 (읽기 전용)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomViewPopup.do")
|
||||
public String mBomViewPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/mBomViewPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 복사 팝업 메인 (frameset)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomFormPopup.do")
|
||||
public String mBomFormPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
try {
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
System.out.println("========== mBomFormPopup ==========");
|
||||
System.out.println("objId: " + objId);
|
||||
|
||||
// PROJECT_MGMT 정보 조회
|
||||
if(!"".equals(objId)) {
|
||||
paramMap.put("objId", objId);
|
||||
Map<String, Object> projectInfo = commonService.selectOne("productionplanning.getProjectMgmtDetail", request, paramMap);
|
||||
System.out.println("projectInfo: " + projectInfo);
|
||||
|
||||
if(projectInfo != null && !projectInfo.isEmpty()) {
|
||||
request.setAttribute("info", projectInfo);
|
||||
} else {
|
||||
System.out.println("projectInfo is null or empty!");
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/productionplanning/mBomPopupHeaderFs";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 상단 헤더
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomHeaderPopup.do")
|
||||
public String mBomHeaderPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
try {
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
if(!"".equals(objId)) {
|
||||
paramMap.put("objId", objId);
|
||||
Map<String, Object> projectInfo = commonService.selectOne("productionplanning.getProjectMgmtDetail", request, paramMap);
|
||||
request.setAttribute("info", projectInfo);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/productionplanning/mBomHeaderPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 중앙 버튼 영역
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomCenterBtnPopup.do")
|
||||
public String mBomCenterBtnPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/mBomCenterBtnPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 중앙 버튼 영역
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomPopupCenter.do")
|
||||
public String mBomPopupCenter(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/mBomPopupCenter";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 오른쪽 E-BOM 목록
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomPopupRight.do")
|
||||
public String mBomPopupRight(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/mBomPopupRight";
|
||||
}
|
||||
|
||||
/**
|
||||
* E-BOM 목록 조회 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/getEbomList.do")
|
||||
@ResponseBody
|
||||
public Map<String, Object> getEbomList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
List<Map<String, Object>> list = commonService.selectList("productionplanning.getEbomList", request, paramMap);
|
||||
result.put("list", list);
|
||||
result.put("result", true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
result.put("result", false);
|
||||
result.put("list", new ArrayList<>());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 하단 frameset
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomBottomPopupFS.do")
|
||||
public String mBomBottomPopupFS(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/mBomPopupFs";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 조회 팝업 왼쪽 트리
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/productionplanning/mBomPopupLeft.do")
|
||||
public String mBomPopupLeft(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Gson gson = new Gson();
|
||||
try {
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
|
||||
// PROJECT_MGMT 정보 조회
|
||||
if(!"".equals(objId)) {
|
||||
paramMap.put("objId", objId);
|
||||
Map<String, Object> projectInfo = commonService.selectOne("productionplanning.getProjectMgmtDetail", request, paramMap);
|
||||
|
||||
if(projectInfo != null) {
|
||||
// 1. 먼저 저장된 M-BOM 데이터가 있는지 확인
|
||||
List<Map<String, Object>> mbomDetailList = commonService.selectList("productionplanning.getMbomDetailByProject", request, paramMap);
|
||||
|
||||
if(mbomDetailList != null && !mbomDetailList.isEmpty()) {
|
||||
// 저장된 M-BOM 데이터가 있으면 이를 표시
|
||||
int maxLevel = 1;
|
||||
for(Map<String, Object> item : mbomDetailList) {
|
||||
Integer level = (Integer) item.get("LEVEL");
|
||||
if(level != null && level > maxLevel) {
|
||||
maxLevel = level;
|
||||
}
|
||||
}
|
||||
|
||||
request.setAttribute("MAXLEV", maxLevel);
|
||||
request.setAttribute("bomTreeListJson", gson.toJson(mbomDetailList));
|
||||
return "/productionplanning/mBomPopupLeft";
|
||||
}
|
||||
|
||||
// 저장된 M-BOM이 없으면 할당된 E-BOM 정보 조회
|
||||
String bomReportObjid = CommonUtils.checkNull(projectInfo.get("BOM_REPORT_OBJID"));
|
||||
if(!"".equals(bomReportObjid)) {
|
||||
Map<String, Object> ebomParam = new HashMap<>();
|
||||
ebomParam.put("objId", bomReportObjid);
|
||||
ebomParam.put("bomReportObjId", bomReportObjid);
|
||||
|
||||
// E-BOM 정보 조회
|
||||
Map<String, Object> ebomInfo = commonService.selectOne("partMng.getBomReportInfo", request, ebomParam);
|
||||
request.setAttribute("ebomInfo", ebomInfo);
|
||||
|
||||
// BOM 트리 데이터 조회 (레벨 정보 포함)
|
||||
List<Map<String, Object>> bomTreeList = commonService.selectList("partMng.getBOMTreeList", request, ebomParam);
|
||||
|
||||
if(bomTreeList != null && !bomTreeList.isEmpty()) {
|
||||
// MAX LEVEL 계산
|
||||
int maxLevel = 1;
|
||||
for(Map<String, Object> item : bomTreeList) {
|
||||
Integer level = (Integer) item.get("LEVEL");
|
||||
if(level != null && level > maxLevel) {
|
||||
maxLevel = level;
|
||||
}
|
||||
}
|
||||
request.setAttribute("MAXLEV", maxLevel);
|
||||
request.setAttribute("bomTreeListJson", gson.toJson(bomTreeList));
|
||||
return "/productionplanning/mBomPopupLeft";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 데이터가 없을 때 빈 배열 설정
|
||||
request.setAttribute("MAXLEV", 1);
|
||||
request.setAttribute("bomTreeListJson", "[]");
|
||||
return "/productionplanning/mBomPopupLeft";
|
||||
}
|
||||
|
||||
/**
|
||||
* E-BOM을 M-BOM(PROJECT_MGMT)에 할당
|
||||
* @param request
|
||||
@@ -970,4 +1174,67 @@ public class ProductionPlanningController extends BaseService {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 목록 조회 (검색 조건 포함)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/getMbomList.do")
|
||||
public Map<String, Object> getMbomList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
// 검색 조건에 맞는 M-BOM 목록 조회
|
||||
List<Map<String, Object>> list = commonService.selectList("productionplanning.getMbomList", request, paramMap);
|
||||
result.put("list", list);
|
||||
result.put("result", true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
result.put("result", false);
|
||||
result.put("list", new ArrayList<>());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 저장
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/saveMbom.do")
|
||||
public Map<String, Object> saveMbom(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
try {
|
||||
// M-BOM 데이터 저장 로직
|
||||
List<Map<String, Object>> mbomData = (List<Map<String, Object>>) paramMap.get("mbomData");
|
||||
String partNo = CommonUtils.checkNull(paramMap.get("partNo"));
|
||||
String partName = CommonUtils.checkNull(paramMap.get("partName"));
|
||||
|
||||
if(mbomData == null || mbomData.isEmpty()) {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "저장할 데이터가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// M-BOM 저장 서비스 호출
|
||||
int saveResult = productionPlanningService.saveMbom(request, mbomData, partNo, partName);
|
||||
|
||||
if(saveResult > 0) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("message", "M-BOM이 저장되었습니다.");
|
||||
} else {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "저장에 실패했습니다.");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2530,18 +2530,18 @@ SELECT option_objid::VARCHAR AS CODE
|
||||
AND PRODUCT_MGMT_OBJID::VARCHAR = #{codeId}::VARCHAR
|
||||
</select>
|
||||
|
||||
<select id="getRevNoselect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.OBJID::varchar AS CODE
|
||||
,T.REV AS NAME
|
||||
,T1.PRODUCT_CODE AS CODE_CD
|
||||
,'' AS STATUS
|
||||
,T.spec_name AS ID
|
||||
,'' AS EXT_VAL
|
||||
FROM PART_BOM_REPORT T,PRODUCT_MGMT T1
|
||||
WHERE T.PRODUCT_MGMT_OBJID = T1.OBJID
|
||||
AND T1.OBJID = #{code}::numeric
|
||||
ORDER BY T.REV
|
||||
<select id="getRevNoselect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.OBJID::varchar AS CODE
|
||||
,COALESCE(T.REVISION, T.REV, '1.0') AS NAME
|
||||
,T1.PRODUCT_CODE AS CODE_CD
|
||||
,'' AS STATUS
|
||||
,T.spec_name AS ID
|
||||
,'' AS EXT_VAL
|
||||
FROM PART_BOM_REPORT T,PRODUCT_MGMT T1
|
||||
WHERE T.PRODUCT_MGMT_OBJID = T1.OBJID
|
||||
AND T1.OBJID = #{code}::numeric
|
||||
ORDER BY COALESCE(T.REVISION, T.REV, '1.0')
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
@@ -2999,6 +2999,22 @@ SELECT T1.LEV, T1.BOM_REPORT_OBJID, T1.ROOT_PART_NO, T1.PATH, T1.LEAF, T2.*
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 품번으로 BOM OBJID 조회 -->
|
||||
<select id="getBomObjIdByPartNo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
PART_NO,
|
||||
PART_NAME
|
||||
FROM PART_BOM_REPORT
|
||||
WHERE PART_NO = #{partNo}
|
||||
AND PART_NO IS NOT NULL
|
||||
AND TRIM(PART_NO) != ''
|
||||
AND PART_NAME IS NOT NULL
|
||||
AND TRIM(PART_NAME) != ''
|
||||
ORDER BY REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- BOM 복사를 위한 파트 목록 조회 -->
|
||||
<select id="getBomPartListForCopy" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
|
||||
@@ -2870,8 +2870,9 @@
|
||||
ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 관리 목록 조회 -->
|
||||
<!-- M-BOM 관리 목록 조회 - 품목별로 나눠서 보이기 (판매관리와 동일) -->
|
||||
<select id="mBomMgmtGridList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
/* productionplanning.mBomMgmtGridList - 품목별로 나눠서 조회 (CONTRACT_ITEM 기준) */
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.CONTRACT_OBJID,
|
||||
@@ -2906,54 +2907,40 @@
|
||||
ELSE ''
|
||||
END
|
||||
) AS PAID_TYPE_NAME,
|
||||
COALESCE(PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PM.PART_NAME, '') AS PART_NAME,
|
||||
-- S/N: CONTRACT_ITEM_SERIAL에서 조회
|
||||
-- 품목 정보: CONTRACT_ITEM에서 가져오기 (품목별로 펼쳐서 보이기)
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
CI.PART_OBJID,
|
||||
-- S/N: 해당 품목의 시리얼 번호만 표시
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM CI
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
COALESCE(PM.QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 요청납기: CONTRACT_ITEM 우선, 없으면 PROJECT_MGMT, 없으면 CONTRACT_MGMT
|
||||
COALESCE(
|
||||
(SELECT CI.DUE_DATE
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE' LIMIT 1),
|
||||
PM.DUE_DATE,
|
||||
CM.req_del_date
|
||||
) AS REQ_DEL_DATE,
|
||||
-- 수량: CONTRACT_ITEM의 수량
|
||||
COALESCE(CI.ORDER_QUANTITY::numeric, PM.QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 요청납기: CONTRACT_ITEM 우선
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.req_del_date) AS REQ_DEL_DATE,
|
||||
-- 고객요청사항: CONTRACT_ITEM에서 가져옴
|
||||
COALESCE(
|
||||
(SELECT CI.CUSTOMER_REQUEST
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE' LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_REQUEST,
|
||||
-- E-BOM 정보: PM.PART_OBJID가 E-BOM OBJID를 직접 가리킴
|
||||
PM.PART_OBJID AS BOM_REPORT_OBJID,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- E-BOM 정보: CI.PART_OBJID가 E-BOM OBJID를 가리킴
|
||||
COALESCE(CI.PART_OBJID, PM.PART_OBJID) AS BOM_REPORT_OBJID,
|
||||
COALESCE(
|
||||
(SELECT PBR.STATUS
|
||||
FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = PM.PART_OBJID
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID)
|
||||
LIMIT 1),
|
||||
''
|
||||
) AS EBOM_STATUS,
|
||||
COALESCE(
|
||||
(SELECT TO_CHAR(PBR.REGDATE, 'YYYY-MM-DD')
|
||||
FROM PART_BOM_REPORT PBR
|
||||
WHERE PBR.OBJID::VARCHAR = PM.PART_OBJID
|
||||
WHERE PBR.OBJID::VARCHAR = COALESCE(CI.PART_OBJID, PM.PART_OBJID)
|
||||
LIMIT 1),
|
||||
''
|
||||
) AS EBOM_REGDATE,
|
||||
@@ -2963,18 +2950,27 @@
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
-- CONTRACT_ITEM과 LEFT JOIN하여 품목별로 펼쳐서 보이기
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 품번 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
AND (
|
||||
UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
OR UPPER(CI.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 품명 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
AND (
|
||||
UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
OR UPPER(CI.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
)
|
||||
</if>
|
||||
ORDER BY PM.REGDATE DESC
|
||||
ORDER BY PM.REGDATE DESC, CI.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- E-BOM을 PROJECT_MGMT에 할당 -->
|
||||
@@ -3003,4 +2999,299 @@
|
||||
LEFT JOIN USER_INFO UI ON UI.USER_ID = T.WRITER
|
||||
WHERE T.OBJID::VARCHAR = #{objid}
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 상세 조회 (PROJECT_MGMT + CONTRACT_MGMT 정보) -->
|
||||
<select id="getProjectMgmtDetail" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PROJECT_NO,
|
||||
PM.BOM_REPORT_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
CM.CATEGORY_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
''
|
||||
) AS CATEGORY_NAME,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.AREA_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.AREA_CD LIMIT 1),
|
||||
''
|
||||
) AS AREA_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID = CM.CUSTOMER_OBJID::NUMERIC LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
CM.PAID_TYPE,
|
||||
CM.REQ_DEL_DATE,
|
||||
TO_CHAR(PM.REGDATE, 'YYYY-MM-DD') AS RECEIPT_DATE,
|
||||
TO_CHAR(PM.REGDATE, 'YYYY-MM-DD') AS MBOM_REGDATE
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
PM.OBJID::VARCHAR = #{objId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- E-BOM 목록 조회 -->
|
||||
<select id="getEbomList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
T.OBJID,
|
||||
T.PRODUCT_CD,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = T.PRODUCT_CD LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
T.PART_NO,
|
||||
T.PART_NAME,
|
||||
T.STATUS,
|
||||
T.REVISION,
|
||||
TO_CHAR(T.REGDATE, 'YYYY-MM-DD') AS REG_DATE,
|
||||
UI.USER_NAME AS WRITER_NAME,
|
||||
UI.DEPT_NAME,
|
||||
COALESCE(PM.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(PM.MAKER, '') AS SUPPLIER
|
||||
FROM
|
||||
PART_BOM_REPORT T
|
||||
LEFT JOIN USER_INFO UI ON UI.USER_ID = T.WRITER
|
||||
LEFT JOIN PART_MNG PM ON PM.PART_NO = T.PART_NO AND PM.STATUS = 'release'
|
||||
WHERE 1=1
|
||||
<!-- 품번, 품명이 비어있지 않은 것만 조회 -->
|
||||
AND T.PART_NO IS NOT NULL
|
||||
AND TRIM(T.PART_NO) != ''
|
||||
AND T.PART_NAME IS NOT NULL
|
||||
AND TRIM(T.PART_NAME) != ''
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(T.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
</if>
|
||||
<!-- 재료 검색 -->
|
||||
<if test="search_material != null and search_material != ''">
|
||||
AND UPPER(PM.MATERIAL) LIKE '%' || UPPER(#{search_material}) || '%'
|
||||
</if>
|
||||
<!-- 공급업체 검색 -->
|
||||
<if test="search_supplier != null and search_supplier != ''">
|
||||
AND UPPER(PM.MAKER) LIKE '%' || UPPER(#{search_supplier}) || '%'
|
||||
</if>
|
||||
ORDER BY T.REGDATE DESC
|
||||
LIMIT 100
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 목록 조회 -->
|
||||
<select id="getMbomList" resultType="map" parameterType="map">
|
||||
SELECT
|
||||
MH.OBJID,
|
||||
MH.MBOM_NO,
|
||||
MH.PART_NO,
|
||||
MH.PART_NAME,
|
||||
MH.SAVE_DATE,
|
||||
MH.CREATE_USER,
|
||||
MH.CREATE_DATE,
|
||||
MH.UPDATE_USER,
|
||||
MH.UPDATE_DATE
|
||||
FROM
|
||||
MBOM_HEADER MH
|
||||
WHERE 1=1
|
||||
<!-- 품번 검색 -->
|
||||
<if test="partNo != null and partNo != ''">
|
||||
AND UPPER(MH.PART_NO) LIKE '%' || UPPER(#{partNo}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="partName != null and partName != ''">
|
||||
AND UPPER(MH.PART_NAME) LIKE '%' || UPPER(#{partName}) || '%'
|
||||
</if>
|
||||
<!-- M-BOM 품번 검색 -->
|
||||
<if test="mbomPartNo != null and mbomPartNo != ''">
|
||||
AND UPPER(MH.MBOM_NO) LIKE '%' || UPPER(#{mbomPartNo}) || '%'
|
||||
</if>
|
||||
<!-- 저장일 검색 -->
|
||||
<if test="saveDate != null and saveDate != ''">
|
||||
AND DATE(MH.SAVE_DATE) = #{saveDate}
|
||||
</if>
|
||||
ORDER BY MH.SAVE_DATE DESC
|
||||
LIMIT 100
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 상세 데이터 조회 (프로젝트별) -->
|
||||
<select id="getMbomDetailByProject" resultType="map" parameterType="map">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.MBOM_HEADER_OBJID,
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
MD.QTY,
|
||||
MD.QTY_TEMP,
|
||||
MD.ITEM_QTY,
|
||||
MD.LEVEL,
|
||||
MD.REVISION,
|
||||
MD.SPEC,
|
||||
MD.PRODUCT_NAME,
|
||||
MD.STATUS_NAME,
|
||||
MD.LEVEL_1,
|
||||
MD.LEVEL_2,
|
||||
MD.LEVEL_3,
|
||||
MD.LEVEL_4,
|
||||
MD.LEVEL_5,
|
||||
MD.LEVEL_6,
|
||||
MD.LEVEL_7,
|
||||
MD.LEVEL_8,
|
||||
MD.LEVEL_9,
|
||||
MD.LEVEL_10
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
INNER JOIN
|
||||
MBOM_HEADER MH ON MD.MBOM_HEADER_OBJID = MH.OBJID
|
||||
WHERE
|
||||
MH.PROJECT_MGMT_OBJID = #{objId}
|
||||
ORDER BY
|
||||
MD.LEVEL, MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 헤더 저장 -->
|
||||
<insert id="insertMbomHeader" parameterType="map">
|
||||
<selectKey keyProperty="OBJID" resultType="string" order="BEFORE">
|
||||
SELECT REPLACE(UUID(),'-','') FROM DUAL
|
||||
</selectKey>
|
||||
INSERT INTO MBOM_HEADER (
|
||||
OBJID,
|
||||
MBOM_NO,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
SAVE_DATE,
|
||||
CREATE_USER,
|
||||
CREATE_DATE,
|
||||
UPDATE_USER,
|
||||
UPDATE_DATE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
CONCAT('MBOM-', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')),
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
NOW(),
|
||||
#{CREATE_USER},
|
||||
NOW(),
|
||||
#{UPDATE_USER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- M-BOM 상세 저장 -->
|
||||
<insert id="insertMbomDetail" parameterType="map">
|
||||
<selectKey keyProperty="OBJID" resultType="string" order="BEFORE">
|
||||
SELECT REPLACE(UUID(),'-','') FROM DUAL
|
||||
</selectKey>
|
||||
INSERT INTO MBOM_DETAIL (
|
||||
OBJID,
|
||||
MBOM_HEADER_OBJID,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
QTY,
|
||||
LEVEL,
|
||||
REVISION,
|
||||
SPEC,
|
||||
PRODUCT_NAME,
|
||||
STATUS_NAME,
|
||||
CREATE_USER,
|
||||
CREATE_DATE,
|
||||
UPDATE_USER,
|
||||
UPDATE_DATE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{MBOM_HEADER_OBJID},
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
#{QTY},
|
||||
#{LEVEL},
|
||||
#{REVISION},
|
||||
#{SPEC},
|
||||
#{PRODUCT_NAME},
|
||||
#{STATUS_NAME},
|
||||
#{CREATE_USER},
|
||||
NOW(),
|
||||
#{UPDATE_USER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- E-BOM을 M-BOM으로 복사 -->
|
||||
<insert id="saveMbomFromEbom" parameterType="map">
|
||||
/* productionplanning.saveMbomFromEbom - E-BOM을 M-BOM으로 복사 */
|
||||
/* 1. 새로운 PART_BOM_REPORT 생성 (M-BOM용) */
|
||||
WITH new_bom_report AS (
|
||||
INSERT INTO PART_BOM_REPORT (
|
||||
OBJID,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
STATUS
|
||||
) VALUES (
|
||||
(SELECT (FLOOR(RANDOM() * 1000000000) + 1000000000)::INTEGER),
|
||||
#{PART_NO},
|
||||
#{PART_NAME},
|
||||
#{USER_ID},
|
||||
NOW(),
|
||||
'Y'
|
||||
)
|
||||
RETURNING OBJID
|
||||
),
|
||||
/* 2. E-BOM의 BOM_PART_QTY 데이터를 새 M-BOM으로 복사 */
|
||||
copied_bom_data AS (
|
||||
INSERT INTO BOM_PART_QTY (
|
||||
BOM_REPORT_OBJID,
|
||||
OBJID,
|
||||
PARENT_OBJID,
|
||||
CHILD_OBJID,
|
||||
PARENT_PART_NO,
|
||||
PART_NO,
|
||||
QTY,
|
||||
ITEM_QTY,
|
||||
QTY_TEMP,
|
||||
REGDATE,
|
||||
WRITER,
|
||||
SEQ,
|
||||
STATUS,
|
||||
LAST_PART_OBJID
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM new_bom_report),
|
||||
(SELECT (FLOOR(RANDOM() * 1000000000) + 1000000000 + ROW_NUMBER() OVER (ORDER BY OBJID))::INTEGER),
|
||||
PARENT_OBJID,
|
||||
CHILD_OBJID,
|
||||
PARENT_PART_NO,
|
||||
PART_NO,
|
||||
QTY,
|
||||
ITEM_QTY,
|
||||
QTY_TEMP,
|
||||
NOW(),
|
||||
#{USER_ID},
|
||||
ROW_NUMBER() OVER (ORDER BY OBJID),
|
||||
'adding',
|
||||
LAST_PART_OBJID
|
||||
FROM BOM_PART_QTY
|
||||
WHERE BOM_REPORT_OBJID::VARCHAR = #{SOURCE_BOM_OBJID}
|
||||
AND COALESCE(STATUS, '') NOT IN ('deleting', 'deleted')
|
||||
RETURNING 1
|
||||
)
|
||||
/* 3. PROJECT_MGMT 업데이트 */
|
||||
UPDATE PROJECT_MGMT
|
||||
SET
|
||||
BOM_REPORT_OBJID = (SELECT OBJID FROM new_bom_report),
|
||||
MBOM_STATUS = 'Y',
|
||||
PART_NO = #{PART_NO},
|
||||
PART_NAME = #{PART_NAME}
|
||||
WHERE OBJID::VARCHAR = #{PROJECT_OBJID}
|
||||
</insert>
|
||||
</mapper>
|
||||
|
||||
@@ -269,7 +269,24 @@ public class ContractMgmtController {
|
||||
@ResponseBody
|
||||
@RequestMapping("/contractMgmt/contractGridList.do")
|
||||
public Map getProductKindSpecListPaging(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
commonService.selectListPagingNew("contractMgmt.contractGridList", request, paramMap);
|
||||
try {
|
||||
// 페이징 데이터 조회
|
||||
commonService.selectListPagingNew("contractMgmt.contractGridList", request, paramMap);
|
||||
|
||||
// 조회된 데이터의 전체 합계 조회
|
||||
Map<String, Object> totalAmount = (Map<String, Object>) commonService.selectOne("contractMgmt.getContractGridTotalAmount", request, paramMap);
|
||||
|
||||
// 합계 데이터 추가
|
||||
if(totalAmount != null) {
|
||||
paramMap.put("TOTAL_AMOUNT_KRW", totalAmount.get("totalAmountKRW"));
|
||||
} else {
|
||||
paramMap.put("TOTAL_AMOUNT_KRW", 0);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
paramMap.put("TOTAL_AMOUNT_KRW", 0);
|
||||
}
|
||||
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
@@ -2393,6 +2410,41 @@ public class ContractMgmtController {
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 주문서관리 - Total 합계 조회
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/contractMgmt/getOrderTotalAmount.do")
|
||||
public Map getOrderTotalAmount(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
// Total 합계 조회
|
||||
Map<String, Object> totalData = contractMgmtService.getOrderTotalAmount(request, paramMap);
|
||||
|
||||
if(totalData != null) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("totalSupplyPrice", totalData.get("TOTAL_SUPPLY_PRICE"));
|
||||
resultMap.put("totalVat", totalData.get("TOTAL_VAT"));
|
||||
resultMap.put("totalAmount", totalData.get("TOTAL_AMOUNT"));
|
||||
} else {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("totalSupplyPrice", 0);
|
||||
resultMap.put("totalVat", 0);
|
||||
resultMap.put("totalAmount", 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 수주등록 팝업 페이지
|
||||
* @param session
|
||||
|
||||
@@ -248,6 +248,7 @@ public class SalesNcollectMgmtController {
|
||||
@RequestMapping(value = "/salesMgmt/salesRegForm.do", method = RequestMethod.GET)
|
||||
public String showSalesRegForm(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
try {
|
||||
|
||||
// URL 인코딩 처리: 한글 프로젝트 번호 디코딩
|
||||
if(paramMap.get("orderNo") != null) {
|
||||
String orderNo = paramMap.get("orderNo").toString();
|
||||
@@ -280,43 +281,154 @@ public class SalesNcollectMgmtController {
|
||||
request.setAttribute("saleInfo", saleInfo);
|
||||
request.setAttribute("orderInfo", saleInfo);
|
||||
}
|
||||
// orderNo가 있으면 기존 판매 정보 조회
|
||||
// orderNo가 있으면 판매 정보 조회
|
||||
else if(paramMap.get("orderNo") != null && !paramMap.get("orderNo").equals("")) {
|
||||
saleInfo = salesNcollectMgmtService.getSaleInfo(paramMap);
|
||||
salesCurrency = CommonUtils.nullToEmpty((String)saleInfo.get("SALES_CURRENCY"));
|
||||
System.out.println("=== salesRegForm.do 파라미터 확인 ===");
|
||||
System.out.println("orderNo: " + paramMap.get("orderNo"));
|
||||
System.out.println("saleNo: " + paramMap.get("saleNo"));
|
||||
System.out.println("remainingQuantity: " + paramMap.get("remainingQuantity"));
|
||||
|
||||
// 판매 정보가 비어있거나 금액이 0이면 수주 데이터로 채우기
|
||||
if(saleInfo == null ||
|
||||
(saleInfo.get("SALES_SUPPLY_PRICE") == null ||
|
||||
"0".equals(String.valueOf(saleInfo.get("SALES_SUPPLY_PRICE"))) ||
|
||||
Integer.parseInt(String.valueOf(saleInfo.get("SALES_SUPPLY_PRICE"))) == 0)) {
|
||||
// orderNo로 contractObjId 조회 후 수주 데이터 가져오기
|
||||
Map<String, Object> orderDataParam = new HashMap<String, Object>();
|
||||
orderDataParam.put("orderNo", paramMap.get("orderNo"));
|
||||
Map<String, Object> orderData = salesNcollectMgmtService.getOrderDataByOrderNo(orderDataParam);
|
||||
|
||||
if(orderData != null && orderData.get("SALES_SUPPLY_PRICE") != null) {
|
||||
// 수주 데이터를 saleInfo에 병합 (기존 S/N 등은 유지)
|
||||
if(saleInfo == null) saleInfo = new HashMap<String, Object>();
|
||||
saleInfo.put("SALES_QUANTITY", orderData.get("SALES_QUANTITY"));
|
||||
saleInfo.put("SALES_UNIT_PRICE", orderData.get("SALES_UNIT_PRICE"));
|
||||
saleInfo.put("SALES_SUPPLY_PRICE", orderData.get("SALES_SUPPLY_PRICE"));
|
||||
saleInfo.put("SALES_VAT", orderData.get("SALES_VAT"));
|
||||
saleInfo.put("SALES_TOTAL_AMOUNT", orderData.get("SALES_TOTAL_AMOUNT"));
|
||||
saleInfo.put("SALES_CURRENCY", orderData.get("SALES_CURRENCY"));
|
||||
saleInfo.put("SALES_CURRENCY_NAME", orderData.get("SALES_CURRENCY_NAME"));
|
||||
saleInfo.put("SALES_EXCHANGE_RATE", orderData.get("SALES_EXCHANGE_RATE"));
|
||||
if(saleInfo.get("SHIPPING_DATE") == null || "".equals(saleInfo.get("SHIPPING_DATE"))) {
|
||||
saleInfo.put("SHIPPING_DATE", orderData.get("SHIPPING_DATE"));
|
||||
}
|
||||
salesCurrency = CommonUtils.nullToEmpty((String)orderData.get("SALES_CURRENCY"));
|
||||
}
|
||||
// saleNo가 "detail"이면 주문서 관리의 결재 정보 조회 모드
|
||||
if(paramMap.get("saleNo") != null && "detail".equals(paramMap.get("saleNo"))) {
|
||||
System.out.println("=== 주문서 관리 결재 정보 조회 모드 ===");
|
||||
|
||||
// PROJECT_MGMT에서 CONTRACT_OBJID 조회
|
||||
Map<String, Object> projectInfo = salesNcollectMgmtService.getProjectInfo(paramMap);
|
||||
Object contractObjId = projectInfo != null ? projectInfo.get("contract_objid") : null;
|
||||
if(contractObjId == null && projectInfo != null) {
|
||||
contractObjId = projectInfo.get("CONTRACT_OBJID");
|
||||
}
|
||||
|
||||
request.setAttribute("saleInfo", saleInfo);
|
||||
System.out.println("CONTRACT_OBJID: " + contractObjId);
|
||||
|
||||
// orderInfo로 견적 정보 전달 (saleInfo가 이미 모든 필요한 정보를 포함)
|
||||
request.setAttribute("orderInfo", saleInfo);
|
||||
if(contractObjId != null) {
|
||||
// CONTRACT_MGMT 상세 정보 조회
|
||||
Map<String, Object> contractParam = new HashMap<String, Object>();
|
||||
contractParam.put("objId", contractObjId);
|
||||
Map<String, Object> contractInfo = commonService.selectOne("contractMgmt.getContractInfo", request, contractParam);
|
||||
|
||||
// PROJECT_MGMT에서 품번/품명/S/N/요청납기/고객요청사항/반납사유 조회
|
||||
if(projectInfo != null) {
|
||||
// 품번
|
||||
if(contractInfo.get("PART_NO") == null || "".equals(contractInfo.get("PART_NO"))) {
|
||||
contractInfo.put("PART_NO", projectInfo.get("part_no") != null ? projectInfo.get("part_no") : projectInfo.get("PART_NO"));
|
||||
}
|
||||
// 품명
|
||||
if(contractInfo.get("PART_NAME") == null || "".equals(contractInfo.get("PART_NAME"))) {
|
||||
contractInfo.put("PART_NAME", projectInfo.get("part_name") != null ? projectInfo.get("part_name") : projectInfo.get("PART_NAME"));
|
||||
}
|
||||
// S/N
|
||||
Object serialNo = projectInfo.get("serial_no") != null ? projectInfo.get("serial_no") : projectInfo.get("SERIAL_NO");
|
||||
contractInfo.put("SERIAL_NO", serialNo != null ? serialNo : "-");
|
||||
|
||||
// 요청납기
|
||||
Object reqDelDate = projectInfo.get("req_del_date") != null ? projectInfo.get("req_del_date") : projectInfo.get("REQ_DEL_DATE");
|
||||
contractInfo.put("REQ_DEL_DATE", reqDelDate != null ? reqDelDate : "-");
|
||||
|
||||
// 고객요청사항
|
||||
Object customerRequest = projectInfo.get("customer_request") != null ? projectInfo.get("customer_request") : projectInfo.get("CUSTOMER_REQUEST");
|
||||
contractInfo.put("CUSTOMER_REQUEST", customerRequest != null ? customerRequest : "-");
|
||||
|
||||
// 반납사유
|
||||
Object returnReason = projectInfo.get("return_reason") != null ? projectInfo.get("return_reason") : projectInfo.get("RETURN_REASON");
|
||||
contractInfo.put("RETURN_REASON", returnReason != null ? returnReason : "-");
|
||||
}
|
||||
|
||||
// 결재 라인 정보 조회
|
||||
Map<String, Object> approvalParam = new HashMap<String, Object>();
|
||||
approvalParam.put("objId", contractObjId);
|
||||
List<Map<String, Object>> approvalLine = commonService.selectList("approval.getApprovalLine", request, approvalParam);
|
||||
|
||||
request.setAttribute("info", contractInfo);
|
||||
request.setAttribute("approvalLine", approvalLine);
|
||||
|
||||
System.out.println("=== 주문서 관리 데이터 조회 완료 ===");
|
||||
System.out.println("CATEGORY_NAME: " + contractInfo.get("CATEGORY_NAME"));
|
||||
System.out.println("PRODUCT_NAME: " + contractInfo.get("PRODUCT_NAME"));
|
||||
System.out.println("PART_NO: " + contractInfo.get("PART_NO"));
|
||||
System.out.println("PART_NAME: " + contractInfo.get("PART_NAME"));
|
||||
System.out.println("결재 라인 개수: " + (approvalLine != null ? approvalLine.size() : 0));
|
||||
|
||||
// 별도의 JSP로 이동
|
||||
return "/salesmgmt/salesMgmt/projectDetailView";
|
||||
}
|
||||
}
|
||||
// saleNo가 있지만 "detail"이 아니면 프로젝트 기본 정보 조회 모드
|
||||
else if(paramMap.get("saleNo") != null && !paramMap.get("saleNo").equals("")) {
|
||||
System.out.println("=== 프로젝트 기본 정보 조회 모드 ===");
|
||||
Map<String, Object> orderDataParam = new HashMap<String, Object>();
|
||||
orderDataParam.put("orderNo", paramMap.get("orderNo"));
|
||||
saleInfo = salesNcollectMgmtService.getOrderDataByOrderNo(orderDataParam);
|
||||
|
||||
if(saleInfo != null) {
|
||||
salesCurrency = CommonUtils.nullToEmpty((String)saleInfo.get("SALES_CURRENCY"));
|
||||
saleInfo.put("ORDER_QUANTITY", saleInfo.get("SALES_QUANTITY"));
|
||||
|
||||
Map<String, Object> shipmentParam = new HashMap<String, Object>();
|
||||
shipmentParam.put("projectNo", paramMap.get("orderNo"));
|
||||
Integer totalShipped = salesNcollectMgmtService.getTotalShippedQuantity(shipmentParam);
|
||||
saleInfo.put("SALES_QUANTITY", totalShipped != null ? totalShipped : 0);
|
||||
|
||||
System.out.println("=== 프로젝트 기본 정보 조회 완료 ===");
|
||||
System.out.println("ORDER_QUANTITY (수주수량): " + saleInfo.get("ORDER_QUANTITY"));
|
||||
System.out.println("SALES_QUANTITY (총 판매수량): " + saleInfo.get("SALES_QUANTITY"));
|
||||
}
|
||||
}
|
||||
// saleNo가 없으면 신규 판매 등록 모드 -> 수주 데이터만 조회
|
||||
else {
|
||||
System.out.println("=== 신규 판매 등록 모드 ===");
|
||||
Map<String, Object> orderDataParam = new HashMap<String, Object>();
|
||||
orderDataParam.put("orderNo", paramMap.get("orderNo"));
|
||||
saleInfo = salesNcollectMgmtService.getOrderDataByOrderNo(orderDataParam);
|
||||
|
||||
if(saleInfo != null) {
|
||||
salesCurrency = CommonUtils.nullToEmpty((String)saleInfo.get("SALES_CURRENCY"));
|
||||
// 수주 데이터의 SALES_QUANTITY를 ORDER_QUANTITY로 변경
|
||||
saleInfo.put("ORDER_QUANTITY", saleInfo.get("SALES_QUANTITY"));
|
||||
saleInfo.put("SALES_QUANTITY", ""); // 신규 등록이므로 판매수량은 비워둠
|
||||
|
||||
System.out.println("=== 수주 데이터 조회 완료 ===");
|
||||
System.out.println("ORDER_QUANTITY: " + saleInfo.get("ORDER_QUANTITY"));
|
||||
System.out.println("SALES_QUANTITY: " + saleInfo.get("SALES_QUANTITY"));
|
||||
System.out.println("SALES_UNIT_PRICE: " + saleInfo.get("SALES_UNIT_PRICE"));
|
||||
System.out.println("SALES_SUPPLY_PRICE: " + saleInfo.get("SALES_SUPPLY_PRICE"));
|
||||
}
|
||||
}
|
||||
|
||||
// 신규 등록 모드에서는 이미 수주 데이터를 조회했으므로 추가 처리 불필요
|
||||
|
||||
// 잔량은 그리드에서 이미 계산되어 있으므로 별도 계산 불필요
|
||||
// URL 파라미터로 잔량이 전달된 경우 사용
|
||||
if(paramMap.get("remainingQuantity") != null && !paramMap.get("remainingQuantity").equals("")) {
|
||||
if(saleInfo == null) saleInfo = new HashMap<String, Object>();
|
||||
saleInfo.put("REMAINING_QUANTITY", paramMap.get("remainingQuantity"));
|
||||
System.out.println("=== 그리드에서 전달받은 잔량 ===");
|
||||
System.out.println("잔량 (REMAINING_QUANTITY): " + saleInfo.get("REMAINING_QUANTITY"));
|
||||
}
|
||||
|
||||
// 판매수량은 기존 값 유지 (이미 판매 등록된 경우) 또는 비워둠 (신규 등록)
|
||||
if(saleInfo != null) {
|
||||
if(saleInfo.get("SALES_QUANTITY") == null || saleInfo.get("SALES_QUANTITY").equals(0)) {
|
||||
saleInfo.put("SALES_QUANTITY", ""); // 신규 등록: 비워둠
|
||||
}
|
||||
System.out.println("판매수량 (SALES_QUANTITY): " + saleInfo.get("SALES_QUANTITY"));
|
||||
}
|
||||
|
||||
// 프로젝트의 모든 품목 조회 (Phase 2) - 주석처리: 품목은 하나만 존재
|
||||
/*
|
||||
List<Map<String, Object>> projectItems = null;
|
||||
if(paramMap.get("orderNo") != null && !paramMap.get("orderNo").equals("")) {
|
||||
projectItems = salesNcollectMgmtService.getProjectItems(paramMap);
|
||||
System.out.println("=== 프로젝트 품목 조회 ===");
|
||||
System.out.println("품목 개수: " + (projectItems != null ? projectItems.size() : 0));
|
||||
request.setAttribute("projectItems", projectItems);
|
||||
}
|
||||
*/
|
||||
|
||||
request.setAttribute("saleInfo", saleInfo);
|
||||
|
||||
// orderInfo로 견적 정보 전달 (saleInfo가 이미 모든 필요한 정보를 포함)
|
||||
request.setAttribute("orderInfo", saleInfo);
|
||||
}
|
||||
|
||||
// 환종(통화) - 공통코드 0001533
|
||||
@@ -418,6 +530,96 @@ public class SalesNcollectMgmtController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 출하일 상세 내역 팝업
|
||||
* </pre>
|
||||
* @param request
|
||||
* @param paramMap - projectNo
|
||||
* @return String
|
||||
*/
|
||||
@RequestMapping(value = "/salesMgmt/shippingDetailPopup.do", method = RequestMethod.GET)
|
||||
public String showShippingDetailPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
try {
|
||||
String projectNo = (String) paramMap.get("projectNo");
|
||||
List<Map<String, Object>> shippingList = salesNcollectMgmtService.getShippingDetailList(projectNo);
|
||||
request.setAttribute("shippingList", shippingList);
|
||||
request.setAttribute("projectNo", projectNo);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/salesmgmt/salesMgmt/shippingDetailPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래명세서 폼 표시
|
||||
*/
|
||||
@RequestMapping(value = "/salesMgmt/transactionStatementForm.do", method = RequestMethod.GET)
|
||||
public String showTransactionStatementForm(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/salesmgmt/salesMgmt/transactionStatementForm";
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래명세서 데이터 조회
|
||||
*/
|
||||
@RequestMapping(value = "/salesMgmt/getTransactionStatementData.do", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Map<String, Object> getTransactionStatementData(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
String projectNos = (String) paramMap.get("projectNos");
|
||||
|
||||
if(projectNos == null || projectNos.isEmpty()) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "프로젝트 번호가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 거래명세서 데이터 조회
|
||||
Map<String, Object> statementData = salesNcollectMgmtService.getTransactionStatementData(paramMap);
|
||||
|
||||
resultMap.put("success", true);
|
||||
resultMap.putAll(statementData);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "데이터 조회 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래명세서 저장 (차수 관리 없음)
|
||||
*/
|
||||
@RequestMapping(value = "/salesMgmt/saveTransactionStatement.do", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Map<String, Object> saveTransactionStatement(HttpServletRequest request, @org.springframework.web.bind.annotation.RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
System.out.println("=== 거래명세서 저장 Controller ===");
|
||||
System.out.println("프로젝트 번호: " + paramMap.get("projectNos"));
|
||||
System.out.println("납품일: " + paramMap.get("deliveryDate"));
|
||||
System.out.println("비고: " + paramMap.get("noteContent"));
|
||||
System.out.println("품목 개수: " + ((List)paramMap.get("items")).size());
|
||||
|
||||
// Service 호출하여 DB에 저장
|
||||
resultMap = salesNcollectMgmtService.saveTransactionStatement(paramMap);
|
||||
|
||||
System.out.println("저장 결과: " + resultMap.get("success"));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "저장 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 계약관리 목록 조회
|
||||
@@ -798,4 +1000,40 @@ public class SalesNcollectMgmtController {
|
||||
Map resultMap = salesNcollectMgmtService.salesDeadlineConfirm(request, paramMap);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/salesMgmt/getAllSerialNumbers.do", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Map<String, Object> getAllSerialNumbers(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
List<String> serialNumbers = salesNcollectMgmtService.getAllSerialNumbers(paramMap);
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("serialNumbers", serialNumbers);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/salesMgmt/getSavedTransactionStatement.do", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public Map<String, Object> getSavedTransactionStatement(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
List<Map<String, Object>> savedData = salesNcollectMgmtService.getSavedTransactionStatement(paramMap);
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("data", savedData);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,13 +523,20 @@
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
,(SELECT objid FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID order by regdate desc limit 1) AS EST_OBJID
|
||||
-- 최근 차수 견적서 합계 정보
|
||||
,(SELECT TOTAL_AMOUNT FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT
|
||||
,(SELECT TOTAL_AMOUNT_KRW FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT_KRW
|
||||
-- 수주 합계 정보 (CONTRACT_MGMT 테이블에 저장된 값 사용)
|
||||
,T.ORDER_SUPPLY_PRICE AS ORDER_SUPPLY_PRICE_SUM
|
||||
,T.ORDER_VAT AS ORDER_VAT_SUM
|
||||
,T.ORDER_TOTAL_AMOUNT AS ORDER_TOTAL_AMOUNT_SUM
|
||||
-- 최근 차수 견적서 합계 정보
|
||||
,(SELECT TOTAL_AMOUNT FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT
|
||||
,(SELECT TOTAL_AMOUNT_KRW FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT_KRW
|
||||
-- 견적수량 (ESTIMATE_TEMPLATE_ITEM의 수량 합계)
|
||||
,(SELECT COALESCE(SUM(CAST(QUANTITY AS NUMERIC)), 0) FROM ESTIMATE_TEMPLATE_ITEM WHERE TEMPLATE_OBJID = (SELECT objid FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1)) AS ESTIMATE_QUANTITY
|
||||
-- 수주 합계 정보 (CONTRACT_MGMT 테이블에 저장된 값 사용)
|
||||
,T.ORDER_SUPPLY_PRICE AS ORDER_SUPPLY_PRICE_SUM
|
||||
,T.ORDER_VAT AS ORDER_VAT_SUM
|
||||
,T.ORDER_TOTAL_AMOUNT AS ORDER_TOTAL_AMOUNT_SUM
|
||||
-- 수주수량 (CONTRACT_MGMT의 QUANTITY 또는 CONTRACT_ITEM 합계)
|
||||
,COALESCE(
|
||||
NULLIF(T.QUANTITY, '')::NUMERIC,
|
||||
(SELECT COALESCE(SUM(CAST(QUANTITY AS NUMERIC)), 0) FROM CONTRACT_ITEM WHERE CONTRACT_OBJID = T.OBJID AND STATUS = 'ACTIVE')
|
||||
) AS ORDER_QUANTITY
|
||||
,CASE
|
||||
WHEN T.ORDER_TOTAL_AMOUNT IS NOT NULL AND T.ORDER_TOTAL_AMOUNT != ''
|
||||
AND T.EXCHANGE_RATE IS NOT NULL AND T.EXCHANGE_RATE != ''
|
||||
@@ -790,6 +797,102 @@
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 주문서관리 Total 합계 조회 (조회된 데이터 전체 합계) -->
|
||||
<select id="getContractGridTotalAmount" parameterType="map" resultType="map">
|
||||
/* contractMgmt.getContractGridTotalAmount */
|
||||
SELECT
|
||||
COALESCE(SUM(COALESCE(T.ORDER_TOTAL_AMOUNT_KRW, 0)), 0) AS "totalAmountKRW"
|
||||
FROM
|
||||
<include refid="contractBase"/> T
|
||||
WHERE 1=1
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND SUBSTR(CONTRACT_DATE,0,5) = #{Year}
|
||||
</if>
|
||||
|
||||
<if test="category_cd !=null and category_cd != '' ">
|
||||
AND category_cd = #{category_cd}
|
||||
</if>
|
||||
|
||||
<if test="customer_objid !=null and customer_objid != '' ">
|
||||
AND customer_objid = #{customer_objid}
|
||||
</if>
|
||||
|
||||
<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_result !=null and contract_result !=''">
|
||||
AND contract_result = #{contract_result}
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
AND pm_user_id = #{pm_user_id}
|
||||
</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 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>
|
||||
|
||||
<!-- 품번/품명 검색: PART_OBJID로 정확하게 검색 -->
|
||||
<if test="search_partObjId != null and search_partObjId != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = T.OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND CI.PART_OBJID = #{search_partObjId}
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_poNo != null and search_poNo != ''">
|
||||
AND UPPER(PO_NO) LIKE UPPER('%${search_poNo}%')
|
||||
</if>
|
||||
|
||||
<if test="order_start_date != null and !''.equals(order_start_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{order_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="order_end_date != null and !''.equals(order_end_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{order_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(DUE_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>
|
||||
</select>
|
||||
|
||||
<select id="contractList_bak" parameterType="map" resultType="map">
|
||||
SELECT *
|
||||
FROM (
|
||||
@@ -4481,6 +4584,103 @@ WHERE
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 주문서관리 Total 합계 조회 -->
|
||||
<select id="getOrderTotalAmount" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
COALESCE(SUM(COALESCE(T.ORDER_SUPPLY_PRICE_SUM, 0)), 0) AS TOTAL_SUPPLY_PRICE,
|
||||
COALESCE(SUM(COALESCE(T.ORDER_VAT_SUM, 0)), 0) AS TOTAL_VAT,
|
||||
COALESCE(SUM(COALESCE(T.ORDER_TOTAL_AMOUNT_SUM, 0)), 0) AS TOTAL_AMOUNT
|
||||
FROM
|
||||
<include refid="contractBase"/> T
|
||||
WHERE 1=1
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND SUBSTR(CONTRACT_DATE,0,5) = #{Year}
|
||||
</if>
|
||||
|
||||
<if test="category_cd !=null and category_cd != '' ">
|
||||
AND category_cd = #{category_cd}
|
||||
</if>
|
||||
|
||||
<if test="customer_objid !=null and customer_objid != '' ">
|
||||
AND customer_objid = #{customer_objid}
|
||||
</if>
|
||||
|
||||
<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_result !=null and contract_result !=''">
|
||||
AND contract_result = #{contract_result}
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
AND pm_user_id = #{pm_user_id}
|
||||
</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 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>
|
||||
|
||||
<!-- 품번/품명 검색: PART_OBJID로 정확하게 검색 -->
|
||||
<if test="search_partObjId != null and search_partObjId != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = T.OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND CI.PART_OBJID = #{search_partObjId}
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
AND UPPER(SERIAL_NO) LIKE UPPER('%${search_serialNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_poNo != null and search_poNo != ''">
|
||||
AND UPPER(PO_NO) LIKE UPPER('%${search_poNo}%')
|
||||
</if>
|
||||
|
||||
<if test="order_start_date != null and !''.equals(order_start_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{order_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="order_end_date != null and !''.equals(order_end_date)">
|
||||
AND TO_DATE(ORDER_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{order_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="due_start_date != null and !''.equals(due_start_date)">
|
||||
AND TO_DATE(DUE_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>
|
||||
</select>
|
||||
|
||||
<!-- 영업정보 조회 (수주등록용) -->
|
||||
<select id="getContractInfo" parameterType="map" resultType="map">
|
||||
@@ -4488,6 +4688,24 @@ WHERE
|
||||
OBJID,
|
||||
CONTRACT_NO,
|
||||
CUSTOMER_OBJID,
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID = CONTRACT_MGMT.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME,
|
||||
-- 주문유형
|
||||
CATEGORY_CD,
|
||||
CODE_NAME(CATEGORY_CD) AS CATEGORY_NAME,
|
||||
-- 제품구분
|
||||
PRODUCT,
|
||||
CODE_NAME(PRODUCT) AS PRODUCT_NAME,
|
||||
-- 국내/해외
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
-- 유/무상
|
||||
PAID_TYPE,
|
||||
-- 접수일 (이미 날짜 형식이면 그대로, YYYYMMDD 형식이면 변환)
|
||||
CASE
|
||||
WHEN RECEIPT_DATE ~ '^\d{8}$' THEN TO_CHAR(TO_DATE(RECEIPT_DATE, 'YYYYMMDD'), 'YYYY-MM-DD')
|
||||
ELSE RECEIPT_DATE
|
||||
END AS RECEIPT_DATE,
|
||||
-- 환종/환율
|
||||
CONTRACT_CURRENCY,
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
EXCHANGE_RATE,
|
||||
|
||||
@@ -876,16 +876,32 @@
|
||||
(SELECT CM.PRODUCTION_STATUS FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PRODUCTION_STATUS,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 한 번에 가져오기)
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
-- 판매수량: 모든 분할 출하의 합계
|
||||
COALESCE(
|
||||
(SELECT SUM(sales_quantity)
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE T.PROJECT_NO || '%'),
|
||||
0
|
||||
) AS SALES_QUANTITY,
|
||||
COALESCE(SR.sales_unit_price, 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SR.sales_supply_price, 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SR.sales_vat, 0) AS SALES_VAT,
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT,
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT_KRW,
|
||||
-- 잔량 계산: 수주수량 - 판매수량
|
||||
COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0) AS REMAINING_QUANTITY,
|
||||
-- 잔량원화총액 계산: (수주수량 - 판매수량) * 판매단가
|
||||
(COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0)) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW,
|
||||
-- 잔량 계산: 수주수량 - shipment_log의 split_quantity 합계
|
||||
COALESCE(T.QUANTITY::numeric, 0) - COALESCE(
|
||||
(SELECT SUM(COALESCE(split_quantity, 0))
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.PROJECT_NO),
|
||||
0
|
||||
) AS REMAINING_QUANTITY,
|
||||
-- 잔량원화총액 계산: (수주수량 - shipment_log 합계) * 판매단가
|
||||
(COALESCE(T.QUANTITY::numeric, 0) - COALESCE(
|
||||
(SELECT SUM(COALESCE(split_quantity, 0))
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.PROJECT_NO),
|
||||
0
|
||||
)) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW,
|
||||
COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY) AS SALES_CURRENCY,
|
||||
CODE_NAME(COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY)) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(SR.sales_exchange_rate, T.CONTRACT_PRICE_CURRENCY::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
@@ -896,10 +912,10 @@
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT shipping_date) = 0 THEN ''
|
||||
WHEN COUNT(DISTINCT shipping_date) = 1 THEN TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD')
|
||||
ELSE TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD') || '외' || (COUNT(DISTINCT shipping_date) - 1)::TEXT
|
||||
ELSE TO_CHAR(MIN(shipping_date), 'YYYY-MM-DD') || ' 외 ' || (COUNT(DISTINCT shipping_date) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM shipment_log
|
||||
WHERE target_objid = T.OBJID::VARCHAR
|
||||
WHERE target_objid = T.PROJECT_NO
|
||||
AND shipping_date IS NOT NULL
|
||||
AND UPPER(COALESCE(shipping_status, '')) != 'CANCELLED'),
|
||||
COALESCE(TO_CHAR(SR.shipping_date, 'YYYY-MM-DD'), '')
|
||||
@@ -911,12 +927,17 @@
|
||||
) AS MANAGER,
|
||||
COALESCE(SR.incoterms, '') AS INCOTERMS,
|
||||
T.SALES_STATUS,
|
||||
T.OBJID::VARCHAR AS SALE_NO,
|
||||
'ORIGINAL' AS RECORD_TYPE,
|
||||
'' AS SPLIT_LOG_ID
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
WHERE 1 = 1
|
||||
T.OBJID::VARCHAR AS SALE_NO,
|
||||
'ORIGINAL' AS RECORD_TYPE,
|
||||
'' AS SPLIT_LOG_ID,
|
||||
-- 거래명세서 존재 여부
|
||||
CASE WHEN EXISTS(
|
||||
SELECT 1 FROM NSWOS100_TBL
|
||||
WHERE OdOrderNo = T.PROJECT_NO
|
||||
) THEN 'Y' ELSE 'N' END AS HAS_TRANSACTION_STATEMENT
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
WHERE 1 = 1
|
||||
AND T.PROJECT_NO IS NOT NULL
|
||||
AND T.PROJECT_NO != ''
|
||||
<if test="orderType != null and orderType != ''">
|
||||
@@ -1398,29 +1419,12 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
NULL,
|
||||
</otherwise>
|
||||
</choose>
|
||||
#{shippingMethod},
|
||||
#{manager},
|
||||
#{incoterms},
|
||||
#{cretEmpNo}
|
||||
)
|
||||
ON CONFLICT (project_no)
|
||||
DO UPDATE SET
|
||||
shipping_order_status = EXCLUDED.shipping_order_status,
|
||||
serial_no = EXCLUDED.serial_no,
|
||||
sales_quantity = EXCLUDED.sales_quantity,
|
||||
sales_unit_price = EXCLUDED.sales_unit_price,
|
||||
sales_supply_price = EXCLUDED.sales_supply_price,
|
||||
sales_vat = EXCLUDED.sales_vat,
|
||||
sales_total_amount = EXCLUDED.sales_total_amount,
|
||||
sales_currency = EXCLUDED.sales_currency,
|
||||
sales_exchange_rate = EXCLUDED.sales_exchange_rate,
|
||||
shipping_date = EXCLUDED.shipping_date,
|
||||
shipping_method = EXCLUDED.shipping_method,
|
||||
manager_user_id = EXCLUDED.manager_user_id,
|
||||
incoterms = EXCLUDED.incoterms,
|
||||
upd_date = NOW(),
|
||||
upd_user_id = EXCLUDED.reg_user_id
|
||||
</insert>
|
||||
#{shippingMethod},
|
||||
#{manager},
|
||||
#{incoterms},
|
||||
#{cretEmpNo}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!--
|
||||
/**
|
||||
@@ -1489,9 +1493,15 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
AND UPPER(STATUS) = 'ACTIVE'
|
||||
) THEN 'Y' ELSE 'N' END AS ORDER_ATTACH,
|
||||
(SELECT CM.PRODUCTION_STATUS FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PRODUCTION_STATUS,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 가져오기)
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
-- 판매 관련 필드들 (sales_registration 테이블에서 가져오기)
|
||||
SR.sale_no AS SALE_NO,
|
||||
COALESCE(SR.shipping_order_status, '') AS SHIPPING_ORDER_STATUS,
|
||||
|
||||
-- 주문수량 (PROJECT_MGMT에서 가져오기) - 잔량 계산용
|
||||
COALESCE(T.QUANTITY::NUMERIC, 0) AS ORDER_QUANTITY,
|
||||
|
||||
-- 판매수량 (sales_registration에서 가져오기) - 이미 판매한 수량
|
||||
COALESCE(SR.sales_quantity, 0) AS SALES_QUANTITY,
|
||||
COALESCE(SR.sales_unit_price, 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SR.sales_supply_price, 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SR.sales_vat, 0) AS SALES_VAT,
|
||||
@@ -1499,13 +1509,16 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT_KRW,
|
||||
COALESCE(NULLIF(SR.sales_currency, ''), CM.CONTRACT_CURRENCY) AS SALES_CURRENCY,
|
||||
CODE_NAME(COALESCE(NULLIF(SR.sales_currency, ''), CM.CONTRACT_CURRENCY)) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(NULLIF(SR.sales_exchange_rate, 0), CM.EXCHANGE_RATE::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
COALESCE(NULLIF(SR.sales_exchange_rate, 0), NULLIF(CM.EXCHANGE_RATE, '')::numeric, 0) AS SALES_EXCHANGE_RATE,
|
||||
COALESCE(TO_CHAR(SR.shipping_date, 'YYYY-MM-DD'), '') AS SHIPPING_DATE,
|
||||
COALESCE(SR.shipping_method, '') AS SHIPPING_METHOD,
|
||||
COALESCE(SR.manager_user_id, T.PM_USER_ID) AS MANAGER,
|
||||
COALESCE(SR.incoterms, '') AS INCOTERMS
|
||||
FROM PROJECT_MGMT AS T
|
||||
LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no
|
||||
<if test="saleNo != null and saleNo != ''">
|
||||
AND SR.sale_no = #{saleNo}::integer
|
||||
</if>
|
||||
LEFT JOIN CONTRACT_MGMT CM ON CM.OBJID::VARCHAR = T.CONTRACT_OBJID
|
||||
WHERE T.PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
@@ -1567,40 +1580,43 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
-->
|
||||
<select id="getOrderDataByOrderNo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getOrderDataByOrderNo - orderNo로 판매등록용 수주 데이터 조회 */
|
||||
SELECT
|
||||
-- 기본 정보
|
||||
CM.CONTRACT_NO AS ORDER_NO,
|
||||
CM.OBJID AS CONTRACT_OBJID,
|
||||
|
||||
-- 수주 금액 정보 (CONTRACT_ITEM 테이블에서 합산) - VARCHAR 타입이므로 NUMERIC으로 캐스팅
|
||||
COALESCE(SUM(CI.ORDER_QUANTITY::NUMERIC), 0) AS SALES_QUANTITY,
|
||||
COALESCE(ROUND(AVG(CI.ORDER_UNIT_PRICE::NUMERIC), 2), 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SUM(CI.ORDER_SUPPLY_PRICE::NUMERIC), 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SUM(CI.ORDER_VAT::NUMERIC), 0) AS SALES_VAT,
|
||||
COALESCE(SUM(CI.ORDER_TOTAL_AMOUNT::NUMERIC), 0) AS SALES_TOTAL_AMOUNT,
|
||||
|
||||
-- 환종 정보
|
||||
CM.CONTRACT_CURRENCY AS SALES_CURRENCY,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(CM.EXCHANGE_RATE::NUMERIC, 0) AS SALES_EXCHANGE_RATE,
|
||||
|
||||
-- 수주 날짜 - VARCHAR 타입이므로 그대로 사용
|
||||
CM.ORDER_DATE AS SHIPPING_DATE,
|
||||
|
||||
-- 담당자
|
||||
CM.PM_USER_ID AS MANAGER
|
||||
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID AND UPPER(CI.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
GROUP BY
|
||||
CM.CONTRACT_NO,
|
||||
CM.OBJID,
|
||||
CM.CONTRACT_CURRENCY,
|
||||
CM.EXCHANGE_RATE,
|
||||
CM.ORDER_DATE,
|
||||
CM.PM_USER_ID
|
||||
SELECT
|
||||
-- 기본 정보
|
||||
CM.CONTRACT_NO AS ORDER_NO,
|
||||
CM.OBJID AS CONTRACT_OBJID,
|
||||
|
||||
-- 수주 수량 정보 (PROJECT_MGMT에서 직접 가져오기)
|
||||
COALESCE(PM.QUANTITY::NUMERIC, 0) AS SALES_QUANTITY,
|
||||
|
||||
-- 수주 금액 정보 (CONTRACT_ITEM 테이블에서 합산) - VARCHAR 타입이므로 NULLIF로 빈 문자열 제거 후 NUMERIC 캐스팅
|
||||
COALESCE(ROUND(AVG(NULLIF(CI.ORDER_UNIT_PRICE, '')::NUMERIC), 2), 0) AS SALES_UNIT_PRICE,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_SUPPLY_PRICE, '')::NUMERIC), 0) AS SALES_SUPPLY_PRICE,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_VAT, '')::NUMERIC), 0) AS SALES_VAT,
|
||||
COALESCE(SUM(NULLIF(CI.ORDER_TOTAL_AMOUNT, '')::NUMERIC), 0) AS SALES_TOTAL_AMOUNT,
|
||||
|
||||
-- 환종 정보
|
||||
CM.CONTRACT_CURRENCY AS SALES_CURRENCY,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME,
|
||||
COALESCE(NULLIF(CM.EXCHANGE_RATE, '')::NUMERIC, 0) AS SALES_EXCHANGE_RATE,
|
||||
|
||||
-- 수주 날짜 - VARCHAR 타입이므로 그대로 사용
|
||||
CM.ORDER_DATE AS SHIPPING_DATE,
|
||||
|
||||
-- 담당자
|
||||
CM.PM_USER_ID AS MANAGER
|
||||
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID AND UPPER(CI.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
GROUP BY
|
||||
CM.CONTRACT_NO,
|
||||
CM.OBJID,
|
||||
CM.CONTRACT_CURRENCY,
|
||||
CM.EXCHANGE_RATE,
|
||||
CM.ORDER_DATE,
|
||||
CM.PM_USER_ID,
|
||||
PM.QUANTITY
|
||||
</select>
|
||||
|
||||
<!--
|
||||
@@ -1620,5 +1636,342 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 모든 분할 출하의 총 판매 수량 조회 -->
|
||||
<select id="getTotalSalesQuantity" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getTotalSalesQuantity - project_no로 시작하는 모든 레코드의 판매 수량 합계 */
|
||||
SELECT COALESCE(SUM(
|
||||
CASE
|
||||
WHEN sales_quantity IS NULL THEN 0
|
||||
WHEN TRIM(CAST(sales_quantity AS TEXT)) = '' THEN 0
|
||||
ELSE CAST(sales_quantity AS NUMERIC)
|
||||
END
|
||||
), 0) as total
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE #{orderNo} || '%'
|
||||
</select>
|
||||
|
||||
<!-- shipment_log에서 총 출하 수량 조회 -->
|
||||
<select id="getTotalShippedQuantity" parameterType="map" resultType="int">
|
||||
/* salesNcollectMgmt.getTotalShippedQuantity - shipment_log의 split_quantity 합계 */
|
||||
SELECT COALESCE(SUM(split_quantity), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 기본 정보 조회 (CONTRACT_OBJID 포함) -->
|
||||
<select id="getProjectInfo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getProjectInfo - PROJECT_MGMT의 상세 정보 조회 (최신 1개) */
|
||||
SELECT
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
-- 요청납기 (CONTRACT_ITEM의 DUE_DATE 우선, 없으면 PROJECT_MGMT.DUE_DATE)
|
||||
COALESCE(
|
||||
(SELECT CI.DUE_DATE
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1),
|
||||
PM.DUE_DATE
|
||||
) AS REQ_DEL_DATE,
|
||||
-- S/N 조회 (CONTRACT_ITEM_SERIAL에서)
|
||||
(SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM CI
|
||||
JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
) AS SERIAL_NO,
|
||||
-- 고객요청사항 (CONTRACT_ITEM에서)
|
||||
(SELECT CI.CUSTOMER_REQUEST
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1
|
||||
) AS CUSTOMER_REQUEST,
|
||||
-- 반납사유 (CONTRACT_ITEM에서)
|
||||
(SELECT CI.RETURN_REASON
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LIMIT 1
|
||||
) AS RETURN_REASON
|
||||
FROM PROJECT_MGMT PM
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
ORDER BY PM.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- sales_registration 개수 조회 (분할 출하 순번용) -->
|
||||
<select id="getSaleRegistrationCount" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getSaleRegistrationCount - project_no로 시작하는 레코드 개수 */
|
||||
SELECT COUNT(*) as count
|
||||
FROM sales_registration
|
||||
WHERE project_no LIKE #{orderNo} || '%'
|
||||
</select>
|
||||
|
||||
<!-- sales_registration DELETE (기존 데이터 삭제) -->
|
||||
<delete id="deleteSaleRegistration" parameterType="map">
|
||||
/* salesNcollectMgmt.deleteSaleRegistration - sales_registration 삭제 */
|
||||
DELETE FROM sales_registration
|
||||
WHERE project_no = #{orderNo}
|
||||
</delete>
|
||||
|
||||
<!-- sales_registration UPDATE (기존 데이터 수정) -->
|
||||
<update id="updateSaleRegistration" parameterType="map">
|
||||
/* salesNcollectMgmt.updateSaleRegistration - sales_registration 업데이트 */
|
||||
UPDATE sales_registration
|
||||
SET
|
||||
shipping_order_status = <choose>
|
||||
<when test="shippingOrderStatus != null and shippingOrderStatus != ''">
|
||||
#{shippingOrderStatus},
|
||||
</when>
|
||||
<otherwise>
|
||||
'',
|
||||
</otherwise>
|
||||
</choose>
|
||||
serial_no = #{serialNo},
|
||||
sales_quantity = #{salesQuantity}::integer,
|
||||
sales_unit_price = #{salesUnitPrice}::numeric,
|
||||
sales_supply_price = #{salesSupplyPrice}::numeric,
|
||||
sales_vat = #{salesVat}::numeric,
|
||||
sales_total_amount = #{salesTotalAmount}::numeric,
|
||||
sales_currency = #{salesCurrency},
|
||||
sales_exchange_rate = #{salesExchangeRate}::numeric,
|
||||
shipping_date = <choose>
|
||||
<when test="shippingDate != null and shippingDate != ''">
|
||||
TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
|
||||
</when>
|
||||
<otherwise>
|
||||
NULL,
|
||||
</otherwise>
|
||||
</choose>
|
||||
shipping_method = #{shippingMethod},
|
||||
manager_user_id = #{manager},
|
||||
incoterms = #{incoterms},
|
||||
upd_date = NOW(),
|
||||
upd_user_id = #{cretEmpNo}
|
||||
WHERE project_no = #{orderNo}
|
||||
</update>
|
||||
|
||||
<!-- ========================================
|
||||
분할 출하 관련 쿼리 (shipment_log 테이블 활용)
|
||||
======================================== -->
|
||||
|
||||
<!-- shipment_log의 split_quantity 합산 조회 -->
|
||||
<select id="getShipmentLogTotal" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getShipmentLogTotal - shipment_log의 split_quantity 합산 */
|
||||
SELECT COALESCE(SUM(split_quantity), 0) as total
|
||||
FROM shipment_log SL
|
||||
INNER JOIN project_mgmt PM ON SL.target_objid = PM.OBJID::VARCHAR
|
||||
WHERE PM.PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
|
||||
<!-- shipment_log에 분할 출하 기록 저장 -->
|
||||
<insert id="insertShipmentLog" parameterType="map">
|
||||
/* salesNcollectMgmt.insertShipmentLog - 분할 출하 기록 저장 */
|
||||
INSERT INTO shipment_log (
|
||||
target_objid, log_type, log_message, split_quantity, original_quantity,
|
||||
remaining_quantity, shipping_status, shipping_date, shipping_method,
|
||||
sales_unit_price, sales_supply_price, sales_vat, sales_total_amount,
|
||||
sales_currency, sales_exchange_rate, manager_user_id, incoterms,
|
||||
serial_no, parent_sale_no, reg_user_id
|
||||
) VALUES (
|
||||
#{targetObjid}, 'SPLIT_SHIPMENT', '분할 출하',
|
||||
#{salesQuantity}::integer, #{originalQuantity}::integer, #{remainingQuantity}::integer,
|
||||
#{shippingOrderStatus},
|
||||
<choose>
|
||||
<when test="shippingDate != null and shippingDate != ''">
|
||||
TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
|
||||
</when>
|
||||
<otherwise>NULL,</otherwise>
|
||||
</choose>
|
||||
#{shippingMethod}, #{salesUnitPrice}::numeric, #{salesSupplyPrice}::numeric,
|
||||
#{salesVat}::numeric, #{salesTotalAmount}::numeric, #{salesCurrency},
|
||||
#{salesExchangeRate}::numeric, #{managerUserId}, #{incoterms}, #{serialNo},
|
||||
#{parentSaleNo}::integer, #{cretEmpNo}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- sales_registration의 수량을 shipment_log 합계로 업데이트 -->
|
||||
<update id="updateSalesQuantityFromShipmentLog" parameterType="map">
|
||||
/* salesNcollectMgmt.updateSalesQuantityFromShipmentLog - shipment_log 합계로 sales_quantity 업데이트 */
|
||||
UPDATE sales_registration
|
||||
SET sales_quantity = (
|
||||
SELECT COALESCE(SUM(split_quantity), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_supply_price = (
|
||||
SELECT COALESCE(SUM(sales_supply_price), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_vat = (
|
||||
SELECT COALESCE(SUM(sales_vat), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
),
|
||||
sales_total_amount = (
|
||||
SELECT COALESCE(SUM(sales_total_amount), 0)
|
||||
FROM shipment_log
|
||||
WHERE target_objid = #{projectNo}
|
||||
)
|
||||
WHERE sale_no = #{saleNo}
|
||||
</update>
|
||||
|
||||
<!-- PROJECT_MGMT의 OBJID 조회 (shipment_log의 target_objid로 사용) -->
|
||||
<select id="getProjectObjid" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getProjectObjid - PROJECT_MGMT의 OBJID 조회 */
|
||||
SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = #{orderNo}
|
||||
</select>
|
||||
|
||||
<!-- 출하일 상세 내역 조회 (모든 분할 출하 포함) -->
|
||||
<select id="getShippingDetailList" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getShippingDetailList - shipment_log에서 모든 분할 출하 조회 */
|
||||
SELECT
|
||||
COALESCE(TO_CHAR(SL.shipping_date, 'YYYY-MM-DD'), '미등록') AS shipping_date,
|
||||
COALESCE(SL.split_quantity, 0) AS shipping_quantity,
|
||||
COALESCE(SL.shipping_status, '미등록') AS shipping_order_status,
|
||||
COALESCE(SL.serial_no, '-') AS serial_no,
|
||||
SL.target_objid AS project_no,
|
||||
'분할 출하 ' || SL.log_id AS source,
|
||||
TO_CHAR(SL.reg_date, 'YYYY-MM-DD HH24:MI:SS') AS reg_date
|
||||
FROM shipment_log SL
|
||||
WHERE SL.target_objid = #{projectNo}
|
||||
ORDER BY SL.shipping_date DESC, SL.log_id DESC
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 - 고객 정보 조회 -->
|
||||
<select id="getCustomerInfoByProjectNo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getCustomerInfoByProjectNo - 프로젝트 번호로 고객 정보 조회 */
|
||||
SELECT
|
||||
SM.SUPPLY_NAME AS CUSTOMER_NAME,
|
||||
SM.BUSINESS_NO AS CUSTOMER_REG_NO,
|
||||
SM.ADDRESS AS CUSTOMER_ADDRESS,
|
||||
SM.BUSINESS_TYPE AS CUSTOMER_BUSINESS,
|
||||
SM.BUSINESS_ITEM AS CUSTOMER_TYPE,
|
||||
SM.TEL_NO AS CUSTOMER_CONTACT
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN SUPPLY_MNG SM ON PM.CUSTOMER_OBJID::NUMERIC = SM.OBJID
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 - 품목 정보 조회 -->
|
||||
<select id="getTransactionStatementItem" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getTransactionStatementItem - 프로젝트 번호로 품목 정보 조회 */
|
||||
SELECT
|
||||
PM.PART_NAME AS productName,
|
||||
PM.PART_NO AS spec,
|
||||
COALESCE(SR.sales_quantity, PM.QUANTITY) AS quantity,
|
||||
COALESCE(SR.sales_unit_price, 0) AS unitPrice,
|
||||
COALESCE(SR.sales_supply_price, 0) AS supplyPrice,
|
||||
COALESCE(SR.sales_vat, 0) AS vat
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN sales_registration SR ON PM.PROJECT_NO = SR.project_no
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
</select>
|
||||
|
||||
<!-- 거래명세서 저장 - NSWOS100_TBL 테이블 사용 -->
|
||||
<insert id="saveTransactionStatement" parameterType="map">
|
||||
/* salesNcollectMgmt.saveTransactionStatement - 거래명세서 저장 */
|
||||
INSERT INTO NSWOS100_TBL (
|
||||
SuVndCd /* 업체코드 */
|
||||
,IssueDt /* 작성일자 */
|
||||
,IssueNo /* 거래명세서번호 */
|
||||
,IsNo /* 순번 */
|
||||
,ProdCd /* 기종코드 */
|
||||
,OdOrderNo /* 발주번호 */
|
||||
,ImItemId /* 품번 */
|
||||
,RmDueDt /* 납기일자 */
|
||||
,RmOrderQty /* 발주수량 */
|
||||
,RmRcptQty /* 입고처리수량 */
|
||||
,RmRemQty /* 잔량 */
|
||||
,IsDt /* 납기일자 */
|
||||
,IsQty /* 납품수량 */
|
||||
,IsPrice /* 납품단가 */
|
||||
,IsAmount /* 납품금액 */
|
||||
) VALUES (
|
||||
#{suVndCd} /* 업체코드 */
|
||||
,#{issueDt} /* 작성일자 */
|
||||
,#{issueNo}::integer /* 거래명세서번호 */
|
||||
,#{isNo}::integer /* 순번 */
|
||||
,COALESCE(#{prodCd}, '') /* 기종코드 */
|
||||
,COALESCE(#{odOrderNo}, '') /* 발주번호 */
|
||||
,COALESCE(#{imItemId}, '') /* 품번 */
|
||||
,COALESCE(#{rmDueDt}, '') /* 납기일자 */
|
||||
,COALESCE(#{rmOrderQty}, 0)::integer /* 발주수량 */
|
||||
,COALESCE(#{rmRcptQty}, 0)::integer /* 입고처리수량 */
|
||||
,COALESCE(#{rmRemQty}, 0)::integer /* 잔량 */
|
||||
,COALESCE(#{isDt}, '') /* 납기일자 */
|
||||
,COALESCE(#{isQty}, 0)::integer /* 납품수량 */
|
||||
,COALESCE(#{isPrice}, 0)::numeric /* 납품단가 */
|
||||
,COALESCE(#{isAmount}, 0)::numeric /* 납품금액 */
|
||||
) ON CONFLICT (SuVndCd, IssueDt, IssueNo, IsNo) DO
|
||||
UPDATE SET
|
||||
ProdCd = COALESCE(#{prodCd}, '')
|
||||
,OdOrderNo = COALESCE(#{odOrderNo}, '')
|
||||
,ImItemId = COALESCE(#{imItemId}, '')
|
||||
,RmDueDt = COALESCE(#{rmDueDt}, '')
|
||||
,RmOrderQty = COALESCE(#{rmOrderQty}, 0)::integer
|
||||
,RmRcptQty = COALESCE(#{rmRcptQty}, 0)::integer
|
||||
,RmRemQty = COALESCE(#{rmRemQty}, 0)::integer
|
||||
,IsDt = COALESCE(#{isDt}, '')
|
||||
,IsQty = COALESCE(#{isQty}, 0)::integer
|
||||
,IsPrice = COALESCE(#{isPrice}, 0)::numeric
|
||||
,IsAmount = COALESCE(#{isAmount}, 0)::numeric
|
||||
</insert>
|
||||
|
||||
<!-- 거래명세서 번호 생성 -->
|
||||
<select id="getNextTransactionStatementNo" parameterType="map" resultType="int">
|
||||
/* salesNcollectMgmt.getNextTransactionStatementNo - 거래명세서 번호 생성 */
|
||||
SELECT COALESCE(MAX(IssueNo), 0) + 1 AS nextNo
|
||||
FROM NSWOS100_TBL
|
||||
WHERE SuVndCd = #{suVndCd}
|
||||
AND IssueDt = #{issueDt}
|
||||
</select>
|
||||
|
||||
<select id="getAllSerialNumbers" parameterType="map" resultType="string">
|
||||
/* salesNcollectMgmt.getAllSerialNumbers - 프로젝트의 모든 S/N 조회 */
|
||||
SELECT CIS.SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
WHERE PM.PROJECT_NO = #{projectNo}
|
||||
AND CIS.SERIAL_NO IS NOT NULL
|
||||
ORDER BY CIS.SERIAL_NO
|
||||
</select>
|
||||
|
||||
<select id="getSavedTransactionStatement" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getSavedTransactionStatement - 저장된 거래명세서 조회 */
|
||||
SELECT
|
||||
SuVndCd,
|
||||
IssueDt,
|
||||
IssueNo,
|
||||
IsNo,
|
||||
ProdCd,
|
||||
OdOrderNo,
|
||||
ImItemId,
|
||||
RmDueDt,
|
||||
RmOrderQty,
|
||||
RmRcptQty,
|
||||
RmRemQty,
|
||||
IsDt,
|
||||
IsQty,
|
||||
IsPrice,
|
||||
IsAmount
|
||||
FROM NSWOS100_TBL
|
||||
WHERE OdOrderNo = #{projectNo}
|
||||
ORDER BY IsNo
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
|
||||
@@ -2452,6 +2452,41 @@ private String encodeImageToBase64(String imagePath) {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 주문서관리 Total 합계 조회
|
||||
* @param request
|
||||
* @param paramMap - 검색 조건
|
||||
* @return Map - TOTAL_SUPPLY_PRICE, TOTAL_VAT, TOTAL_AMOUNT
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Map<String, Object> getOrderTotalAmount(HttpServletRequest request, Map<String, Object> paramMap){
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
resultMap = sqlSession.selectOne("contractMgmt.getOrderTotalAmount", paramMap);
|
||||
|
||||
// 대문자 변환
|
||||
if(resultMap != null) {
|
||||
resultMap = CommonUtils.keyChangeUpperMap(resultMap);
|
||||
} else {
|
||||
// 데이터가 없을 경우 기본값 설정
|
||||
resultMap = new HashMap<String, Object>();
|
||||
resultMap.put("TOTAL_SUPPLY_PRICE", 0);
|
||||
resultMap.put("TOTAL_VAT", 0);
|
||||
resultMap.put("TOTAL_AMOUNT", 0);
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 품목 조회 (수주등록용)
|
||||
* 최종 견적서의 품목 정보를 수주등록 형식으로 변환하여 반환
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
package com.pms.salesmgmt.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -308,10 +310,39 @@ public class SalesNcollectMgmtService {
|
||||
}
|
||||
}
|
||||
|
||||
return CommonUtils.toUpperCaseMapKey(resultMap);
|
||||
return CommonUtils.toUpperCaseMapKey(resultMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 프로젝트의 모든 품목 조회 - 주석처리: 품목은 하나만 존재
|
||||
*/
|
||||
/*
|
||||
public List<Map<String, Object>> getProjectItems(Map<String, Object> paramMap) {
|
||||
List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
resultList = sqlSession.selectList("salesNcollectMgmt.getProjectItems", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> saveSaleRegistration(HttpServletRequest request, Map<String, Object> paramMap) {
|
||||
// 대문자 키로 변환
|
||||
List<Map<String, Object>> upperCaseList = new ArrayList<Map<String, Object>>();
|
||||
for(Map<String, Object> item : resultList) {
|
||||
upperCaseList.add(CommonUtils.toUpperCaseMapKey(item));
|
||||
}
|
||||
|
||||
return upperCaseList;
|
||||
}
|
||||
*/
|
||||
|
||||
public Map<String, Object> saveSaleRegistration(HttpServletRequest request, Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
@@ -321,18 +352,117 @@ public class SalesNcollectMgmtService {
|
||||
PersonBean person = (PersonBean) request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("cretEmpNo", person.getUserId());
|
||||
|
||||
// sales_registration 테이블에 판매 데이터 저장 (ON CONFLICT로 자동 UPDATE)
|
||||
sqlSession.insert("salesNcollectMgmt.insertSaleRegistration", paramMap);
|
||||
|
||||
sqlSession.commit();
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("msg", "저장되었습니다.");
|
||||
String projectNo = (String) paramMap.get("orderNo");
|
||||
String saleNo = (String) paramMap.get("saleNo");
|
||||
|
||||
System.out.println("=== saveSaleRegistration 시작 ===");
|
||||
System.out.println("projectNo: " + projectNo);
|
||||
System.out.println("saleNo (파라미터): " + saleNo);
|
||||
System.out.println("salesQuantity: " + paramMap.get("salesQuantity"));
|
||||
|
||||
// 모든 판매를 shipment_log에 기록 (분할 출하 방식 통일)
|
||||
// 1. 해당 프로젝트의 sales_registration 레코드 확인
|
||||
Map<String, Object> checkParam = new HashMap<String, Object>();
|
||||
checkParam.put("orderNo", projectNo);
|
||||
Map<String, Object> existingSale = sqlSession.selectOne("salesNcollectMgmt.getSaleInfo", checkParam);
|
||||
|
||||
Object saleNoObj = null;
|
||||
if(existingSale != null) {
|
||||
saleNoObj = existingSale.get("SALE_NO");
|
||||
if(saleNoObj == null) saleNoObj = existingSale.get("sale_no");
|
||||
}
|
||||
|
||||
System.out.println("existingSale: " + (existingSale != null ? "있음" : "없음"));
|
||||
System.out.println("SALE_NO: " + saleNoObj);
|
||||
|
||||
// 2. sales_registration 레코드가 없으면 먼저 생성
|
||||
if(saleNoObj == null) {
|
||||
System.out.println("sales_registration 레코드 생성 (첫 판매)");
|
||||
|
||||
// sales_registration에 기본 레코드 INSERT (수량은 0으로)
|
||||
Map<String, Object> baseRecord = new HashMap<String, Object>();
|
||||
baseRecord.put("orderNo", projectNo);
|
||||
baseRecord.put("salesQuantity", 0); // 기본 레코드는 수량 0
|
||||
baseRecord.put("salesUnitPrice", paramMap.get("salesUnitPrice"));
|
||||
baseRecord.put("salesSupplyPrice", 0);
|
||||
baseRecord.put("salesVat", 0);
|
||||
baseRecord.put("salesTotalAmount", 0);
|
||||
baseRecord.put("salesCurrency", paramMap.get("salesCurrency"));
|
||||
baseRecord.put("salesExchangeRate", paramMap.get("salesExchangeRate"));
|
||||
baseRecord.put("shippingDate", paramMap.get("shippingDate"));
|
||||
baseRecord.put("shippingMethod", paramMap.get("shippingMethod"));
|
||||
baseRecord.put("managerUserId", paramMap.get("managerUserId"));
|
||||
baseRecord.put("incoterms", paramMap.get("incoterms"));
|
||||
baseRecord.put("serialNo", paramMap.get("serialNo"));
|
||||
baseRecord.put("cretEmpNo", paramMap.get("cretEmpNo"));
|
||||
|
||||
sqlSession.insert("salesNcollectMgmt.insertSaleRegistration", baseRecord);
|
||||
|
||||
// 생성된 sale_no 조회
|
||||
existingSale = sqlSession.selectOne("salesNcollectMgmt.getSaleInfo", checkParam);
|
||||
saleNoObj = existingSale.get("SALE_NO");
|
||||
if(saleNoObj == null) saleNoObj = existingSale.get("sale_no");
|
||||
|
||||
System.out.println("생성된 SALE_NO: " + saleNoObj);
|
||||
}
|
||||
|
||||
// 3. shipment_log에 판매 기록 INSERT
|
||||
System.out.println("shipment_log에 판매 기록 INSERT");
|
||||
|
||||
Object orderQtyObj = existingSale.get("ORDER_QUANTITY");
|
||||
if(orderQtyObj == null) orderQtyObj = existingSale.get("order_quantity");
|
||||
|
||||
System.out.println("ORDER_QUANTITY: " + orderQtyObj);
|
||||
|
||||
if(orderQtyObj == null || saleNoObj == null) {
|
||||
System.out.println("=== existingSale 전체 내용 ===");
|
||||
for(Object key : existingSale.keySet()) {
|
||||
System.out.println(key + ": " + existingSale.get(key));
|
||||
}
|
||||
throw new RuntimeException("ORDER_QUANTITY 또는 SALE_NO가 null입니다");
|
||||
}
|
||||
|
||||
paramMap.put("targetObjid", projectNo);
|
||||
paramMap.put("originalQuantity", orderQtyObj);
|
||||
|
||||
// 잔량 계산
|
||||
int orderQuantity = Integer.parseInt(String.valueOf(orderQtyObj).split("\\.")[0]);
|
||||
int salesQuantity = Integer.parseInt(String.valueOf(paramMap.get("salesQuantity")));
|
||||
int remainingQuantity = orderQuantity - salesQuantity;
|
||||
|
||||
System.out.println("orderQuantity: " + orderQuantity);
|
||||
System.out.println("salesQuantity: " + salesQuantity);
|
||||
System.out.println("remainingQuantity: " + remainingQuantity);
|
||||
|
||||
paramMap.put("remainingQuantity", remainingQuantity);
|
||||
paramMap.put("parentSaleNo", saleNoObj);
|
||||
|
||||
System.out.println("shipment_log INSERT 직전 파라미터:");
|
||||
System.out.println(" targetObjid: " + paramMap.get("targetObjid"));
|
||||
System.out.println(" parentSaleNo: " + paramMap.get("parentSaleNo"));
|
||||
System.out.println(" cretEmpNo: " + paramMap.get("cretEmpNo"));
|
||||
|
||||
sqlSession.insert("salesNcollectMgmt.insertShipmentLog", paramMap);
|
||||
|
||||
// 4. sales_registration의 sales_quantity를 shipment_log 합계로 업데이트
|
||||
System.out.println("sales_registration 업데이트 - shipment_log 합계 반영");
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.put("projectNo", projectNo);
|
||||
updateParam.put("saleNo", saleNoObj);
|
||||
sqlSession.update("salesNcollectMgmt.updateSalesQuantityFromShipmentLog", updateParam);
|
||||
|
||||
sqlSession.commit();
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("msg", "저장되었습니다.");
|
||||
System.out.println("=== 저장 성공 ===");
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", "저장 중 오류가 발생했습니다.");
|
||||
System.out.println("=== 저장 실패 ===");
|
||||
System.out.println("에러 메시지: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
@@ -918,4 +1048,382 @@ public class SalesNcollectMgmtService {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 분할 출하의 총 판매 수량 조회
|
||||
* @param paramMap
|
||||
* @return Map
|
||||
*/
|
||||
public Map<String, Object> getTotalSalesQuantity(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> result = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
result = sqlSession.selectOne("salesNcollectMgmt.getTotalSalesQuantity", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* shipment_log에서 총 출하 수량 조회
|
||||
* </pre>
|
||||
* @param paramMap
|
||||
* @return Integer
|
||||
*/
|
||||
public Integer getTotalShippedQuantity(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Integer result = 0;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
result = sqlSession.selectOne("salesNcollectMgmt.getTotalShippedQuantity", paramMap);
|
||||
if(result == null) result = 0;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
result = 0;
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 프로젝트 기본 정보 조회 (CONTRACT_OBJID 포함)
|
||||
* </pre>
|
||||
* @param paramMap
|
||||
* @return Map
|
||||
*/
|
||||
public Map<String, Object> getProjectInfo(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> result = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
result = sqlSession.selectOne("salesNcollectMgmt.getProjectInfo", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 출하일 상세 내역 조회
|
||||
* @param projectNo
|
||||
* @return List
|
||||
*/
|
||||
public List<Map<String, Object>> getShippingDetailList(String projectNo) {
|
||||
SqlSession sqlSession = null;
|
||||
List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
Map<String, Object> paramMap = new HashMap<String, Object>();
|
||||
paramMap.put("projectNo", projectNo);
|
||||
resultList = sqlSession.selectList("salesNcollectMgmt.getShippingDetailList", paramMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래명세서 데이터 조회
|
||||
* @param paramMap - projectNos (쉼표로 구분된 프로젝트 번호들)
|
||||
* @return Map
|
||||
*/
|
||||
public Map<String, Object> getTransactionStatementData(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String projectNos = (String) paramMap.get("projectNos");
|
||||
System.out.println("=== getTransactionStatementData 시작 ===");
|
||||
System.out.println("projectNos: " + projectNos);
|
||||
|
||||
String[] projectNoArray = projectNos.split(",");
|
||||
|
||||
// 첫 번째 프로젝트의 고객 정보 조회
|
||||
Map<String, Object> firstProjectParam = new HashMap<String, Object>();
|
||||
firstProjectParam.put("projectNo", projectNoArray[0].trim());
|
||||
System.out.println("고객 정보 조회 - projectNo: " + projectNoArray[0].trim());
|
||||
|
||||
Map<String, Object> customerInfo = sqlSession.selectOne("salesNcollectMgmt.getCustomerInfoByProjectNo", firstProjectParam);
|
||||
System.out.println("고객 정보 조회 결과: " + customerInfo);
|
||||
|
||||
if(customerInfo != null) {
|
||||
resultMap.put("customerName", customerInfo.get("CUSTOMER_NAME"));
|
||||
resultMap.put("customerRegNo", customerInfo.get("CUSTOMER_REG_NO"));
|
||||
resultMap.put("customerAddress", customerInfo.get("CUSTOMER_ADDRESS"));
|
||||
resultMap.put("customerBusiness", customerInfo.get("CUSTOMER_BUSINESS"));
|
||||
resultMap.put("customerType", customerInfo.get("CUSTOMER_TYPE"));
|
||||
resultMap.put("customerContact", customerInfo.get("CUSTOMER_CONTACT"));
|
||||
System.out.println("고객명: " + customerInfo.get("CUSTOMER_NAME"));
|
||||
} else {
|
||||
System.out.println("고객 정보가 null입니다!");
|
||||
}
|
||||
|
||||
// 공급자 정보 (회사 정보)
|
||||
resultMap.put("supplierName", "㈜압피에스");
|
||||
resultMap.put("supplierRegNo", "314-81-75146");
|
||||
resultMap.put("supplierAddress", "대전광역시 유성구 국제과학10로 8");
|
||||
resultMap.put("supplierBusiness", "제조");
|
||||
resultMap.put("supplierType", "금속절삭가공기계의");
|
||||
resultMap.put("supplierContact", "TEL:042-602-3300/FAX:042-672");
|
||||
|
||||
// 품목 정보 조회
|
||||
List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();
|
||||
for(String projectNo : projectNoArray) {
|
||||
Map<String, Object> itemParam = new HashMap<String, Object>();
|
||||
itemParam.put("projectNo", projectNo.trim());
|
||||
System.out.println("품목 정보 조회 - projectNo: " + projectNo.trim());
|
||||
|
||||
Map<String, Object> item = sqlSession.selectOne("salesNcollectMgmt.getTransactionStatementItem", itemParam);
|
||||
System.out.println("품목 정보 조회 결과: " + item);
|
||||
|
||||
if(item != null) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
resultMap.put("items", items);
|
||||
System.out.println("총 품목 개수: " + items.size());
|
||||
|
||||
// 비고
|
||||
resultMap.put("note", "아래와 같이 공급합니다.");
|
||||
|
||||
System.out.println("=== resultMap 최종 ===");
|
||||
System.out.println("customerName: " + resultMap.get("customerName"));
|
||||
System.out.println("items size: " + ((List)resultMap.get("items")).size());
|
||||
System.out.println("supplierName: " + resultMap.get("supplierName"));
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println("=== 에러 발생 ===");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래명세서 저장 (NSWOS100_TBL)
|
||||
*/
|
||||
public Map<String, Object> saveTransactionStatement(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
System.out.println("=== 거래명세서 저장 시작 ===");
|
||||
System.out.println("paramMap: " + paramMap);
|
||||
|
||||
// 업체코드 (고객 정보에서 추출 필요 - 임시로 '0001' 사용)
|
||||
String suVndCd = "0001";
|
||||
|
||||
// 작성일자 (오늘 날짜)
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
|
||||
String issueDt = sdf.format(new Date());
|
||||
|
||||
// 납품일자 포맷 변환 (한글 날짜 또는 YYYY-MM-DD → YYYYMMDD)
|
||||
String deliveryDate = "";
|
||||
if(paramMap.get("deliveryDate") != null && !paramMap.get("deliveryDate").equals("")) {
|
||||
String deliveryDateStr = String.valueOf(paramMap.get("deliveryDate"));
|
||||
|
||||
// 한글 날짜 형식인 경우 (예: "목요일, 11월 13, 2025")
|
||||
// 오늘 날짜로 대체
|
||||
if(deliveryDateStr.contains("월") || deliveryDateStr.contains("일")) {
|
||||
deliveryDate = issueDt; // 작성일자와 동일하게 설정
|
||||
System.out.println("납품일자 변환 (한글): " + deliveryDateStr + " → " + deliveryDate + " (오늘 날짜 사용)");
|
||||
}
|
||||
// YYYY-MM-DD 형식인 경우
|
||||
else if(deliveryDateStr.contains("-")) {
|
||||
deliveryDate = deliveryDateStr.replaceAll("-", ""); // "2025-11-13" → "20251113"
|
||||
System.out.println("납품일자 변환 (하이픈): " + deliveryDateStr + " → " + deliveryDate);
|
||||
}
|
||||
// 이미 YYYYMMDD 형식인 경우
|
||||
else if(deliveryDateStr.length() == 8) {
|
||||
deliveryDate = deliveryDateStr;
|
||||
System.out.println("납품일자 변환 (8자리): " + deliveryDateStr + " → " + deliveryDate);
|
||||
}
|
||||
// 그 외의 경우 오늘 날짜 사용
|
||||
else {
|
||||
deliveryDate = issueDt;
|
||||
System.out.println("납품일자 변환 (기타): " + deliveryDateStr + " → " + deliveryDate + " (오늘 날짜 사용)");
|
||||
}
|
||||
}
|
||||
|
||||
// 거래명세서 번호 생성
|
||||
Map<String, Object> noParam = new HashMap<String, Object>();
|
||||
noParam.put("suVndCd", suVndCd);
|
||||
noParam.put("issueDt", issueDt);
|
||||
Integer issueNo = sqlSession.selectOne("salesNcollectMgmt.getNextTransactionStatementNo", noParam);
|
||||
|
||||
System.out.println("업체코드: " + suVndCd);
|
||||
System.out.println("작성일자: " + issueDt);
|
||||
System.out.println("거래명세서번호: " + issueNo);
|
||||
|
||||
// 품목 정보 저장
|
||||
List<Map<String, Object>> items = (List<Map<String, Object>>) paramMap.get("items");
|
||||
if(items != null && items.size() > 0) {
|
||||
int seqNo = 1;
|
||||
for(Map<String, Object> item : items) {
|
||||
Map<String, Object> insertParam = new HashMap<String, Object>();
|
||||
insertParam.put("suVndCd", suVndCd);
|
||||
insertParam.put("issueDt", issueDt);
|
||||
insertParam.put("issueNo", issueNo);
|
||||
insertParam.put("isNo", seqNo);
|
||||
|
||||
// 품목 정보
|
||||
insertParam.put("prodCd", ""); // 기종코드
|
||||
|
||||
// 발주번호 (프로젝트번호) - VARCHAR(15) 제한
|
||||
String projectNos = String.valueOf(paramMap.get("projectNos"));
|
||||
if(projectNos.length() > 15) {
|
||||
projectNos = projectNos.substring(0, 15); // 15자로 자르기
|
||||
}
|
||||
insertParam.put("odOrderNo", projectNos);
|
||||
|
||||
// 품번 - VARCHAR(15) 제한
|
||||
String spec = String.valueOf(item.get("spec"));
|
||||
if(spec != null && spec.length() > 15) {
|
||||
spec = spec.substring(0, 15); // 15자로 자르기
|
||||
}
|
||||
insertParam.put("imItemId", spec);
|
||||
|
||||
insertParam.put("rmDueDt", ""); // 납기일자
|
||||
|
||||
// 수량 정보
|
||||
String quantityStr = String.valueOf(item.get("quantity"));
|
||||
quantityStr = quantityStr.replaceAll(",", "").replaceAll("[^0-9]", "");
|
||||
int quantity = 0;
|
||||
try {
|
||||
quantity = Integer.parseInt(quantityStr);
|
||||
} catch(Exception e) {
|
||||
quantity = 0;
|
||||
}
|
||||
insertParam.put("rmOrderQty", quantity); // 발주수량
|
||||
insertParam.put("rmRcptQty", 0); // 입고처리수량
|
||||
insertParam.put("rmRemQty", 0); // 잔량
|
||||
insertParam.put("isDt", deliveryDate); // 납기일자 (포맷 변환된 값)
|
||||
insertParam.put("isQty", quantity); // 납품수량
|
||||
|
||||
// 금액 정보
|
||||
String unitPriceStr = String.valueOf(item.get("unitPrice"));
|
||||
unitPriceStr = unitPriceStr.replaceAll(",", "").replaceAll("[^0-9.]", "");
|
||||
double unitPrice = 0;
|
||||
try {
|
||||
unitPrice = Double.parseDouble(unitPriceStr);
|
||||
} catch(Exception e) {
|
||||
unitPrice = 0;
|
||||
}
|
||||
|
||||
String supplyPriceStr = String.valueOf(item.get("supplyPrice"));
|
||||
supplyPriceStr = supplyPriceStr.replaceAll(",", "").replaceAll("[^0-9.]", "");
|
||||
double supplyPrice = 0;
|
||||
try {
|
||||
supplyPrice = Double.parseDouble(supplyPriceStr);
|
||||
} catch(Exception e) {
|
||||
supplyPrice = 0;
|
||||
}
|
||||
|
||||
insertParam.put("isPrice", unitPrice); // 납품단가
|
||||
insertParam.put("isAmount", supplyPrice); // 납품금액
|
||||
|
||||
System.out.println("품목 " + seqNo + " 저장: " + item.get("productName"));
|
||||
System.out.println(" - 품번: " + item.get("spec"));
|
||||
System.out.println(" - 수량: " + quantity);
|
||||
System.out.println(" - 단가: " + unitPrice);
|
||||
System.out.println(" - 금액: " + supplyPrice);
|
||||
|
||||
sqlSession.insert("salesNcollectMgmt.saveTransactionStatement", insertParam);
|
||||
seqNo++;
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("message", "거래명세서가 저장되었습니다.");
|
||||
resultMap.put("issueNo", issueNo);
|
||||
|
||||
System.out.println("=== 거래명세서 저장 완료 ===");
|
||||
|
||||
} catch (Exception e) {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
System.out.println("=== 거래명세서 저장 실패 ===");
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "저장 중 오류가 발생했습니다: " + e.getMessage());
|
||||
} finally {
|
||||
if (sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
public List<String> getAllSerialNumbers(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
List<String> result = new ArrayList<String>();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
result = sqlSession.selectList("salesNcollectMgmt.getAllSerialNumbers", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getSavedTransactionStatement(Map<String, Object> paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
result = sqlSession.selectList("salesNcollectMgmt.getSavedTransactionStatement", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3476,6 +3476,35 @@ public class PartMngService extends BaseService {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 품번으로 BOM OBJID 조회
|
||||
*/
|
||||
public Map<String, Object> getBomObjIdByPartNo(Map paramMap) throws Exception{
|
||||
Map<String, Object> resultMap = null;
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
// PART_BOM_REPORT 테이블에서 품번으로 OBJID 조회
|
||||
resultMap = (Map<String, Object>)sqlSession.selectOne("partMng.getBomObjIdByPartNo", paramMap);
|
||||
|
||||
if(resultMap != null) {
|
||||
resultMap = CommonUtils.toUpperCaseMapKey(resultMap);
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* BOM 복사를 위한 데이터 조회 (엑셀 파싱 형식과 동일하게 반환)
|
||||
*/
|
||||
|
||||
@@ -749,4 +749,57 @@ public class ProductionPlanningService {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 저장
|
||||
* @param request
|
||||
* @param mbomData
|
||||
* @param partNo
|
||||
* @param partName
|
||||
* @return
|
||||
*/
|
||||
public int saveMbom(HttpServletRequest request, List<Map<String, Object>> mbomData, String partNo, String partName) {
|
||||
SqlSession sqlSession = null;
|
||||
int result = 0;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
|
||||
// M-BOM 헤더 정보 생성
|
||||
Map<String, Object> headerMap = new HashMap<>();
|
||||
headerMap.put("PART_NO", partNo);
|
||||
headerMap.put("PART_NAME", partName);
|
||||
headerMap.put("CREATE_USER", userId);
|
||||
headerMap.put("UPDATE_USER", userId);
|
||||
|
||||
// M-BOM 헤더 저장
|
||||
sqlSession.insert("productionplanning.insertMbomHeader", headerMap);
|
||||
String mbomHeaderObjid = (String) headerMap.get("OBJID");
|
||||
|
||||
// M-BOM 상세 데이터 저장
|
||||
for(Map<String, Object> item : mbomData) {
|
||||
item.put("MBOM_HEADER_OBJID", mbomHeaderObjid);
|
||||
item.put("CREATE_USER", userId);
|
||||
item.put("UPDATE_USER", userId);
|
||||
sqlSession.insert("productionplanning.insertMbomDetail", item);
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
result = 1;
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user