dev #436

Merged
ysCha merged 10 commits from dev into prd-deploy 2026-03-19 15:28:15 +09:00
4 changed files with 205 additions and 189 deletions

View File

@ -71,7 +71,12 @@ public class AdminUserConfiguration implements JobExecutionListener {
@Bean @Bean
public ItemProcessor<AdminUserSyncResponse, AdminUserSyncResponse> adminUserProcessor() { public ItemProcessor<AdminUserSyncResponse, AdminUserSyncResponse> adminUserProcessor() {
return item -> item; return item -> {
if (item.getCategory() != null && item.getCategory().length() > 20) {
item.setCategory(item.getCategory().substring(0, 20));
}
return item;
};
} }
@Bean @Bean

View File

@ -1,6 +1,7 @@
package com.interplug.qcast.config.Exception; package com.interplug.qcast.config.Exception;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
@ -12,6 +13,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
protected ResponseEntity<ErrorResponse> handle(HttpRequestMethodNotSupportedException e) { protected ResponseEntity<ErrorResponse> handle(HttpRequestMethodNotSupportedException e) {
return ResponseEntity.badRequest() return ResponseEntity.badRequest()
.contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(ErrorCode.METHOD_NOT_ALLOWED.getMessage())); .body(ErrorResponse.of(ErrorCode.METHOD_NOT_ALLOWED.getMessage()));
} }
@ -19,6 +21,7 @@ public class GlobalExceptionHandler {
protected ResponseEntity<ErrorResponse> handle(BaseException e) { protected ResponseEntity<ErrorResponse> handle(BaseException e) {
final ErrorCode errorCode = e.getErrorCode(); final ErrorCode errorCode = e.getErrorCode();
return ResponseEntity.status(errorCode.getStatus()) return ResponseEntity.status(errorCode.getStatus())
.contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(errorCode.getMessage())); .body(ErrorResponse.of(errorCode.getMessage()));
} }
@ -27,14 +30,18 @@ public class GlobalExceptionHandler {
final ErrorCode errorCode = e.getErrorCode(); final ErrorCode errorCode = e.getErrorCode();
if (e.getMessage() == null) { if (e.getMessage() == null) {
return ResponseEntity.status(errorCode.getStatus()) return ResponseEntity.status(errorCode.getStatus())
.contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(errorCode.getMessage())); .body(ErrorResponse.of(errorCode.getMessage()));
} }
return ResponseEntity.status(errorCode.getStatus()).body(ErrorResponse.of(e.getMessage())); return ResponseEntity.status(errorCode.getStatus())
.contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(e.getMessage()));
} }
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponse> handle(Exception e) { protected ResponseEntity<ErrorResponse> handle(Exception e) {
return ResponseEntity.internalServerError() return ResponseEntity.internalServerError()
.contentType(MediaType.APPLICATION_JSON)
.body(ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR.getMessage())); .body(ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR.getMessage()));
} }
} }

View File

@ -37,41 +37,41 @@ public class InterfaceQsp {
* @return String * @return String
* @throws Exception * @throws Exception
*/ */
public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject) public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject)
throws Exception { throws Exception {
URL url = null; URL url = null;
HttpURLConnection con = null; HttpURLConnection con = null;
OutputStreamWriter osw = null; OutputStreamWriter osw = null;
BufferedReader br = null; BufferedReader br = null;
StringBuilder sb = null; StringBuilder sb = null;
long startAt = System.currentTimeMillis(); long startAt = System.currentTimeMillis();
String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName();
try { try {
// GET 요청 requestObject를 쿼리 스트링으로 변환 // GET 요청 requestObject를 쿼리 스트링으로 변환
if (HttpMethod.GET.equals(httpMethod) && requestObject != null) { if (HttpMethod.GET.equals(httpMethod) && requestObject != null) {
ObjectMapper om = new ObjectMapper(); ObjectMapper om = new ObjectMapper();
Map<String, Object> params = om.convertValue(requestObject, Map.class); // Object -> Map 변환 Map<String, Object> params = om.convertValue(requestObject, Map.class); // Object -> Map 변환
String queryString = String queryString =
params.entrySet().stream() params.entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue()) .map(entry -> entry.getKey() + "=" + entry.getValue())
.reduce((p1, p2) -> p1 + "&" + p2) .reduce((p1, p2) -> p1 + "&" + p2)
.orElse(""); .orElse("");
apiPath += "?" + queryString; // 쿼리 스트링 추가 apiPath += "?" + queryString; // 쿼리 스트링 추가
} }
log.debug( log.debug(
"QSP API call start: method={}, url={}, requestType={}", "QSP API call start: method={}, url={}, requestType={}",
httpMethod, httpMethod,
apiPath, apiPath,
requestType); requestType);
url = new URL(apiPath); url = new URL(apiPath);
con = (HttpURLConnection) url.openConnection(); con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정 con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정
con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정 con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정
con.setRequestMethod(httpMethod.toString()); con.setRequestMethod(httpMethod.toString());
con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Referer", frontUrl); con.setRequestProperty("Referer", frontUrl);
con.setDoInput(true); con.setDoInput(true);
@ -91,33 +91,34 @@ public class InterfaceQsp {
} }
sb = new StringBuilder(); sb = new StringBuilder();
int status = con.getResponseCode(); int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) { if (status == HttpURLConnection.HTTP_OK) {
br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); log.info("[DEBUG] QSP Content-Type: {}", con.getContentType());
br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
String line;
while ((line = br.readLine()) != null) { String line;
sb.append(line); while ((line = br.readLine()) != null) {
} sb.append(line);
} }
log.debug( }
"QSP API call end: method={}, url={}, status={}, durationMs={}", log.debug(
httpMethod, "QSP API call end: method={}, url={}, status={}, durationMs={}",
apiPath, httpMethod,
status, apiPath,
System.currentTimeMillis() - startAt); status,
} catch (Exception e) { System.currentTimeMillis() - startAt);
log.error( } catch (Exception e) {
"QSP API call failed: method={}, url={}, durationMs={}", log.error(
httpMethod, "QSP API call failed: method={}, url={}, durationMs={}",
apiPath, httpMethod,
System.currentTimeMillis() - startAt, apiPath,
e); System.currentTimeMillis() - startAt,
throw e; e);
} finally { throw e;
try { } finally {
if (osw != null) osw.close(); try {
if (br != null) br.close(); if (osw != null) osw.close();
if (br != null) br.close();
} catch (Exception e) { } catch (Exception e) {
throw e; throw e;
} }
@ -176,30 +177,30 @@ public class InterfaceQsp {
* @return String * @return String
* @throws Exception * @throws Exception
*/ */
public byte[] callApi( public byte[] callApi(
HttpMethod httpMethod, String apiPath, Object requestObject, Map<String, String> result) HttpMethod httpMethod, String apiPath, Object requestObject, Map<String, String> result)
throws Exception { throws Exception {
URL url = null; URL url = null;
HttpURLConnection con = null; HttpURLConnection con = null;
OutputStreamWriter osw = null; OutputStreamWriter osw = null;
BufferedReader br = null; BufferedReader br = null;
byte[] bt = null; byte[] bt = null;
long startAt = System.currentTimeMillis(); long startAt = System.currentTimeMillis();
String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName();
try { try {
log.debug( log.debug(
"QSP API call start: method={}, url={}, requestType={}", "QSP API call start: method={}, url={}, requestType={}",
httpMethod, httpMethod,
apiPath, apiPath,
requestType); requestType);
url = new URL(apiPath); url = new URL(apiPath);
con = (HttpURLConnection) url.openConnection(); con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정 con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정
con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정 con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정
con.setRequestMethod(httpMethod.toString()); con.setRequestMethod(httpMethod.toString());
con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Referer", frontUrl); con.setRequestProperty("Referer", frontUrl);
con.setDoInput(true); con.setDoInput(true);
@ -217,40 +218,40 @@ public class InterfaceQsp {
osw.flush(); osw.flush();
} }
} }
int status = con.getResponseCode(); int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) { if (status == HttpURLConnection.HTTP_OK) {
// response 헤더 결과 셋팅 // response 헤더 결과 셋팅
result.put("type", con.getHeaderField("Content-Type")); result.put("type", con.getHeaderField("Content-Type"));
result.put("disposition", con.getHeaderField("Content-Disposition")); result.put("disposition", con.getHeaderField("Content-Disposition"));
InputStream inputStream = con.getInputStream(); InputStream inputStream = con.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
int bytesRead; int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) { while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead); outputStream.write(buffer, 0, bytesRead);
} }
bt = outputStream.toByteArray(); // 파일 데이터 반환 bt = outputStream.toByteArray(); // 파일 데이터 반환
} }
log.debug( log.debug(
"QSP API call end: method={}, url={}, status={}, durationMs={}", "QSP API call end: method={}, url={}, status={}, durationMs={}",
httpMethod, httpMethod,
apiPath, apiPath,
status, status,
System.currentTimeMillis() - startAt); System.currentTimeMillis() - startAt);
} catch (Exception e) { } catch (Exception e) {
log.error( log.error(
"QSP API call failed: method={}, url={}, durationMs={}", "QSP API call failed: method={}, url={}, durationMs={}",
httpMethod, httpMethod,
apiPath, apiPath,
System.currentTimeMillis() - startAt, System.currentTimeMillis() - startAt,
e); e);
throw e; throw e;
} finally { } finally {
try { try {
if (osw != null) osw.close(); if (osw != null) osw.close();
if (br != null) br.close(); if (br != null) br.close();
} catch (Exception e) { } catch (Exception e) {
throw e; throw e;
} }

View File

@ -91,91 +91,94 @@
<select id="selectEstimatePdfDetail" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest" resultType="com.interplug.qcast.biz.estimate.dto.EstimateResponse"> <select id="selectEstimatePdfDetail" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest" resultType="com.interplug.qcast.biz.estimate.dto.EstimateResponse">
/* sqlid : com.interplug.qcast.biz.estimate.selectPdfEstimateDetail */ /* sqlid : com.interplug.qcast.biz.estimate.selectPdfEstimateDetail */
SELECT Z.*
, SS3.ZIP_NO AS ZIP_NO3
, SS3.ADDRESS AS ADDRESS3
, SS3.TEL AS TEL3
, SS3.FAX AS FAX3
, CASE WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') = '' THEN Z.ZIP_NO2
WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') != '' THEN SS3.ZIP_NO
ELSE Z.ZIP_NO1 END AS ZIP_NO
, CASE WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') = '' THEN Z.ADDRESS2
WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') != '' THEN SS3.ADDRESS
ELSE Z.ADDRESS1 END AS ADDRESS
, CASE WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') = '' THEN Z.TEL2
WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') != '' THEN SS3.TEL
ELSE Z.TEL1 END AS TEL
, CASE WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') = '' THEN Z.FAX2
WHEN Z.CREATE_USER = 'T01' AND ISNULL(Z.FIRST_AGENT_ID,'') != '' THEN SS3.FAX
ELSE Z.FAX1 END AS FAX
FROM (
SELECT
T.*
, SS1.SALE_STORE_NAME AS CUST_SALE_STORE_NAME
, COALESCE(NULLIF(SS2.DISP_COMPANY_NAME, ''), SS2.SALE_STORE_NAME) AS SALE_STORE_NAME
, COALESCE(NULLIF(SS2.DISP_ZIP_NO, ''), SS2.ZIP_NO) AS ZIP_NO1
, COALESCE(NULLIF(SS2.DISP_ADDRESS, ''), SS2.ADDRESS) AS ADDRESS1
, COALESCE(NULLIF(SS2.DISP_TEL, ''), SS2.TEL) AS TEL1
, COALESCE(NULLIF(SS2.DISP_FAX, ''), SS2.FAX) AS FAX1
, SSI2.BIZ_NO
, SS1.ZIP_NO AS ZIP_NO2
, SS1.ADDRESS AS ADDRESS2
, SS1.TEL AS TEL2
, SS1.FAX AS FAX2
, SS1.FIRST_AGENT_ID
, (SELECT BC.BUSINESS_TEAM_CD FROM M_BUSINESS_CHARGER BC WHERE BC.BUSINESS_CHARGER_CD = T.BUSINESS_CHARGER_CD) AS BUSINESS_TEAM_CD
FROM
(
SELECT SELECT
P.OBJECT_NO T.*
, P.PLAN_NO , SS1.SALE_STORE_NAME AS CUST_SALE_STORE_NAME
, CONVERT(VARCHAR(10), P.DRAWING_ESTIMATE_CREATE_DATE, 121) AS DRAWING_ESTIMATE_CREATE_DATE , COALESCE(NULLIF(SS2.DISP_COMPANY_NAME, ''), SS2.SALE_STORE_NAME) AS SALE_STORE_NAME
, P.ESTIMATE_VALIDITY_TERM <if test='saleStoreId != null and saleStoreId != "T01"'>
, P.SNOWFALL , COALESCE(NULLIF(SS2.DISP_ZIP_NO, ''), SS2.ZIP_NO) AS ZIP_NO
, CONVERT(NVARCHAR(10), P.LAST_EDIT_DATETIME, 121) AS ESTIMATE_DATE , COALESCE(NULLIF(SS2.DISP_ADDRESS, ''), SS2.ADDRESS) AS ADDRESS
, PI.ESTIMATE_TYPE , COALESCE(NULLIF(SS2.DISP_TEL, ''), SS2.TEL) AS TEL
, PI.ESTIMATE_OPTION , COALESCE(NULLIF(SS2.DISP_FAX, ''), SS2.FAX) AS FAX
, PI.PKG_ASP </if>
, PI.REMARKS <if test='saleStoreId != null and saleStoreId == "T01"'>
, PI.CREATE_USER , ISNULL((SELECT
, O.SALE_STORE_ID SUBSTRING(MCL.REF_CHR3, CHARINDEX('〒', MCL.REF_CHR3) + 1,
, (SELECT SS.BUSINESS_CHARGER_CD FROM M_SALES_STORE SS WHERE SS.SALE_STORE_ID = O.SALE_STORE_ID ) AS BUSINESS_CHARGER_CD CHARINDEX(')', MCL.REF_CHR3, CHARINDEX('〒', MCL.REF_CHR3)) - CHARINDEX('〒', MCL.REF_CHR3) - 1)
, O.OBJECT_NAME FROM M_COMM_L MCL
, O.OBJECT_NAME_OMIT WHERE MCL.HEAD_CD = '103200'
, (SELECT SALE_STORE_ID FROM M_USER WHERE USER_ID = OI.CREATE_USER) AS CREATE_SALE_STORE_ID AND MCL.CODE = T.BUSINESS_TEAM_CD), '') AS ZIP_NO
, ISNULL(MP.PREF_NAME, '') AS PREF_NAME , ISNULL((SELECT
, ISNULL(MPA.AREA_NAME, '') AS AREA_NAME LTRIM(SUBSTRING(MCL.REF_CHR3,
, ISNULL(C1.CODE_NM, '') AS STANDARD_WIND_SPEED_NAME CHARINDEX(')', MCL.REF_CHR3, CHARINDEX('〒', MCL.REF_CHR3)) + 1,
FROM T_PLAN P WITH (NOLOCK) LEN(MCL.REF_CHR3)))
INNER JOIN T_PLAN_INFO PI WITH (NOLOCK) FROM M_COMM_L MCL
ON P.OBJECT_NO = PI.OBJECT_NO WHERE MCL.HEAD_CD = '103200'
AND P.PLAN_NO = PI.PLAN_NO AND MCL.CODE = T.BUSINESS_TEAM_CD), '') AS ADDRESS
INNER JOIN T_OBJECT O WITH (NOLOCK) , ISNULL((SELECT MCL.REF_CHR4
ON P.OBJECT_NO = O.OBJECT_NO FROM M_COMM_L MCL
INNER JOIN T_OBJECT_INFO OI WITH (NOLOCK) WHERE MCL.HEAD_CD = '103200'
ON O.OBJECT_NO = OI.OBJECT_NO AND MCL.CODE = T.BUSINESS_TEAM_CD), '') AS TEL
LEFT OUTER JOIN T_SIMULATION_PREFECTURE MP WITH (NOLOCK) , ISNULL((SELECT MCL.REF_CHR5
ON O.PREF_ID = MP.PREF_ID FROM M_COMM_L MCL
LEFT OUTER JOIN T_SIMULATION_AREA MPA WITH (NOLOCK) WHERE MCL.HEAD_CD = '103200'
ON O.PREF_ID = MPA.PREF_ID AND MCL.CODE = T.BUSINESS_TEAM_CD), '') AS FAX
AND OI.AREA_ID = MPA.AREA_ID </if>
AND MPA.DEL_FLG = 0 , SSI2.BIZ_NO
LEFT OUTER JOIN M_COMM_L C1 WITH (NOLOCK) FROM
ON C1.HEAD_CD = '202000' (
AND P.STANDARD_WIND_SPEED_ID = C1.CODE SELECT
WHERE P.OBJECT_NO = #{objectNo} P.OBJECT_NO
AND P.PLAN_NO = #{planNo} , P.PLAN_NO
) T , CONVERT(VARCHAR(10), P.DRAWING_ESTIMATE_CREATE_DATE, 121) AS DRAWING_ESTIMATE_CREATE_DATE
LEFT OUTER JOIN M_SALES_STORE SS1 WITH (NOLOCK) , P.ESTIMATE_VALIDITY_TERM
, P.SNOWFALL
, CONVERT(NVARCHAR(10), P.LAST_EDIT_DATETIME, 121) AS ESTIMATE_DATE
, PI.ESTIMATE_TYPE
, PI.ESTIMATE_OPTION
, PI.PKG_ASP
, PI.REMARKS
, O.SALE_STORE_ID
, O.OBJECT_NAME
, O.OBJECT_NAME_OMIT
, (SELECT SALE_STORE_ID FROM M_USER WHERE USER_ID = OI.CREATE_USER) AS CREATE_SALE_STORE_ID
<if test='saleStoreId != null and saleStoreId == "T01"'>
, (SELECT BC.BUSINESS_TEAM_CD
FROM M_SALES_STORE SS WITH (NOLOCK)
INNER JOIN M_BUSINESS_CHARGER BC WITH (NOLOCK)
ON SS.BUSINESS_CHARGER_CD = BC.BUSINESS_CHARGER_CD
WHERE SS.SALE_STORE_ID = O.SALE_STORE_ID
) AS BUSINESS_TEAM_CD
</if>
, ISNULL(MP.PREF_NAME, '') AS PREF_NAME
, ISNULL(MPA.AREA_NAME, '') AS AREA_NAME
, ISNULL(C1.CODE_NM, '') AS STANDARD_WIND_SPEED_NAME
FROM T_PLAN P WITH (NOLOCK)
INNER JOIN T_PLAN_INFO PI WITH (NOLOCK)
ON P.OBJECT_NO = PI.OBJECT_NO
AND P.PLAN_NO = PI.PLAN_NO
INNER JOIN T_OBJECT O WITH (NOLOCK)
ON P.OBJECT_NO = O.OBJECT_NO
INNER JOIN T_OBJECT_INFO OI WITH (NOLOCK)
ON O.OBJECT_NO = OI.OBJECT_NO
LEFT OUTER JOIN T_SIMULATION_PREFECTURE MP WITH (NOLOCK)
ON O.PREF_ID = MP.PREF_ID
LEFT OUTER JOIN T_SIMULATION_AREA MPA WITH (NOLOCK)
ON O.PREF_ID = MPA.PREF_ID
AND OI.AREA_ID = MPA.AREA_ID
AND MPA.DEL_FLG = 0
LEFT OUTER JOIN M_COMM_L C1 WITH (NOLOCK)
ON C1.HEAD_CD = '202000'
AND P.STANDARD_WIND_SPEED_ID = C1.CODE
WHERE P.OBJECT_NO = #{objectNo}
AND P.PLAN_NO = #{planNo}
) T
LEFT OUTER JOIN M_SALES_STORE SS1 WITH (NOLOCK)
ON T.SALE_STORE_ID = SS1.SALE_STORE_ID ON T.SALE_STORE_ID = SS1.SALE_STORE_ID
LEFT OUTER JOIN M_SALES_STORE SS2 WITH (NOLOCK) LEFT OUTER JOIN M_SALES_STORE SS2 WITH (NOLOCK)
ON T.CREATE_SALE_STORE_ID = SS2.SALE_STORE_ID ON T.CREATE_SALE_STORE_ID = SS2.SALE_STORE_ID
LEFT OUTER JOIN M_SALES_STORE_INFO SSI2 WITH (NOLOCK) LEFT OUTER JOIN M_SALES_STORE_INFO SSI2 WITH (NOLOCK)
ON T.CREATE_SALE_STORE_ID = SSI2.SALE_STORE_ID ON T.CREATE_SALE_STORE_ID = SSI2.SALE_STORE_ID
)Z
LEFT OUTER JOIN M_SALES_STORE SS3 WITH (NOLOCK)
ON Z.FIRST_AGENT_ID = SS3.SALE_STORE_ID
</select> </select>
<select id="selectEstimateApiFailList" resultType="com.interplug.qcast.biz.estimate.dto.EstimateSendResponse"> <select id="selectEstimateApiFailList" resultType="com.interplug.qcast.biz.estimate.dto.EstimateSendResponse">