Compare commits

...

10 Commits

Author SHA1 Message Date
f1f7785062 배치 URL 추가 2024-11-08 16:08:54 +09:00
d19caebb5a
Merge Q-CAST-III-MR-243: 아이템 동기화 배치 작업 2024-11-08 06:29:43 +00:00
DESKTOP-6ARNG1Q\dlsgk
3a2b958335 store 배치 최종본 커밋 2024-11-08 15:28:05 +09:00
10dcce28c1 아이템 동기화 배치 작업 2024-11-08 15:27:46 +09:00
DESKTOP-6ARNG1Q\dlsgk
3088641e84 배치주석제거 2024-11-08 15:13:13 +09:00
DESKTOP-6ARNG1Q\dlsgk
ae88b2a95a Revert "배치 주석 제거"
This reverts commit b3ff0c308aec1c4a22aad3ff65de900409d9e4cf.
2024-11-08 15:11:54 +09:00
DESKTOP-6ARNG1Q\dlsgk
b3ff0c308a 배치 주석 제거 2024-11-08 15:07:17 +09:00
박 꽃송이
026e66dd5b
Merge Q-CAST-III-MR-240: store 배치 수정 2024-11-08 05:46:14 +00:00
DESKTOP-6ARNG1Q\dlsgk
d3bd562d80 store 배치 수정 2024-11-08 14:45:29 +09:00
2142442aa3 견적서 API 수정(아이템 특이사항 별도 저장 기능 추가) 2024-11-08 13:44:54 +09:00
19 changed files with 668 additions and 152 deletions

View File

@ -98,8 +98,8 @@ public class JobLauncherController {
* @throws JobParametersInvalidException * @throws JobParametersInvalidException
* @throws JobRestartException * @throws JobRestartException
*/ */
// @Scheduled(cron = "*/30 * * * * *") // @Scheduled(cron = "*/5 * * * * *")
@Scheduled(cron = "0 0 0 * * *") @Scheduled(cron = "0 55 23 * * *")
public String storeAdditionalInfoJob() public String storeAdditionalInfoJob()
throws JobInstanceAlreadyCompleteException, throws JobInstanceAlreadyCompleteException,
JobExecutionAlreadyRunningException, JobExecutionAlreadyRunningException,
@ -111,6 +111,35 @@ public class JobLauncherController {
if (job == null) { if (job == null) {
return "Job " + jobName + " not found"; return "Job " + jobName + " not found";
} }
JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
jobLauncher.run(job, jobParameters);
return "OK";
}
/**
* 아이템 동기화 배치
*
* @return
* @throws JobInstanceAlreadyCompleteException
* @throws JobExecutionAlreadyRunningException
* @throws JobParametersInvalidException
* @throws JobRestartException
*/
@Scheduled(cron = "0 0 0 * * *")
public String materialJob()
throws JobInstanceAlreadyCompleteException,
JobExecutionAlreadyRunningException,
JobParametersInvalidException,
JobRestartException {
String jobName = "materialJob";
Job job = jobs.get(jobName);
if (job == null) {
return "Job " + jobName + " not found";
}
JobParameters jobParameters = JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); new JobParametersBuilder().addDate("time", new Date()).toJobParameters();

View File

@ -0,0 +1,87 @@
package com.interplug.qcast.batch.master;
import com.fasterxml.jackson.core.type.TypeReference;
import com.interplug.qcast.biz.displayItem.DisplayItemService;
import com.interplug.qcast.biz.displayItem.dto.ItemSyncRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse;
import com.interplug.qcast.util.InterfaceQsp;
import java.util.Collections;
import java.util.List;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.transaction.PlatformTransactionManager;
/** chunk 방식의 Job을 생성하는 Configuration */
@Configuration
public class MaterialConfiguration implements JobExecutionListener {
private final DisplayItemService displayItemService;
private final InterfaceQsp interfaceQsp;
List<ItemSyncResponse> itemSyncList;
@Value("${qsp.master-material-batch-url}")
private String qspInterfaceUrl;
public MaterialConfiguration(DisplayItemService displayItemService, InterfaceQsp interfaceQsp) {
this.displayItemService = displayItemService;
this.interfaceQsp = interfaceQsp;
}
@Bean
public Job materialJob(JobRepository jobRepository, Step materialStep) {
return new JobBuilder("materialJob", jobRepository).start(materialStep).build();
}
@Bean
public Step materialStep(
JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception {
return new StepBuilder("materialStep", jobRepository)
.<ItemSyncResponse, ItemSyncResponse>chunk(100, transactionManager)
.reader(materialReader())
.processor(materialProcessor())
.writer(materialWriter())
.build();
}
@Bean
@StepScope
public ItemReader<ItemSyncResponse> materialReader() throws Exception {
ItemSyncRequest itemSyncRequest = new ItemSyncRequest();
itemSyncRequest.setAllYn("N");
this.itemSyncList =
interfaceQsp.callApiData(
HttpMethod.GET,
qspInterfaceUrl,
itemSyncRequest,
new TypeReference<List<ItemSyncResponse>>() {});
return (itemSyncList != null)
? new ListItemReader<>(itemSyncList)
: new ListItemReader<>(Collections.emptyList());
}
@Bean
public ItemProcessor<ItemSyncResponse, ItemSyncResponse> materialProcessor() {
return item -> item;
}
@Bean
public ItemWriter<ItemSyncResponse> materialWriter() {
return items -> {
displayItemService.setItemSyncSave((List<ItemSyncResponse>) items.getItems());
};
}
}

View File

@ -1,24 +1,21 @@
package com.interplug.qcast.batch.master; package com.interplug.qcast.batch.master;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.interplug.qcast.biz.storeFavorite.StoreFavoriteService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.interplug.qcast.biz.displayItem.DisplayItemMapper;
import com.interplug.qcast.biz.storeFavorite.StoreFavoriteMapper;
import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest; import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest;
import com.interplug.qcast.biz.user.UserMapper; import com.interplug.qcast.biz.user.UserService;
import com.interplug.qcast.biz.user.dto.StoreRequest; import com.interplug.qcast.biz.user.dto.StoreRequest;
import com.interplug.qcast.biz.user.dto.StoreSyncResponse; import com.interplug.qcast.biz.user.dto.StoreSyncResponse;
import com.interplug.qcast.biz.user.dto.SyncResponse;
import com.interplug.qcast.biz.user.dto.UserRequest; import com.interplug.qcast.biz.user.dto.UserRequest;
import com.interplug.qcast.util.InterfaceQsp; import com.interplug.qcast.util.InterfaceQsp;
import jakarta.annotation.PostConstruct;
import java.util.Collections; import java.util.Collections;
import org.springframework.batch.core.Job; import java.util.List;
import org.springframework.batch.core.Step; import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader; import org.springframework.batch.item.support.ListItemReader;
@ -28,38 +25,37 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
/** chunk 방식의 Job을 생성하는 Configuration */
@Configuration @Configuration
public class StoreJobConfiguration { @Slf4j
public class StoreJobConfiguration implements JobExecutionListener {
private final InterfaceQsp interfaceQsp; private final InterfaceQsp interfaceQsp;
private final UserMapper userMapper; private final UserService userService;
private final StoreFavoriteMapper storeFavoriteMapper; private final StoreFavoriteService storeFavService;
private final DisplayItemMapper displayItemMapper;
@Value("${qsp.url}")
private String qspUrl;
@Value("${qsp.master-store-batch-url}") @Value("${qsp.master-store-batch-url}")
private String qspMasterStoreBatchUrl; private String qspMasterStoreBatchUrl;
private StoreSyncResponse storeSyncResponse;
public StoreJobConfiguration( public StoreJobConfiguration(
InterfaceQsp interfaceQsp, InterfaceQsp interfaceQsp, UserService userService, StoreFavoriteService storeFavService) {
UserMapper userMapper,
StoreFavoriteMapper storeFavoriteMapper,
DisplayItemMapper displayItemMapper) {
this.interfaceQsp = interfaceQsp; this.interfaceQsp = interfaceQsp;
this.userMapper = userMapper; this.userService = userService;
this.storeFavoriteMapper = storeFavoriteMapper; this.storeFavService = storeFavService;
this.displayItemMapper = displayItemMapper;
} }
private StoreSyncResponse storeSyncResponse; // 데이터를 저장할 필드 @Override
public void beforeJob(JobExecution jobExecution) {
@PostConstruct log.info("Job 시작: 초기화 메서드 호출 중...");
public void init() throws Exception { try {
// 애플리케이션 시작 fetchData를 번만 호출하여 데이터 로드 this.storeSyncResponse =
this.storeSyncResponse = fetchData(); interfaceQsp.callApiData(
HttpMethod.GET, qspMasterStoreBatchUrl, null, StoreSyncResponse.class);
log.info("API 호출 완료, 항목 수: {}", this.storeSyncResponse.getStoreList().size());
} catch (Exception e) {
log.error("storeSyncResponse 갱신 중 오류: {}", e.getMessage());
}
} }
@Bean @Bean
@ -69,132 +65,123 @@ public class StoreJobConfiguration {
.start(storeStep) .start(storeStep)
.next(userStep) .next(userStep)
.next(favoriteStep) .next(favoriteStep)
.listener(this)
.build();
}
private <T> Step buildStep(
String stepName,
JobRepository jobRepository,
PlatformTransactionManager transactionManager,
ItemReader<T> reader,
ItemWriter<T> writer) {
return new StepBuilder(stepName, jobRepository)
.<T, T>chunk(10, transactionManager)
.reader(reader)
.writer(writer)
.build(); .build();
} }
@Bean @Bean
public Step storeStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) public Step storeStep(
throws Exception { JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("storeStep", jobRepository) return buildStep(
.<StoreRequest, StoreRequest>chunk(10, transactionManager) "storeStep",
.reader(storeListReader()) jobRepository,
.processor(storeProcessor()) transactionManager,
.writer(storeWriter()) storeListReader(),
.build(); createWriter(
(items) -> {
try {
log.debug("Store batch processing {} items", items.size());
userService.setStoreBatch(items);
log.debug("Successfully processed store batch");
} catch (Exception e) {
log.error("Error processing store batch: {}", e.getMessage(), e);
throw new RuntimeException("Failed to process store batch", e);
}
},
"store"));
} }
@Bean @Bean
public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) public Step userStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
throws Exception { return buildStep(
return new StepBuilder("userStep", jobRepository) "userStep",
.<UserRequest, UserRequest>chunk(10, transactionManager) jobRepository,
.reader(userListReader()) transactionManager,
.processor(userProcessor()) userListReader(),
.writer(userWriter()) createWriter(
.build(); (items) -> {
try {
log.debug("User batch processing {} items", items.size());
userService.setUserBatch(items);
log.debug("Successfully processed user batch");
} catch (Exception e) {
log.error("Error processing user batch: {}", e.getMessage(), e);
throw new RuntimeException("Failed to process user batch", e);
}
},
"user"));
} }
@Bean @Bean
public Step favoriteStep( public Step favoriteStep(
JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("favoriteStep", jobRepository) return buildStep(
.<StoreFavoriteRequest, StoreFavoriteRequest>chunk(10, transactionManager) "favoriteStep",
.reader(storeFavListReader()) jobRepository,
.processor(favoriteProcessor()) transactionManager,
.writer(favoriteWriter()) storeFavListReader(),
.build(); createWriter(
(items) -> {
try {
log.debug("Favorite batch processing {} items", items.size());
storeFavService.setStoreFavoriteBatch(items);
log.debug("Successfully processed favorite batch");
} catch (Exception e) {
log.error("Error processing favorite batch: {}", e.getMessage(), e);
throw new RuntimeException("Failed to process favorite batch", e);
}
},
"favorite"));
} }
private StoreSyncResponse fetchData() throws Exception { private <T> ListItemReader<T> createReader(List<T> items, String readerName) {
log.info("{}Reader 호출됨...", readerName);
// 데이터 읽기 return new ListItemReader<>(items != null ? items : Collections.emptyList());
SyncResponse syncResponse = new SyncResponse();
StoreSyncResponse storeSyncResponse = new StoreSyncResponse();
String strResponse =
interfaceQsp.callApi(HttpMethod.GET, qspUrl + qspMasterStoreBatchUrl, null);
if (!"".equals(strResponse)) {
ObjectMapper om =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
syncResponse = om.readValue(strResponse, SyncResponse.class);
// 'data' 필드를 직접 사용하여 BatchResponse로 변환
if (syncResponse.getData() != null) {
String dataJson = om.writeValueAsString(syncResponse.getData());
// data를 JSON 문자열로 변환
storeSyncResponse = om.readValue(dataJson, StoreSyncResponse.class);
}
}
return storeSyncResponse;
} }
@Bean @Bean
public ItemReader<StoreRequest> storeListReader() throws Exception { @StepScope
if (storeSyncResponse.getStoreList() == null) { public ListItemReader<StoreRequest> storeListReader() {
storeSyncResponse.setStoreList(Collections.emptyList()); return createReader(
} storeSyncResponse != null ? storeSyncResponse.getStoreList() : null, "store");
return new ListItemReader<>(storeSyncResponse.getStoreList());
} }
@Bean @Bean
public ItemReader<UserRequest> userListReader() throws Exception { @StepScope
if (storeSyncResponse.getUserList() == null) { public ListItemReader<UserRequest> userListReader() {
storeSyncResponse.setUserList(Collections.emptyList()); return createReader(storeSyncResponse != null ? storeSyncResponse.getUserList() : null, "user");
}
return new ListItemReader<>(storeSyncResponse.getUserList());
} }
@Bean @Bean
public ItemReader<StoreFavoriteRequest> storeFavListReader() throws Exception { @StepScope
if (storeSyncResponse.getStoreFavList() == null) { public ListItemReader<StoreFavoriteRequest> storeFavListReader() {
storeSyncResponse.setStoreFavList(Collections.emptyList()); return createReader(
} storeSyncResponse != null ? storeSyncResponse.getStoreFavList() : null, "storeFav");
return new ListItemReader<>(storeSyncResponse.getStoreFavList());
} }
@Bean private <T> ItemWriter<T> createWriter(Consumer<List<T>> processor, String writerName) {
public ItemProcessor<StoreRequest, StoreRequest> storeProcessor() { return items -> {
return item -> { try {
userMapper.setStoreSave(item); // 판매정 정보 동기화 List<T> itemList = (List<T>) items.getItems();
userMapper.setStoreSapCdSave(item); // 판매점 custCd 동기화 processor.accept(itemList);
userMapper.setStoreNorthModuleSave(item); log.info("{}Writer: {} items 처리 완료", writerName, items.size());
System.out.println("Processing store: " + item); } catch (Exception e) {
return item; log.error("{}Writer 오류: {}", writerName, e.getMessage());
throw e;
}
}; };
} }
@Bean
public ItemProcessor<UserRequest, UserRequest> userProcessor() {
return item -> {
userMapper.setUserSave(item);
System.out.println("Processing user: " + item);
return item;
};
}
@Bean
public ItemProcessor<StoreFavoriteRequest, StoreFavoriteRequest> favoriteProcessor() {
return item -> {
storeFavoriteMapper.setStoreFavoriteSave(item);
System.out.println("Processing favorite: " + item);
return item;
};
}
@Bean
public ItemWriter<StoreRequest> storeWriter() {
return items -> items.forEach(item -> System.out.println("Writing store: " + item));
}
@Bean
public ItemWriter<UserRequest> userWriter() {
return items -> items.forEach(item -> System.out.println("Writing user: " + item));
}
@Bean
public ItemWriter<StoreFavoriteRequest> favoriteWriter() {
return items -> items.forEach(item -> System.out.println("Writing favorite: " + item));
}
} }

View File

@ -2,6 +2,7 @@ package com.interplug.qcast.biz.displayItem;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest; import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemResponse; import com.interplug.qcast.biz.displayItem.dto.ItemResponse;
import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse;
import java.util.List; import java.util.List;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -14,4 +15,13 @@ public interface DisplayItemMapper {
List<ItemResponse> getItemList(@Param("saleStoreId") String saleStoreId); List<ItemResponse> getItemList(@Param("saleStoreId") String saleStoreId);
ItemResponse getItemDetail(@Param("itemId") String itemId); ItemResponse getItemDetail(@Param("itemId") String itemId);
/**
* 아이템 정보 동기화
*
* @param itemInfoSync 아이템 정보
* @return
* @throws Exception
*/
int setItemSyncSave(ItemSyncResponse itemInfoSync);
} }

View File

@ -2,6 +2,7 @@ package com.interplug.qcast.biz.displayItem;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest; import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemResponse; import com.interplug.qcast.biz.displayItem.dto.ItemResponse;
import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse;
import com.interplug.qcast.biz.estimate.EstimateMapper; import com.interplug.qcast.biz.estimate.EstimateMapper;
import com.interplug.qcast.biz.estimate.dto.NoteRequest; import com.interplug.qcast.biz.estimate.dto.NoteRequest;
import com.interplug.qcast.biz.estimate.dto.NoteResponse; import com.interplug.qcast.biz.estimate.dto.NoteResponse;
@ -70,4 +71,19 @@ public class DisplayItemService {
return itemResponse; return itemResponse;
} }
/**
* 아이템 정보 동기화
*
* @param itemSyncList 아이템 목록
* @return
* @throws Exception
*/
public int setItemSyncSave(List<ItemSyncResponse> itemSyncList) throws Exception {
int cnt = 0;
for (ItemSyncResponse itemSyncData : itemSyncList) {
displayItemMapper.setItemSyncSave(itemSyncData);
}
return cnt;
}
} }

View File

@ -0,0 +1,13 @@
package com.interplug.qcast.biz.displayItem.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 아이템 동기화 Request
*/
@Data
public class ItemSyncRequest {
@Schema(description = "All Material Master Yn")
private String allYn;
}

View File

@ -0,0 +1,141 @@
package com.interplug.qcast.biz.displayItem.dto;
import com.interplug.qcast.util.DefaultResponse;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/** 아이템 동기화 Response */
@Data
public class ItemSyncResponse extends DefaultResponse {
@Schema(description = "Material Number")
String itemId;
@Schema(description = "Customer Product Name")
String itemName;
@Schema(description = "Basic Material")
String itemNo;
@Schema(description = "Basic Material")
String goodsNo;
@Schema(description = "Customer Product ID")
String changeItemId;
@Schema(description = "Customer Unit")
String unit;
@Schema(description = "Size_Dimensions")
String specification;
@Schema(description = "Module, BOS Price")
String fixedPrice;
@Schema(description = "Power Class")
String pnowW;
@Schema(description = "Qcast Material Group Code")
String itemGroup;
@Schema(description = "Panel Order Flg")
String panelOrderFlg;
@Schema(description = "Stand Order Flg")
String standOrderFlg;
@Schema(description = "Module Flg")
String moduleFlg;
@Schema(description = "Power Com Flg")
String powerComFlg;
@Schema(description = "Option Flg")
String optionFlg;
@Schema(description = "Qcast Remark")
String remarks;
@Schema(description = "Disp Order")
String dispOrder;
@Schema(description = "Del Flg")
String delFlg;
@Schema(description = "Limited Release Flg")
String limitedReleaseFlg;
@Schema(description = "Yanegi Flg")
String yanegiFlg;
@Schema(description = "Hory Flg")
String horyFlg;
@Schema(description = "Takasima Flg")
String takasimaFlg;
@Schema(description = "DSwat Flg")
String dSwatFlg;
@Schema(description = "PowerCom Have Flg")
String powerComHaveFlg;
@Schema(description = "PowerCom Non Flg")
String powerComNonFlg;
@Schema(description = "ConnectBox Have Flg")
String connectBoxHaveFlg;
@Schema(description = "ConnectBox Non Flg")
String connectBoxNonFlg;
@Schema(description = "Metal Fitting Detail Flg")
String metalFittingDetailFlg;
@Schema(description = "Metal Fitting All Flg")
String metalFittingAllFlg;
@Schema(description = "Stand Flg")
String standFlg;
@Schema(description = "Secure Target Flg")
String secureTargetFlg;
@Schema(description = "Display Container Flg")
String dispContainerFlg;
@Schema(description = "Panel Layout Design Display Flg")
String panelLayoutDesignDispFlg;
@Schema(description = "Stand Display Flg")
String standDispFlg;
@Schema(description = "Gross Weight")
String grossWt;
@Schema(description = "End Of Sales Flg")
String endOfSalesFlg;
@Schema(description = "Guarantee Material Group Code")
String guarItemGroup;
@Schema(description = "File Upload Flg")
String fileUploadFlg;
@Schema(description = "Salt-affected Flg")
String saltAffectedFlg;
@Schema(description = "Guarantee Except Flg")
String guarExceptFlg;
@Schema(description = "Cold-zone Flg")
String coldZoneFlg;
@Schema(description = "PKG Material Flg")
String pkgMaterialFlg;
@Schema(description = "Status Code(A, D)")
String statCd;
@Schema(description = "Delete Yn(Y, N)")
String delYn;
}

View File

@ -326,9 +326,9 @@ public class EstimateService {
itemRequest.setSpecification(itemResponse.getPnowW()); itemRequest.setSpecification(itemResponse.getPnowW());
itemRequest.setUnitPrice(itemResponse.getSalePrice()); itemRequest.setUnitPrice(itemResponse.getSalePrice());
itemRequest.setSalePrice(itemResponse.getSalePrice()); itemRequest.setSalePrice(itemResponse.getSalePrice());
itemRequest.setFileUploadFlg(itemResponse.getFileUploadFlg());
itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg()); itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
itemRequest.setItemGroup(itemResponse.getItemGroup()); itemRequest.setItemGroup(itemResponse.getItemGroup());
break; break;
} }
} }
@ -378,11 +378,24 @@ public class EstimateService {
} }
} }
for (NoteResponse noteResponse : noteItemList) { for (NoteResponse noteResponse : noteItemList) {
if (estimateOptions.indexOf(noteResponse.getCode()) < 0) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : ""; estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += noteResponse.getCode(); estimateOptions += noteResponse.getCode();
} }
}
estimateRequest.setEstimateOption(estimateOptions); estimateRequest.setEstimateOption(estimateOptions);
// 아이템별 특이사항 코드 체크
for (ItemRequest itemRequest : itemList) {
String specialNoteCd = "";
for (NoteResponse noteResponse : noteItemList) {
if (itemRequest.getItemId().equals(noteResponse.getItemId())) {
specialNoteCd += !StringUtils.isEmpty(specialNoteCd) ? splitStr : "";
specialNoteCd += noteResponse.getCode();
}
}
itemRequest.setSpecialNoteCd(specialNoteCd);
}
} }
// 아이템 목록 필수 체크 // 아이템 목록 필수 체크

View File

@ -186,6 +186,12 @@ public class EstimateResponse {
@Schema(description = "판매점 레벨") @Schema(description = "판매점 레벨")
private String saleStoreLevel; private String saleStoreLevel;
@Schema(description = "1차점 판매점명")
private String firstSaleStoreName;
@Schema(description = "하위 판매점명")
private String agencySaleStoreName;
// 판매점 정보 // 판매점 정보
@Schema(description = "고객 판매점명") @Schema(description = "고객 판매점명")
private String custSaleStoreName; private String custSaleStoreName;

View File

@ -50,9 +50,15 @@ public class ItemRequest {
@Schema(description = "단가") @Schema(description = "단가")
private String salePrice; private String salePrice;
@Schema(description = "파일첨부 필수여부")
private String fileUploadFlg;
@Schema(description = "PKG 제외상품 여부") @Schema(description = "PKG 제외상품 여부")
private String pkgMaterialFlg; private String pkgMaterialFlg;
@Schema(description = "아이템 특이사항 코드")
private String specialNoteCd;
@Schema(description = "아이템 변경 여부") @Schema(description = "아이템 변경 여부")
private String itemChangeFlg; private String itemChangeFlg;

View File

@ -47,9 +47,15 @@ public class ItemResponse {
@Schema(description = "합산") @Schema(description = "합산")
private String saleTotPrice; private String saleTotPrice;
@Schema(description = "파일첨부 필수여부")
private String fileUploadFlg;
@Schema(description = "PKG 제외상품 여부") @Schema(description = "PKG 제외상품 여부")
private String pkgMaterialFlg; private String pkgMaterialFlg;
@Schema(description = "아이템 특이사항 코드")
private String specialNoteCd;
@Schema(description = "아이템 변경 여부") @Schema(description = "아이템 변경 여부")
private String itemChangeFlg; private String itemChangeFlg;
@ -59,9 +65,6 @@ public class ItemResponse {
@Schema(description = "아이템 그룹코드") @Schema(description = "아이템 그룹코드")
private String itemGroup; private String itemGroup;
@Schema(description = "파일첨부 필수여부")
private String fileUploadFlg;
@Schema(description = "모듈여부") @Schema(description = "모듈여부")
private String moduleFlg; private String moduleFlg;
} }

View File

@ -11,6 +11,9 @@ public class NoteResponse {
@Schema(description = "공통코드명") @Schema(description = "공통코드명")
private String codeNm; private String codeNm;
@Schema(description = "아이템 ID")
private String itemId;
@Schema(description = "견적특이사항") @Schema(description = "견적특이사항")
private String remarks; private String remarks;
} }

View File

@ -8,13 +8,16 @@ import com.interplug.qcast.config.Exception.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp; import com.interplug.qcast.util.InterfaceQsp;
import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
@Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class StoreFavoriteService { public class StoreFavoriteService {
@ -77,4 +80,15 @@ public class StoreFavoriteService {
} }
return response; return response;
} }
public void setStoreFavoriteBatch(List<StoreFavoriteRequest> storeFavList) throws Exception {
// 즐겨찾기 동기화
for (StoreFavoriteRequest storeFavoriteRequest : storeFavList) {
try {
storeFavoriteMapper.setStoreFavoriteSave(storeFavoriteRequest);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
} }

View File

@ -4,8 +4,10 @@ import com.interplug.qcast.biz.user.dto.StoreRequest;
import com.interplug.qcast.biz.user.dto.UserRequest; import com.interplug.qcast.biz.user.dto.UserRequest;
import java.util.List; import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class UserService { public class UserService {
@ -52,4 +54,32 @@ public class UserService {
public int setStoreSapCdSave(StoreRequest storeReq) throws Exception { public int setStoreSapCdSave(StoreRequest storeReq) throws Exception {
return userMapper.setStoreSapCdSave(storeReq); return userMapper.setStoreSapCdSave(storeReq);
} }
/**
* @param storeList
* @throws Exception
*/
public void setStoreBatch(List<StoreRequest> storeList) throws Exception {
// 판매점 동기화
for (StoreRequest storeRequest : storeList) {
try {
userMapper.setStoreSave(storeRequest);
userMapper.setStoreSapCdSave(storeRequest);
userMapper.setStoreNorthModuleSave(storeRequest);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
public void setUserBatch(List<UserRequest> userList) throws Exception {
// 사용자 동기화
for (UserRequest userRequest : userList) {
try {
userMapper.setUserSave(userRequest);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
} }

View File

@ -39,6 +39,8 @@ spring:
qsp: qsp:
url: http://1.248.227.176:8120 url: http://1.248.227.176:8120
master-store-batch-url: /api/master/storeAdditionalInfo master-store-batch-url: /api/master/storeAdditionalInfo
master-material-batch-url: /api/master/materialList
master-bom-batch-url: /api/master/bomList
simulation-guide-info-url: /api/simulation/guideInfo simulation-guide-info-url: /api/simulation/guideInfo
aes256.key: jpqcellQ123456!! aes256.key: jpqcellQ123456!!
auto.login.aes256.key: _autoL!! auto.login.aes256.key: _autoL!!

View File

@ -39,6 +39,8 @@ spring:
qsp: qsp:
url: http://1.248.227.176:8120 url: http://1.248.227.176:8120
master-store-batch-url: /api/master/storeAdditionalInfo master-store-batch-url: /api/master/storeAdditionalInfo
master-material-batch-url: /api/master/materialList
master-bom-batch-url: /api/master/bomList
simulation-guide-info-url: /api/simulation/guideInfo simulation-guide-info-url: /api/simulation/guideInfo
aes256.key: jpqcellQ123456!! aes256.key: jpqcellQ123456!!
auto.login.aes256.key: _autoL!! auto.login.aes256.key: _autoL!!

View File

@ -39,6 +39,8 @@ spring:
qsp: qsp:
url: http://jp.qsalesplatform.com url: http://jp.qsalesplatform.com
master-store-batch-url: /api/master/storeAdditionalInfo master-store-batch-url: /api/master/storeAdditionalInfo
master-material-batch-url: /api/master/materialList
master-bom-batch-url: /api/master/bomList
simulation-guide-info-url: /api/simulation/guideInfo simulation-guide-info-url: /api/simulation/guideInfo
aes256.key: jpqcellQ123456!! aes256.key: jpqcellQ123456!!
auto.login.aes256.key: _autoL!! auto.login.aes256.key: _autoL!!

View File

@ -20,7 +20,7 @@
UPDATE SET UPDATE SET
START_DATE = #{startDate} START_DATE = #{startDate}
, END_DATE = #{endDate} , END_DATE = #{endDate}
, DEL_FLG = #{delFlg} , DEL_FLG = CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END
, LAST_EDIT_DATETIME = #{lastEditDatetime} , LAST_EDIT_DATETIME = #{lastEditDatetime}
WHEN NOT MATCHED THEN WHEN NOT MATCHED THEN
INSERT ( INSERT (
@ -38,7 +38,7 @@
, #{itemId} , #{itemId}
, #{startDate} , #{startDate}
, #{endDate} , #{endDate}
, #{delFlg} , CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END
, #{registDatetime} , #{registDatetime}
, #{lastEditDatetime} , #{lastEditDatetime}
); );
@ -102,4 +102,142 @@
AND MI.ITEM_ID = #{itemId} AND MI.ITEM_ID = #{itemId}
</select> </select>
<insert id="setItemSyncSave" parameterType="com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse" >
/* sqlid : com.interplug.qcast.displayItem.setItemSyncSave */
MERGE M_ITEM AS A
USING
( SELECT #{itemId} AS ITEM_ID
) AS D
ON (
A.ITEM_ID = D.ITEM_ID
)
WHEN MATCHED THEN
UPDATE SET
ITEM_NAME = #{itemName}
, ITEM_NO = #{itemNo}
, GOODS_NO = #{goodsNo}
, UNIT = #{unit}
, SPECIFICATION = #{specification}
, FIXED_PRICE = #{fixedPrice}
, PNOW_W = #{pnowW}
, ITEM_GROUP = #{itemGroup}
, PANEL_ORDER_FLG = CASE WHEN #{panelOrderFlg} = 'FALSE' THEN 0 ELSE 1 END
, STAND_ORDER_FLG = CASE WHEN #{standOrderFlg} = 'FALSE' THEN 0 ELSE 1 END
, MODULE_FLG = CASE WHEN #{moduleFlg} = 'FALSE' THEN 0 ELSE 1 END
, POWER_COM_FLG = CASE WHEN #{powerComFlg} = 'FALSE' THEN 0 ELSE 1 END
, OPTION_FLG = CASE WHEN #{optionFlg} = 'FALSE' THEN 0 ELSE 1 END
, REMARKS = #{remarks}
, DISP_ORDER = #{dispOrder}
, DEL_FLG = CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END
, LIMITED_RELEASE_FLG = CASE WHEN #{limitedReleaseFlg} = 'FALSE' THEN 0 ELSE 1 END
, YANEGI_FLG = CASE WHEN #{yanegiFlg} = 'FALSE' THEN 0 ELSE 1 END
, HORY_FLG = CASE WHEN #{horyFlg} = 'FALSE' THEN 0 ELSE 1 END
, TAKASIMA_FLG = CASE WHEN #{takasimaFlg} = 'FALSE' THEN 0 ELSE 1 END
, D_SWAT_FLG = CASE WHEN #{dSwatFlg} = 'FALSE' THEN 0 ELSE 1 END
, POWER_COM_HAVE_FLG = CASE WHEN #{powerComHaveFlg} = 'FALSE' THEN 0 ELSE 1 END
, POWER_COM_NON_FLG = CASE WHEN #{powerComNonFlg} = 'FALSE' THEN 0 ELSE 1 END
, CONNECT_BOX_HAVE_FLG = CASE WHEN #{connectBoxHaveFlg} = 'FALSE' THEN 0 ELSE 1 END
, CONNECT_BOX_NON_FLG = CASE WHEN #{connectBoxNonFlg} = 'FALSE' THEN 0 ELSE 1 END
, METAL_FITTING_DETAIL_FLG = CASE WHEN #{metalFittingDetailFlg} = 'FALSE' THEN 0 ELSE 1 END
, METAL_FITTING_ALL_FLG = CASE WHEN #{metalFittingAllFlg} = 'FALSE' THEN 0 ELSE 1 END
, STAND_FLG = CASE WHEN #{standFlg} = 'FALSE' THEN 0 ELSE 1 END
, SECURE_TARGET_FLG = CASE WHEN #{secureTargetFlg} = 'FALSE' THEN 0 ELSE 1 END
, DISP_CONTAINER_FLG = CASE WHEN #{dispContainerFlg} = 'FALSE' THEN 0 ELSE 1 END
, PANEL_LAYOUT_DESIGN_DISP_FLG = CASE WHEN #{panelLayoutDesignDispFlg} = 'FALSE' THEN 0 ELSE 1 END
, STAND_DISP_FLG = CASE WHEN #{standDispFlg} = 'FALSE' THEN 0 ELSE 1 END
, GROSS_WT = #{grossWt}
, GUAR_ITEM_GROUP = #{guarItemGroup}
, FILE_UPLOAD_FLG = CASE WHEN #{fileUploadFlg} = 'FALSE' THEN 0 ELSE 1 END
, SALT_AFFECTED_FLG = CASE WHEN #{saltAffectedFlg} = 'FALSE' THEN 0 ELSE 1 END
, GUAR_EXCEPT_FLG = CASE WHEN #{guarExceptFlg} = 'FALSE' THEN 0 ELSE 1 END
, COLD_ZONE_FLG = CASE WHEN #{coldZoneFlg} = 'FALSE' THEN 0 ELSE 1 END
, PKG_MATERIAL_FLG = CASE WHEN #{pkgMaterialFlg} = 'FALSE' THEN 0 ELSE 1 END
, LAST_EDIT_DATETIME = GETDATE()
WHEN NOT MATCHED THEN
INSERT (
ITEM_ID
, ITEM_NAME
, ITEM_NO
, GOODS_NO
, UNIT
, SPECIFICATION
, FIXED_PRICE
, PNOW_W
, ITEM_GROUP
, PANEL_ORDER_FLG
, STAND_ORDER_FLG
, MODULE_FLG
, POWER_COM_FLG
, OPTION_FLG
, REMARKS
, DISP_ORDER
, DEL_FLG
, LIMITED_RELEASE_FLG
, YANEGI_FLG
, HORY_FLG
, TAKASIMA_FLG
, D_SWAT_FLG
, POWER_COM_HAVE_FLG
, POWER_COM_NON_FLG
, CONNECT_BOX_HAVE_FLG
, CONNECT_BOX_NON_FLG
, METAL_FITTING_DETAIL_FLG
, METAL_FITTING_ALL_FLG
, STAND_FLG
, SECURE_TARGET_FLG
, DISP_CONTAINER_FLG
, PANEL_LAYOUT_DESIGN_DISP_FLG
, STAND_DISP_FLG
, GROSS_WT
, GUAR_ITEM_GROUP
, FILE_UPLOAD_FLG
, SALT_AFFECTED_FLG
, GUAR_EXCEPT_FLG
, COLD_ZONE_FLG
, PKG_MATERIAL_FLG
, LAST_EDIT_DATETIME
) VALUES (
#{itemId}
, #{itemName}
, #{itemNo}
, #{goodsNo}
, #{unit}
, #{specification}
, #{fixedPrice}
, #{pnowW}
, #{itemGroup}
, CASE WHEN #{panelOrderFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{standOrderFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{moduleFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{powerComFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{optionFlg} = 'FALSE' THEN 0 ELSE 1 END
, #{remarks}
, #{dispOrder}
, CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{limitedReleaseFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{yanegiFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{horyFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{takasimaFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{dSwatFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{powerComHaveFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{powerComNonFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{connectBoxHaveFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{connectBoxNonFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{metalFittingDetailFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{metalFittingAllFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{standFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{secureTargetFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{dispContainerFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{panelLayoutDesignDispFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{standDispFlg} = 'FALSE' THEN 0 ELSE 1 END
, #{grossWt}
, #{guarItemGroup}
, CASE WHEN #{fileUploadFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{saltAffectedFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{guarExceptFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{coldZoneFlg} = 'FALSE' THEN 0 ELSE 1 END
, CASE WHEN #{pkgMaterialFlg} = 'FALSE' THEN 0 ELSE 1 END
, GETDATE()
);
</insert>
</mapper> </mapper>

View File

@ -56,6 +56,8 @@
, O.SALE_STORE_ID , O.SALE_STORE_ID
, SS.FIRST_AGENT_ID , SS.FIRST_AGENT_ID
, SS.SALE_STORE_LEVEL , SS.SALE_STORE_LEVEL
, CASE WHEN ISNULL(SS.FIRST_AGENT_ID, '') = '' THEN SS.SALE_STORE_NAME ELSE (SELECT SALE_STORE_NAME FROM M_SALES_STORE WHERE SALE_STORE_ID = SS.FIRST_AGENT_ID) END AS FIRST_SALE_STORE_NAME
, CASE WHEN ISNULL(SS.FIRST_AGENT_ID, '') = '' THEN NULL ELSE SS.SALE_STORE_NAME END AS AGENCY_SALE_STORE_NAME
FROM T_PLAN P WITH (NOLOCK) FROM T_PLAN P WITH (NOLOCK)
INNER JOIN T_OBJECT O WITH (NOLOCK) INNER JOIN T_OBJECT O WITH (NOLOCK)
ON P.OBJECT_NO = O.OBJECT_NO ON P.OBJECT_NO = O.OBJECT_NO
@ -116,11 +118,13 @@
, PE.UNIT , PE.UNIT
, PE.SPECIFICATION , PE.SPECIFICATION
, PE.AMOUNT , PE.AMOUNT
, PE.UNIT_PRICE
, PE.SALE_PRICE , PE.SALE_PRICE
, PE.FILE_UPLOAD_FLG
, PE.PKG_MATERIAL_FLG , PE.PKG_MATERIAL_FLG
, PE.SPECIAL_NOTE_CD
, PE.ITEM_CHANGE_FLG , PE.ITEM_CHANGE_FLG
, I.PNOW_W , I.PNOW_W
, I.FILE_UPLOAD_FLG
, CASE WHEN I.ITEM_GROUP = 'MODULE_' THEN '1' ELSE '0' END AS MODULE_FLG , CASE WHEN I.ITEM_GROUP = 'MODULE_' THEN '1' ELSE '0' END AS MODULE_FLG
FROM T_PART_ESTIMATE PE WITH (NOLOCK) FROM T_PART_ESTIMATE PE WITH (NOLOCK)
INNER JOIN M_ITEM I WITH (NOLOCK) INNER JOIN M_ITEM I WITH (NOLOCK)
@ -141,6 +145,7 @@
, I.PNOW_W , I.PNOW_W
, I.ITEM_GROUP , I.ITEM_GROUP
, I.PKG_MATERIAL_FLG , I.PKG_MATERIAL_FLG
, I.FILE_UPLOAD_FLG
, ISNULL(PPM.SALE_PRICE, '0') AS SALE_PRICE , ISNULL(PPM.SALE_PRICE, '0') AS SALE_PRICE
FROM M_ITEM I WITH (NOLOCK) FROM M_ITEM I WITH (NOLOCK)
LEFT OUTER JOIN M_PRICE_PATTERN_MONEY PPM LEFT OUTER JOIN M_PRICE_PATTERN_MONEY PPM
@ -180,6 +185,7 @@
/* sqlid : com.interplug.qcast.biz.estimate.selectEstimateNoteItemList */ /* sqlid : com.interplug.qcast.biz.estimate.selectEstimateNoteItemList */
SELECT SELECT
CL.CODE CL.CODE
, OSNI.ITEM_ID
FROM M_COMM_L CL WITH (NOLOCK) FROM M_COMM_L CL WITH (NOLOCK)
INNER JOIN T_OBJECT_SPECIAL_NOTE OSN WITH (NOLOCK) INNER JOIN T_OBJECT_SPECIAL_NOTE OSN WITH (NOLOCK)
ON CL.CODE = OSN.SPN_ATTR_CD ON CL.CODE = OSN.SPN_ATTR_CD
@ -296,7 +302,11 @@
, LAST_EDIT_USER , LAST_EDIT_USER
, UNIT_PRICE , UNIT_PRICE
, SALE_PRICE , SALE_PRICE
, FILE_UPLOAD_FLG
, PKG_MATERIAL_FLG , PKG_MATERIAL_FLG
<if test='specialNoteCd != null and specialNoteCd != ""'>
, SPECIAL_NOTE_CD
</if>
, ITEM_CHANGE_FLG , ITEM_CHANGE_FLG
) VALUES ( ) VALUES (
#{objectNo} #{objectNo}
@ -316,7 +326,11 @@
, #{userId} , #{userId}
, #{unitPrice} , #{unitPrice}
, #{salePrice} , #{salePrice}
, #{fileUploadFlg}
, #{pkgMaterialFlg} , #{pkgMaterialFlg}
<if test='specialNoteCd != null and specialNoteCd != ""'>
, #{specialNoteCd}
</if>
, #{itemChangeFlg} , #{itemChangeFlg}
) )
</insert> </insert>