From 10dcce28c1eca6836d3f88fbfc26470279b2f3bd Mon Sep 17 00:00:00 2001 From: rjy1537 Date: Fri, 8 Nov 2024 15:27:46 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=84=EC=9D=B4=ED=85=9C=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EB=B0=B0=EC=B9=98=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qcast/batch/JobLauncherController.java | 30 ++++ .../batch/master/MaterialConfiguration.java | 87 +++++++++++ .../biz/displayItem/DisplayItemMapper.java | 10 ++ .../biz/displayItem/DisplayItemService.java | 16 ++ .../biz/displayItem/dto/ItemSyncRequest.java | 13 ++ .../biz/displayItem/dto/ItemSyncResponse.java | 141 +++++++++++++++++ .../resources/config/application-local.yml | 1 + .../mappers/displayItem/displayItemMapper.xml | 144 +++++++++++++++++- 8 files changed, 439 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java create mode 100644 src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncRequest.java create mode 100644 src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncResponse.java diff --git a/src/main/java/com/interplug/qcast/batch/JobLauncherController.java b/src/main/java/com/interplug/qcast/batch/JobLauncherController.java index 80aa39a2..1e30e270 100644 --- a/src/main/java/com/interplug/qcast/batch/JobLauncherController.java +++ b/src/main/java/com/interplug/qcast/batch/JobLauncherController.java @@ -118,4 +118,34 @@ public class JobLauncherController { 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 = + new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); + + jobLauncher.run(job, jobParameters); + + return "OK"; + } } diff --git a/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java b/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java new file mode 100644 index 00000000..c6477823 --- /dev/null +++ b/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java @@ -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 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) + .chunk(100, transactionManager) + .reader(materialReader()) + .processor(materialProcessor()) + .writer(materialWriter()) + .build(); + } + + @Bean + @StepScope + public ItemReader materialReader() throws Exception { + ItemSyncRequest itemSyncRequest = new ItemSyncRequest(); + itemSyncRequest.setAllYn("N"); + this.itemSyncList = + interfaceQsp.callApiData( + HttpMethod.GET, + qspInterfaceUrl, + itemSyncRequest, + new TypeReference>() {}); + return (itemSyncList != null) + ? new ListItemReader<>(itemSyncList) + : new ListItemReader<>(Collections.emptyList()); + } + + @Bean + public ItemProcessor materialProcessor() { + return item -> item; + } + + @Bean + public ItemWriter materialWriter() { + return items -> { + displayItemService.setItemSyncSave((List) items.getItems()); + }; + } +} diff --git a/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemMapper.java b/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemMapper.java index 59244c97..b553dc1e 100644 --- a/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemMapper.java +++ b/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemMapper.java @@ -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.ItemResponse; +import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse; import java.util.List; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -14,4 +15,13 @@ public interface DisplayItemMapper { List getItemList(@Param("saleStoreId") String saleStoreId); ItemResponse getItemDetail(@Param("itemId") String itemId); + + /** + * 아이템 정보 동기화 + * + * @param itemInfoSync 아이템 정보 + * @return + * @throws Exception + */ + int setItemSyncSave(ItemSyncResponse itemInfoSync); } diff --git a/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemService.java b/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemService.java index df750e79..d9e6a568 100644 --- a/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemService.java +++ b/src/main/java/com/interplug/qcast/biz/displayItem/DisplayItemService.java @@ -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.ItemResponse; +import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse; import com.interplug.qcast.biz.estimate.EstimateMapper; import com.interplug.qcast.biz.estimate.dto.NoteRequest; import com.interplug.qcast.biz.estimate.dto.NoteResponse; @@ -70,4 +71,19 @@ public class DisplayItemService { return itemResponse; } + + /** + * 아이템 정보 동기화 + * + * @param itemSyncList 아이템 목록 + * @return + * @throws Exception + */ + public int setItemSyncSave(List itemSyncList) throws Exception { + int cnt = 0; + for (ItemSyncResponse itemSyncData : itemSyncList) { + displayItemMapper.setItemSyncSave(itemSyncData); + } + return cnt; + } } diff --git a/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncRequest.java b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncRequest.java new file mode 100644 index 00000000..8ff8c2bf --- /dev/null +++ b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncRequest.java @@ -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; +} diff --git a/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncResponse.java b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncResponse.java new file mode 100644 index 00000000..cfd52ce4 --- /dev/null +++ b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemSyncResponse.java @@ -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; +} diff --git a/src/main/resources/config/application-local.yml b/src/main/resources/config/application-local.yml index 574eed2c..c0c6677c 100644 --- a/src/main/resources/config/application-local.yml +++ b/src/main/resources/config/application-local.yml @@ -39,6 +39,7 @@ spring: qsp: url: http://1.248.227.176:8120 master-store-batch-url: /api/master/storeAdditionalInfo + master-material-batch-url: /api/master/materialList simulation-guide-info-url: /api/simulation/guideInfo aes256.key: jpqcellQ123456!! auto.login.aes256.key: _autoL!! diff --git a/src/main/resources/mappers/displayItem/displayItemMapper.xml b/src/main/resources/mappers/displayItem/displayItemMapper.xml index 32f94fa8..697d4efa 100644 --- a/src/main/resources/mappers/displayItem/displayItemMapper.xml +++ b/src/main/resources/mappers/displayItem/displayItemMapper.xml @@ -20,7 +20,7 @@ UPDATE SET START_DATE = #{startDate} , END_DATE = #{endDate} - , DEL_FLG = #{delFlg} + , DEL_FLG = CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END , LAST_EDIT_DATETIME = #{lastEditDatetime} WHEN NOT MATCHED THEN INSERT ( @@ -38,7 +38,7 @@ , #{itemId} , #{startDate} , #{endDate} - , #{delFlg} + , CASE WHEN #{delFlg} = 'FALSE' THEN 0 ELSE 1 END , #{registDatetime} , #{lastEditDatetime} ); @@ -88,7 +88,7 @@ , MI.GOODS_NO , MI.UNIT , MI.SPECIFICATION - , MI.PNOW_W + , MI.PNOW_W , MI.ITEM_GROUP , MI.MODULE_FLG , MI.PKG_MATERIAL_FLG @@ -102,4 +102,142 @@ AND MI.ITEM_ID = #{itemId} + + /* 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() + ); +