초기셋팅

This commit is contained in:
jazz
2025-12-18 10:04:46 +09:00
commit b68aa39bfb
387 changed files with 54028 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
package com.wb.domainserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.*;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
import java.util.Properties;
import java.util.Random;
@SpringBootApplication(exclude = {
HibernateJpaAutoConfiguration.class,
DataSourceAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class
})
@EnableAsync
@EnableScheduling
@EnableCaching
@EnableTransactionManagement(proxyTargetClass = true)
public class BatchApplication {
private static final Logger logger = LoggerFactory.getLogger(BatchApplication.class);
public static void main(String[] args) throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
SpringApplication app = new SpringApplication(BatchApplication.class);
app.setWebApplicationType(WebApplicationType.NONE);
//TODO: 프로그램 실행 처리
//app.run(BatchApplication.class, args);
ConfigurableApplicationContext ctx = app.run(args);
JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
logger.info(":::A args Length ::: " + args.length);
if (args.length > 0) {
Job job = ctx.getBean(args[0], Job.class);
JobParametersBuilder builder = new JobParametersBuilder();
builder.addLong("currTime", System.currentTimeMillis());
if (args.length > 1) {
Properties props = StringUtils.splitArrayElementsIntoProperties(args, "=");
int idx = 1;
for (Object okey : props.keySet() ) {
String key = (String) okey;
logger.info("parameter[" + idx + "] :::: " + key + "=" + props.get(key));
builder.addString(key, (String) props.get(key));
idx++;
}
}
JobExecution jobExecution = jobLauncher.run(job, builder.toJobParameters());
if (!jobExecution.getExitStatus().equals(ExitStatus.COMPLETED)) {
throw new RuntimeException(args[0] + " Job execution failed.");
}
} else {
throw new RuntimeException("배치JOB명은 필수 입니다. EX) java -jar app.jar 배치JOB명");
}
System.exit(0);
}
}

View File

@@ -0,0 +1,41 @@
package com.wb.domainserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableCaching
@EnableScheduling
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BatchApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ServletInitializer.class, args);
}
}
//@SpringBootApplication
//public class ServletInitializer extends SpringBootServletInitializer {
//
// @Override
// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
// return application.sources(ServletInitializer.class);
// }
//
// public static void main(String[] args) {
// SpringApplication.run(ServletInitializer.class, args);
// }
//
//}

View File

@@ -0,0 +1,148 @@
package com.wb.domainserver.analysis.jobs;
import com.wb.domainserver.analysis.tasklet.*;
import com.wb.domainserver.crm.tasklet.InsertTsDelMbrAppnRegistTasklet;
import com.wb.domainserver.crm.tasklet.InsertTsMbrAppnRegistTasklet;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.listener.ExecutionContextPromotionListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
/**
* 주간보고 자동화 관련 배치
*
* @author 이동호
* @since 2024.06.10
* @version 1.0
*/
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class AnalysisOrderListConfig extends DefaultBatchConfiguration{
private static final Logger logger = LoggerFactory.getLogger(AnalysisOrderListConfig.class);
private final SqlSessionFactory sqlSessionFactory;
private final InsertErpTotalStatisticsListTasklet insertErpTotalStatisticsListTasklet;
private final InsertShoppingMallOrderListTasklet insertShoppingMallOrderListTasklet;
private final InsertSmartStoreOrderListTasklet insertSmartStoreOrderListTasklet;
private final InsertErpGoodsTasklet insertErpGoodsTasklet;
private final InsertErpSetGoodsTasklet insertErpSetGoodsTasklet;
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[]{"message"});
return listener;
}
/* ##############################################################################################
ERP,자사몰,스마트스토어 모든 주문정보 가져오기
################################################################################################# */
/* @param jobRepository
* @param transactionManager
* @return
*/
@Bean
public Job analysisOrderListJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new JobBuilder("analysisOrderListJob", jobRepository)
.start(insertErpTotalStatisticsListStep(jobRepository, transactionManager, promotionListener))
.next(insertSmartStoreOrderListStep(jobRepository, transactionManager, promotionListener))
//.next(insertShoppingMallOrderListStep(jobRepository, transactionManager, promotionListener))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 1. mq -> gcone db로 erp 주문 데이터 추출후 insert
*/
@Bean
public Step insertErpTotalStatisticsListStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertErpTotalStatisticsListStep", jobRepository)
.tasklet(insertErpTotalStatisticsListTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/**
* 2. 자사몰 주문 목록 추출후 insert
*/
@Bean
public Step insertShoppingMallOrderListStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertShoppingMallOrderListStep", jobRepository)
.tasklet(insertShoppingMallOrderListTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/**
* 3. 스마트스토어 주문 목록 추출후 insert
*/
@Bean
public Step insertSmartStoreOrderListStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertSmartStoreOrderListStep", jobRepository)
.tasklet(insertSmartStoreOrderListTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/* ##############################################################################################
MQ -> ERP 제상품 현황, 세트코드 가져오기
################################################################################################# */
/* @param jobRepository
* @param transactionManager
* @return
*/
@Bean
public Job analysisErpGoodsJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new JobBuilder("analysisErpGoodsJob", jobRepository)
.start(insertErpGoodsStep(jobRepository, transactionManager, promotionListener))
.next(insertErpSetGoodsStep(jobRepository, transactionManager, promotionListener))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 1. MQ -> ERP 제상품 현황 INSERT
*/
@Bean
public Step insertErpGoodsStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertErpGoodsStep", jobRepository)
.tasklet(insertErpGoodsTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/**
* 2. MQ -> ERP 세트상품 현황 INSERT
*/
@Bean
public Step insertErpSetGoodsStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertErpSetGoodsStep", jobRepository)
.tasklet(insertErpSetGoodsTasklet, transactionManager)
.listener(promotionListener)
.build();
}
}

View File

@@ -0,0 +1,75 @@
package com.wb.domainserver.analysis.tasklet;
import com.wb.domainserver.analysis.vo.TsAnalysisErpGoodsVO;
import com.wb.domainserver.analysis.vo.TsAnalysisErpSetGoodsVO;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.mapper.gcone.AnalysisMapper;
import com.wb.domainserver.mapper.gcone.MemberAppnMapper;
import com.wb.domainserver.mapper.mq.MqReqCommMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertErpGoodsTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
@Autowired
private MqReqCommMapper mqReqCommMapper;
@Autowired
private AnalysisMapper analysisMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("InsertErpGoodsTasklet 실행");
Map<String,Object> message = new HashMap<>();
try {
List<TsAnalysisErpGoodsVO> goodsVOList = mqReqCommMapper.selectErpGoodsList();
if (goodsVOList!=null && !goodsVOList.isEmpty()) {
analysisMapper.deleteErpGoods();
analysisMapper.insertErpGoods(goodsVOList);
}
} catch (Exception e) {
e.printStackTrace();
message.put("status", "0");
message.put("message", "GC_ANALYSIS_ERP_GOODS 테이블에 insert 실패!!");
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("InsertErpSetGoodsTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,75 @@
package com.wb.domainserver.analysis.tasklet;
import com.wb.domainserver.analysis.vo.TsAnalysisErpSetGoodsVO;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.mapper.gcone.AnalysisMapper;
import com.wb.domainserver.mapper.gcone.GconeMqReqCommMapper;
import com.wb.domainserver.mapper.gcone.MemberAppnMapper;
import com.wb.domainserver.mapper.mq.MqReqCommMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertErpSetGoodsTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
@Autowired
private MqReqCommMapper mqReqCommMapper;
@Autowired
private AnalysisMapper analysisMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("InsertErpSetGoodsTasklet 실행");
Map<String,Object> message = new HashMap<>();
try {
List<TsAnalysisErpSetGoodsVO> setGoodsVOList = mqReqCommMapper.selectErpSetGoodsList();
if (setGoodsVOList!=null && !setGoodsVOList.isEmpty()) {
analysisMapper.deleteErpSetGoods();
analysisMapper.insertErpSetGoods(setGoodsVOList);
}
} catch (Exception e) {
e.printStackTrace();
message.put("status", "0");
message.put("message", "GC_ANALYSIS_ERP_SET_GOODS 테이블에 insert 실패!!");
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("InsertErpSetGoodsTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,64 @@
package com.wb.domainserver.analysis.tasklet;
import com.wb.domainserver.analysis.vo.TsAnalysisErpTotalStatisticsVO;
import com.wb.domainserver.analysis.vo.TsAnalysisOrderListVO;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import com.wb.domainserver.mapper.gcone.AnalysisMapper;
import com.wb.domainserver.mapper.mq.MqReqCommMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
@Component
@JobScope
@Slf4j
public class InsertErpTotalStatisticsListTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertErpTotalStatisticsListTasklet.class);
@Autowired
private AnalysisMapper mapper;
@Autowired
private MqReqCommMapper mqReqCommMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("MemberAppnLogDelTasklet 실행");
Map<String,Object> message = new HashMap<>();
List<TsAnalysisErpTotalStatisticsVO> mqErpTotalStatisticsList = mqReqCommMapper.selectMqErpTotalStatisticsList();
List<TsAnalysisErpTotalStatisticsVO> orderList = new ArrayList<>();
if (mqErpTotalStatisticsList.size() > 0 ) {
mapper.insertTotalList(mqErpTotalStatisticsList);
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("InsertErpTotalStatisticsListTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,142 @@
package com.wb.domainserver.analysis.tasklet;
import com.wb.domainserver.analysis.vo.TsAnalysisOrderListVO;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import com.wb.domainserver.mapper.gcone.AnalysisMapper;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Component
@JobScope
@Slf4j
public class InsertShoppingMallOrderListTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
@Autowired
private AnalysisMapper mapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
log.info("==========================================");
log.info("InsertShoppingMallOrderListTasklet 실행");
Date sDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(sDate);
calendar.add(Calendar.DAY_OF_MONTH, -3);
Date eDate = calendar.getTime();
DataMap params = new DataMap();
params.put("sDate", sDate);
params.put("eDate", eDate);
Map<String, Object> message = new HashMap<>();
List<TsAnalysisOrderListVO> tsAnalysisOrderListVOS = mapper.selectShoppingMallOrderList(params);
List<DataMap> goodsMapList;
List<TsAnalysisOrderListVO> allTsAnalysisOrderList = new ArrayList<>();
DataMap paramMap = new DataMap();
int iCount = 0;
int jCount = 0;
if (tsAnalysisOrderListVOS != null && !tsAnalysisOrderListVOS.isEmpty()) {
for (int i = 0; i < tsAnalysisOrderListVOS.size(); i++) {
goodsMapList = mapper.selectbarcodeGoodsInfo(tsAnalysisOrderListVOS.get(i).getBarcode());
if (goodsMapList != null && !goodsMapList.isEmpty()) {
allTsAnalysisOrderList.add(tsAnalysisOrderListVOS.get(i));
iCount++;
} else {
BigDecimal rlSetleAmt = BigDecimal.ZERO;
paramMap.put("goodsCode", tsAnalysisOrderListVOS.get(i).getBarcode());
if("".equals(tsAnalysisOrderListVOS.get(i).getBarcode()) || tsAnalysisOrderListVOS.get(i).getBarcode() == null) {
continue;
}
goodsMapList = mapper.selectsetCodeGoodsInfo(paramMap);
if (goodsMapList != null && !goodsMapList.isEmpty()) {
Set<String> sameBarcodeSet = goodsMapList.stream()
.map(p -> p != null ? (String) p.get("barcode") : null)
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(
barcode -> barcode,
Collectors.counting()
))
.entrySet().stream()
.filter(p -> p.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
int barcodeQy = goodsMapList.stream()
.filter(map -> sameBarcodeSet.contains(map.get("barcode").toString()))
.mapToInt(map -> (int) map.getOrDefault("barcodeQy", 1))
.sum();
for (int j = 0; j < goodsMapList.size(); j++) {
jCount++;
if (j == 0) {
rlSetleAmt = tsAnalysisOrderListVOS.get(i).getRlSetleAmt();
}
if (barcodeQy != 0) {
tsAnalysisOrderListVOS.get(i).setBarcodeQy(barcodeQy);
} else {
tsAnalysisOrderListVOS.get(i).setBarcodeQy(
Optional.ofNullable(goodsMapList.get(j))
.map(map -> (int) map.get("barcodeQy"))
.orElse(1)
);
}
tsAnalysisOrderListVOS.get(i).setShopSetCd(
Optional.ofNullable(goodsMapList.get(j))
.map(map -> (String) map.get("setCode"))
.orElse("")
);
tsAnalysisOrderListVOS.get(i).setBarcode(
Optional.ofNullable(goodsMapList.get(j))
.map(map -> (String) map.get("barcode"))
.orElse("")
);
tsAnalysisOrderListVOS.get(i).setRlSetleAmt(rlSetleAmt);
allTsAnalysisOrderList.add(tsAnalysisOrderListVOS.get(i));
}
}
}
}
System.out.println("iCount : " + iCount);
System.out.println("jCount : " + jCount);
mapper.insertOrderList(allTsAnalysisOrderList);
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
log.info("InsertShoppingMallOrderListTasklet 종료");
log.info("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,698 @@
package com.wb.domainserver.analysis.tasklet;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.analysis.vo.TsAnalysisOrderListVO;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import static java.util.Map.entry;
import com.wb.domainserver.mapper.gcone.AnalysisMapper;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.wb.domainserver.analysis.vo.SmartStoreProperties;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@Component
@JobScope
@Slf4j
public class InsertSmartStoreOrderListTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
private static final String PAYMENT_WAITING = "PAYMENT_WAITING";
private static final String CANCELED_BY_NOPAYMENT = "CANCELED_BY_NOPAYMENT";
private static final String ACCOUNT_ID_NC = "nutricore";
private static final String ACCOUNT_ID_DT = "ncp_1ns2z5_01";
private static final String ACCOUNT_ID_CH = "shadow222";
private static final String ACCOUNT_ID_LF = "ncp_1np5dl_01";
private static final String ACCOUNT_ID_TZ = "thezac";
private static final String ACCOUNT_ID_NB = "ncp_1nlp35_01";
private static final String ACCOUNT_ID_PL = "proslab";
private static final String ACCOUNT_ID_AF = "ncp_1nm5zw_01";
private static final String ACCOUNT_ID_BD = "ncp_1nprdw_01";
private static final String ACCOUNT_ID_DL = "ncp_1nsmcy_01";
private static final String ACCOUNT_ID_HMALL = "ncp_1nxwne_01";
@Autowired
private final SmartStoreProperties smartStoreProperties;
@Autowired
private final Environment env;
@Autowired
private AnalysisMapper analysisMapper;
@Value("${smartstoreurl.tokenurl}")
private String tokenUri;
@Value("${smartstoreurl.orderlisturl}")
private String orderListUrl;
@Value("${smartstoreurl.orderdetailurl}")
private String orderdetailurl;
private StepExecution stepExecution;
public InsertSmartStoreOrderListTasklet(SmartStoreProperties smartStoreProperties, Environment env) {
this.smartStoreProperties = smartStoreProperties;
this.env = env;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("InsertSmartStoreOrderListTasklet 실행");
Long timestamp = System.currentTimeMillis();
Map<String,Object> message = new HashMap<>();
List<DataMap> orderCodeList = new ArrayList<>();
List<Map<String,Object>> orginDataList = new ArrayList<>();
List<String> sopmalCd = new ArrayList<>();
Map<String ,Map<String,String>> properties = null;
String clientSecretSign = "";
String accessToken = "";
List<TsAnalysisOrderListVO> allTsAnalysisOrderListVOList = new ArrayList<>();
List<TsAnalysisOrderListVO> tsAnalysisOrderListVOList = new ArrayList<>();
sopmalCd = smartStoreProperties.getStoreCodes();
String clientId = "";
String clientSecret = "";
// 쇼핑몰별 네이버 토큰 api 생성
for (String sopmal : sopmalCd) {
properties = smartStoreProperties.getStores();
clientId = properties.get(sopmal).get("clientId");
clientSecret = properties.get(sopmal).get("clientSecret");
clientSecretSign = generateSignature(clientId,clientSecret,timestamp);
System.out.println("clientId : " + clientId);
System.out.println("clientSecret : " + clientSecret);
System.out.println("clientSecretSign : " + clientSecretSign);
accessToken = getAccessToken (clientId,timestamp,clientSecretSign);
System.out.println("accessToken" + accessToken);
properties.get(sopmal).put("accessToken : ", accessToken);
orderCodeList = getOrderCodeList(accessToken);
tsAnalysisOrderListVOList = ApiOrder(accessToken,orderCodeList,tsAnalysisOrderListVOList,sopmal);
allTsAnalysisOrderListVOList.addAll(tsAnalysisOrderListVOList);
tsAnalysisOrderListVOList.clear();
orginDataList.clear();
orderCodeList.clear();
}
analysisMapper.insertOrderList(allTsAnalysisOrderListVOList);
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("InsertSmartStoreOrderListTasklet 종료");
System.out.println("==========================================");
System.out.println("allTsAnalysisOrderListVOList 사이즈 : " + allTsAnalysisOrderListVOList.size());
return RepeatStatus.FINISHED;
}
public String generateSignature(String clientId, String clientSecret, Long timestamp) {
// 밑줄로 연결하여 password 생성
String password = String.join("_", clientId, timestamp.toString());
// bcrypt 해싱
String hashedPw = BCrypt.hashpw(password, clientSecret);
// base64 인코딩
return Base64.getUrlEncoder().encodeToString(hashedPw.getBytes(StandardCharsets.UTF_8));
}
public String getAccessToken(String clientId, Long timestamp, String clientSecretSign) {
HttpURLConnection httpURLConnection = null;
ObjectMapper objectMapper = new ObjectMapper();
BufferedReader reader = null;
OutputStream outputStream = null;
try {
URL url = new URL(tokenUri);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setDoOutput(true);
StringBuilder sb = new StringBuilder();
sb.append("client_id=").append(clientId)
.append("&timestamp=").append(timestamp)
.append("&client_secret_sign=").append(clientSecretSign)
.append("&type=SELF")
.append("&grant_type=client_credentials");
outputStream = httpURLConnection.getOutputStream();
byte[] input = sb.toString().getBytes(StandardCharsets.UTF_8);
outputStream.write(input, 0, input.length);
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), StandardCharsets.UTF_8));
String response = reader.lines().collect(java.util.stream.Collectors.joining());
Map<String, Object> mapResponse = objectMapper.readValue(response, Map.class);
JSONObject jsonResponse = new JSONObject(mapResponse);
return jsonResponse.get("access_token").toString();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 자원 반납
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpURLConnection != null) {
System.out.println("TOKEN HttpURLConnection is being disconnected");
httpURLConnection.disconnect();
}
}
return null;
}
public List<DataMap> getOrderCodeList(String accessToken) {
List<DataMap> allResults = new ArrayList<>();
for (int day = -3; day <= 0; day++) {
final int currentDay = day;
allResults.addAll(fetchSequentialDataForDay(accessToken, currentDay));
}
System.out.println("allresults : " + allResults.size());
return allResults;
}
private List<DataMap> fetchSequentialDataForDay(String accessToken, int day) {
List<String> results = new ArrayList<>();
String moreSequence = null;
String moreFrom = null;
List<DataMap> changeDateList = new ArrayList<>();
do {
Map<String, Object> response = new HashMap<>();
try {
if (moreFrom != null) {
response = fetchOrderData(accessToken, moreFrom,getLastChangedTo(day), moreSequence);
} else {
response = fetchOrderData(accessToken, getLastChangedFrom(day), getLastChangedTo(day), moreSequence);
}
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
if (response == null) break;
Map<String, Object> data = (Map<String, Object>) response.get("data");
if (data == null) break;
List<Map<String, Object>> lastChangeStatuses = (List<Map<String, Object>>) data.get("lastChangeStatuses");
for (Map<String, Object> status : lastChangeStatuses) {
DataMap changeDateMap = new DataMap();
results.add((String) status.get("productOrderId"));
changeDateMap.put("ordrId", (String) status.get("productOrderId"));
changeDateMap.put("lastChangedDate", (String) status.get("lastChangedDate"));
changeDateList.add(changeDateMap);
}
Map<String, Object> moreMap = (Map<String, Object>) data.get("more");
moreSequence = moreMap != null ? (String) moreMap.get("moreSequence") : null;
moreFrom = moreMap != null ? (String) moreMap.get("moreFrom") : null;
} while (moreSequence != null);
return changeDateList;
}
private String getLastChangedFrom(int day) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Seoul"));
calendar.add(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
OffsetDateTime startDate = calendar.toInstant().atOffset(ZoneOffset.ofHours(9));
return startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"));
}
private String getLastChangedTo(int day) {
OffsetDateTime startDate;
if (day == 0) {
startDate = OffsetDateTime.now(ZoneId.of("Asia/Seoul"));
} else {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Seoul"));
calendar.add(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 59);
startDate = calendar.toInstant().atOffset(ZoneOffset.ofHours(9));
}
return startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"));
}
private Map<String, Object> fetchOrderData(String accessToken, String lastChangedFrom, String lastChangedTo, String moreSequence) throws IOException {
String urlParam = String.format("%s?lastChangedFrom=%s&lastChangedTo=%s",
orderListUrl,
URLEncoder.encode(lastChangedFrom, StandardCharsets.UTF_8),
URLEncoder.encode(lastChangedTo, StandardCharsets.UTF_8));
if (moreSequence != null) {
urlParam += "&moreSequence=" + moreSequence;
}
HttpURLConnection connection = null;
InputStream inputStream = null;
BufferedReader reader = null;
try {
connection = (HttpURLConnection) new URL(urlParam).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + accessToken);
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
String response = "";
int responseCode = connection.getResponseCode();
if (responseCode >= 400) {
inputStream = connection.getErrorStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
String errorResponse = reader.lines().collect(Collectors.joining());
System.out.println("Error Response: " + errorResponse);
} else {
inputStream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
response = reader.lines().collect(Collectors.joining());
}
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(response, Map.class);
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
public List<TsAnalysisOrderListVO> getOrderDetailList (String accessToken, List<DataMap> orderCodeList,List<TsAnalysisOrderListVO> tsAnalysisOrderListVOList, String sopmalCd) {
Map<String, Object> requestBody = new HashMap<>();
List<String> productOrderIdList = new ArrayList<>();
List<Map<String, String>> orderDetailsList = new ArrayList<>();
Map<String, Object> result = new HashMap<>();
Instant start = Instant.now();
// productOrderId만 넘기기위한 작업
for (DataMap status : orderCodeList) {
String productOrderId = (String) status.get("ordrId");
String lastChangedDate = (String) status.get("lastChangedDate");
if (productOrderId != null) {
productOrderIdList.add(productOrderId);
Map<String, String> orderDetail = new HashMap<>();
orderDetail.put(productOrderId, lastChangedDate);
orderDetailsList.add(orderDetail);
}
}
requestBody.put("productOrderIds", productOrderIdList);
Map<String, String> accountMap = new HashMap<>();
accountMap = accountIdMapping();
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(orderdetailurl);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Authorization", "Bearer " + accessToken);
httpURLConnection.setRequestProperty("content-type", "application/json");
httpURLConnection.setDoOutput(true);
try (OutputStream os = httpURLConnection.getOutputStream()) {
byte[] input = new ObjectMapper().writeValueAsBytes(requestBody);
os.write(input, 0, input.length);
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), StandardCharsets.UTF_8))) {
String input;
StringBuffer response = new StringBuffer();
while ((input = reader.readLine()) != null) {
response.append(input);
}
reader.close();
httpURLConnection.disconnect();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> responseMap = objectMapper.readValue(response.toString(), Map.class);
List<Map<String, Object>> dataMap = (List<Map<String, Object>>) responseMap.get("data");
//List<Map<String, Object>> productOrderMap = (List<Map<String, Object>>) dataMap.get("productOrder");
if (!dataMap.isEmpty()) {
for (int i = 0; i < dataMap.size(); i++) {
Map<String, Object> order = (Map<String, Object>) dataMap.get(i).get("order");
Map<String, Object> productOrder = (Map<String, Object>) dataMap.get(i).get("productOrder");
String claimType = (String) productOrder.get("claimType");
LocalDateTime lastChangedDate = null;
String ordrStatus = (String) productOrder.get("productOrderStatus");
String goodsCode = (String) productOrder.get("optionManageCode");
if (PAYMENT_WAITING.equals(ordrStatus) || CANCELED_BY_NOPAYMENT.equals(ordrStatus)) {
continue;
}
if ("".equals(goodsCode) || goodsCode == null) {
goodsCode = (String) productOrder.get("sellerProductCode");
}
// 마지막 변화일 저장을 위한 비교후 데이터 저장
for (Map<String, String> lastChangeMap : orderDetailsList) {
String productOrderId = (String) productOrder.get("productOrderId");
if (lastChangeMap.containsKey(productOrderId)) {
lastChangedDate = convertToLocalDateTime(lastChangeMap.get(productOrderId));
}
}
DataMap goodsMap = new DataMap();
DataMap param = new DataMap();
List<DataMap> goodsMapList = new ArrayList<>();
String setCode = "";
String missingFlag = "N";
BigDecimal goodsPrice = BigDecimal.ZERO;
BigDecimal totalPaymentAmount = BigDecimal.ZERO;
List<String> sopmalCdList = new ArrayList<>();
TsAnalysisOrderListVO tsAnalysisOrderListVO = null;
String productOption = Optional.ofNullable(productOrder.get("productOption") != null ? (String) productOrder.get("productOption") : null)
.orElse("");
String claimStatus = Optional.ofNullable(productOrder.get("claimStatus") != null ? (String) productOrder.get("claimStatus") : null)
.orElse("");
String decisionDate = Optional.ofNullable(productOrder.get("decisionDate") != null ? (String) productOrder.get("decisionDate") : null)
.orElse(null);
//바코드 상품조회
goodsMapList = analysisMapper.selectbarcodeGoodsInfo(goodsCode);
if (goodsMapList != null && goodsMapList.size() > 0) {
goodsCode = (String) goodsMapList.get(0).get("barcode");
if (sopmalCd.equals("HMALL") || sopmalCd.equals("AF")) {
sopmalCd = (String) goodsMapList.get(0).get("sopmalCd");
}
totalPaymentAmount = BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount"));
goodsPrice = calCulate(
BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount")),
BigDecimal.valueOf((Integer) productOrder.get("productDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("sellerBurdenDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("deliveryFeeAmount"))
);
tsAnalysisOrderListVO = createBaseOrderListVO(order, productOrder, sopmalCd, claimType, goodsPrice, totalPaymentAmount, goodsCode, 1, "", ordrStatus, lastChangedDate, productOption, claimStatus, decisionDate, missingFlag);
tsAnalysisOrderListVOList.add(tsAnalysisOrderListVO);
} else {
sopmalCd = accountMap.get((String) productOrder.get("mallId"));
param.put("goodsCode", goodsCode);
goodsMapList = analysisMapper.selectsetCodeGoodsInfo(param);
//세트 코드 제품 분할작업
if (goodsMapList.size() > 0) {
//중복 바코드 추리기
Set<String> sameBarcodeSet = goodsMapList.stream().map(p -> p != null ? (String) p.get("barcode") : null)
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(barcode -> barcode, Collectors.counting()))
.entrySet().stream()
.filter(p -> p.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
// 단일 세트상품 수량합치기
int barcodeQy = goodsMapList.stream()
.filter(map -> sameBarcodeSet.contains(map.get("barcode").toString()))
.mapToInt(map -> (int) map.getOrDefault("barcodeQy", 0))
.sum();
for (int k = 0; k < goodsMapList.size(); k++) {
// 세트상품 첫 제품에 금액 몰아주기
if (k == 0) {
goodsPrice = calCulate(
BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount")),
BigDecimal.valueOf((Integer) productOrder.get("productDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("sellerBurdenDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("deliveryFeeAmount"))
);
totalPaymentAmount = BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount"));
} else {
totalPaymentAmount = BigDecimal.ZERO;
goodsPrice = BigDecimal.ZERO;
}
//단일 세트상품일 경우 가격은 같게 갯수는 더해줌
if (sameBarcodeSet.contains(goodsMapList.get(k).get("barcode"))) {
goodsPrice = calCulate(
BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount")),
BigDecimal.valueOf((Integer) productOrder.get("productDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("sellerBurdenDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("deliveryFeeAmount"))
);
totalPaymentAmount = BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount"));
} else {
barcodeQy = Optional.ofNullable(goodsMapList.get(k) != null ? (int) goodsMapList.get(k).get("barcodeQy") : 1)
.orElse(1);
}
goodsCode = Optional.ofNullable(goodsMapList.get(k) != null ? (String) goodsMapList.get(k).get("barcode") : null)
.orElse((String) productOrder.get("optionManageCode"));
if (sopmalCd.equals("HMALL") || sopmalCd.equals("AF")) {
sopmalCd = goodsMapList.get(k) != null ? (String) goodsMapList.get(k).get("sopmalCd") : sopmalCd;
}
setCode = Optional.ofNullable(goodsMapList.get(k) != null ? (String) goodsMapList.get(k).get("setCode") : null)
.orElse("");
tsAnalysisOrderListVO = createBaseOrderListVO(
order, productOrder, sopmalCd, claimType, goodsPrice, totalPaymentAmount, goodsCode, barcodeQy, setCode, ordrStatus, lastChangedDate, productOption, claimStatus, decisionDate, missingFlag
);
tsAnalysisOrderListVOList.add(tsAnalysisOrderListVO);
}
} else {
totalPaymentAmount = BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount"));
goodsPrice = calCulate(
BigDecimal.valueOf((Integer) productOrder.get("totalPaymentAmount")),
BigDecimal.valueOf((Integer) productOrder.get("productDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("sellerBurdenDiscountAmount")),
BigDecimal.valueOf((Integer) productOrder.get("deliveryFeeAmount"))
);
int barcodeQy = 1;
// UPSERT를 위한 초기화
if (goodsCode == null) goodsCode = "";
if (setCode == null) setCode = "";
missingFlag = "Y";
tsAnalysisOrderListVO = createBaseOrderListVO(
order, productOrder, sopmalCd, claimType, goodsPrice, totalPaymentAmount, goodsCode, barcodeQy, setCode, ordrStatus, lastChangedDate, productOption, claimStatus, decisionDate, missingFlag
);
tsAnalysisOrderListVOList.add(tsAnalysisOrderListVO);
}
}
}
}
//log.debug("데이터입니당" + tsAnalysisOrderListVOList);
}
} catch (Exception apiException) {
System.err.println("API 호출 실패: " + apiException.getMessage());
apiException.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
return tsAnalysisOrderListVOList;
}
public String setOrderStatusCode (String ordrSttusCd) {
Map<String, Integer> statusPriority = Map.ofEntries(
entry("PAYMENT_WAITING", 15),
entry("PAYED", 25),
entry("DELIVERING", 65),
entry("DELIVERED", 75),
entry("PURCHASE_DECIDED", 75),
entry("CANCELED", 85),
entry("RETURN", 85),
entry("EXCHANGE", 85),
entry("PURCHASE_DECISION_HOLDBACK", 85),
entry("CANCELED_BY_NOPAYMENT", 99)
);
Integer priority = statusPriority.get(ordrSttusCd);
return (priority != null) ? priority.toString() : "15";
}
public static LocalDateTime convertToLocalDateTime(String isoDate) {
return LocalDateTime.parse(isoDate, DateTimeFormatter.ISO_DATE_TIME);
}
public List<TsAnalysisOrderListVO> ApiOrder (String accessToken, List<DataMap> orderCodeList,List<TsAnalysisOrderListVO> tsAnalysisOrderListVOList, String sopmal) {
final int MAX_ORDER_SIZE = 300;
int totalOrderCnt = orderCodeList.size();
Instant startTime = Instant.now();
for (int i = 0; i < totalOrderCnt; i += MAX_ORDER_SIZE) {
int end = Math.min(i + MAX_ORDER_SIZE, totalOrderCnt);
List<DataMap> maxList = orderCodeList.subList(i, end);
tsAnalysisOrderListVOList = getOrderDetailList(accessToken,maxList , tsAnalysisOrderListVOList, sopmal);
}
Instant ends = Instant.now();
// 시작 시간과 종료 시간 차이 계산
long timeElapsedInMillis = ends.toEpochMilli() - startTime.toEpochMilli();
long timeElapsedInSeconds = timeElapsedInMillis / 1000; // 밀리초를 초로 변환
System.out.println("디테일 경과 시간: " + timeElapsedInSeconds + "초");
return tsAnalysisOrderListVOList;
}
public Date formatDate(String date) {
try {
ZonedDateTime zonedDateTime = ZonedDateTime.parse(date);
return Date.from(zonedDateTime.toInstant());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public BigDecimal calCulate (BigDecimal totalPaymentAmount, BigDecimal productDiscountAmount, BigDecimal sellerBurdenDiscountAmount, BigDecimal deliveryFeeAmount ) {
return totalPaymentAmount.add(productDiscountAmount).subtract(sellerBurdenDiscountAmount).add(deliveryFeeAmount);
}
public Map<String,String> accountIdMapping () {
Map<String,String> accountMap = new HashMap<>();
accountMap.put(ACCOUNT_ID_AF,"AF");
accountMap.put(ACCOUNT_ID_NC,"NC");
accountMap.put(ACCOUNT_ID_BD,"BD");
accountMap.put(ACCOUNT_ID_CH,"CH");
accountMap.put(ACCOUNT_ID_DL,"DL");
accountMap.put(ACCOUNT_ID_DT,"DT");
accountMap.put(ACCOUNT_ID_LF,"LF");
accountMap.put(ACCOUNT_ID_TZ,"TZ");
accountMap.put(ACCOUNT_ID_NB,"NB");
accountMap.put(ACCOUNT_ID_PL,"PL");
accountMap.put(ACCOUNT_ID_HMALL,"HMALL");
return accountMap;
}
private TsAnalysisOrderListVO createBaseOrderListVO(
Map<String, Object> order,
Map<String, Object> productOrder,
String sopmalCd,
String claimType,
BigDecimal goodsPrice,
BigDecimal totalPaymentAmount,
String goodsCode,
int barcodeQy,
String setCode,
String ordrStatus,
LocalDateTime lastChangedDate,
String productOption,
String claimStatus,
String decisionDate,
String missingFlag
) {
return TsAnalysisOrderListVO.builder()
.productOrdrInnb((String) productOrder.get("productOrderId"))
.ordrInnb((String) order.get("orderId"))
.paymentDt(formatDate((String) order.get("paymentDate")))
.goodsNm((String) productOrder.get("productName"))
.goodsQy((int) productOrder.get("quantity"))
.ordrSttusCd(setOrderStatusCode(ordrStatus))
.sopmalDv("스마트스토어")
.totalPaymentAmount(totalPaymentAmount)
.barcode(goodsCode)
.barcodeQy(barcodeQy)
.shopSetCd(setCode)
.sopmalCd(sopmalCd)
.baesongBi(BigDecimal.valueOf((Integer) productOrder.get("deliveryFeeAmount")))
.claimType(claimType)
.rlSetleAmt(goodsPrice)
.lastChangedDate(lastChangedDate)
.productOption(productOption)
.claimStatus(claimStatus)
.decisionDate(decisionDate != null ? formatDate(decisionDate) : null)
.missingFlag(missingFlag)
.build();
}
}

View File

@@ -0,0 +1,20 @@
package com.wb.domainserver.analysis.vo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "smartstore.sopmal")
@Data
public class SmartStoreProperties {
private Map<String, Map<String, String>> stores;
public List<String> getStoreCodes() {
return new ArrayList<>(stores.keySet());
}
}

View File

@@ -0,0 +1,20 @@
package com.wb.domainserver.analysis.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsAnalysisErpGoodsVO {
private String barcode;
private String sopmalCd;
private String goodsNm;
private BigDecimal goodsPrice;
}

View File

@@ -0,0 +1,25 @@
package com.wb.domainserver.analysis.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsAnalysisErpSetGoodsVO {
private String setCode;
private String barcode;
private Integer barcodeQy;
private String sopmalCd;
private String giftYn;
private String setGoodsNm;
private String goodsNm;
private String regNo;
}

View File

@@ -0,0 +1,49 @@
package com.wb.domainserver.analysis.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TsAnalysisErpTotalStatisticsVO {
private String coCd;
private String strgrp1Cd;
private String strgrp2Cd;
private String strgrp3Cd;
private String strgrp4Cd;
private LocalDateTime saleDt;
private String brandNm;
private String itmNm;
private String barcode;
private BigDecimal salAmt;
private int qty;
private BigDecimal salAmt2;
private String itmId;
private LocalDateTime registDt;
private LocalDateTime updateDt;
private String cancType;
}

View File

@@ -0,0 +1,60 @@
package com.wb.domainserver.analysis.vo;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TsAnalysisOrderListVO {
private String ordrInnb;
private String productOrdrInnb;
private String sopmalCd;
private String ordrSttusCd;
private String barcode;
private int goodsQy;
private BigDecimal rlSetleAmt;
private BigDecimal totalPaymentAmount;
private Date paymentDt;
private Date decisionDate;
private String giftYn;
private String sopmalDv;
private String goodsNm;
private int shipNoSeq;
private String shopSetCd;
private BigDecimal baesongBi;
private String claimType;
private int barcodeQy;
private LocalDateTime lastChangedDate;
private String productOption;
private String claimStatus;
private String missingFlag;
}

View File

@@ -0,0 +1,92 @@
package com.wb.domainserver.app.jobs;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import com.wb.domainserver.app.tasklet.AppPushEvtDtTasklet;
import com.wb.domainserver.app.tasklet.AppPushEvtNcTasklet;
import com.wb.domainserver.app.tasklet.AppPushResveDtTasklet;
import com.wb.domainserver.app.tasklet.AppPushResveNcTasklet;
/**
*
* App Push 발송 배치
*
* @author 이훈영
* @since 2025-05-16
* @version 1.0
* @see
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2025-05-16 이훈영 최초 생성
*
* </pre>
*/
@Configuration
@EnableBatchProcessing
public class AppPushConfig {
@Autowired
private AppPushEvtNcTasklet appPushEvtNcTasklet;
@Autowired
private AppPushEvtDtTasklet appPushEvtDtTasklet;
@Autowired
private AppPushResveNcTasklet appPushResveNcTasklet;
@Autowired
private AppPushResveDtTasklet appPushResveDtTasklet;
@Bean
public Job appPushJob(JobRepository jobRepository, Step appPushEvtNcStep, Step appPushEvtDtStep, Step appPushResveNcStep, Step appPushResveDtStep) {
return new JobBuilder("appPushJob", jobRepository)
.start(appPushEvtNcStep)
.next(appPushResveNcStep)
.next(appPushEvtDtStep)
.next(appPushResveDtStep)
.incrementer(new RunIdIncrementer())
.build();
}
@Bean
public Step appPushEvtNcStep(JobRepository jobRepository, @Qualifier("gconeTransactionManager") PlatformTransactionManager transactionManager) {
return new StepBuilder("appPushEvtNcStep", jobRepository)
.tasklet(appPushEvtNcTasklet, transactionManager)
.build();
}
@Bean
public Step appPushEvtDtStep(JobRepository jobRepository, @Qualifier("gconeTransactionManager") PlatformTransactionManager transactionManager) {
return new StepBuilder("appPushEvtDtStep", jobRepository)
.tasklet(appPushEvtDtTasklet, transactionManager)
.build();
}
@Bean
public Step appPushResveNcStep(JobRepository jobRepository, @Qualifier("gconeTransactionManager") PlatformTransactionManager transactionManager) {
return new StepBuilder("appPushResveNcStep", jobRepository)
.tasklet(appPushResveNcTasklet, transactionManager)
.build();
}
@Bean
public Step appPushResveDtStep(JobRepository jobRepository, @Qualifier("gconeTransactionManager") PlatformTransactionManager transactionManager) {
return new StepBuilder("appPushResveDtStep", jobRepository)
.tasklet(appPushResveDtTasklet, transactionManager)
.build();
}
}

View File

@@ -0,0 +1,51 @@
package com.wb.domainserver.app.jobs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.FirebaseMessaging;
import java.io.IOException;
@Configuration
public class FCMConfig {
@Bean(name = "NCFirebaseMessaging")
public FirebaseMessaging nutricoreFirebaseMessaging() throws IOException {
return createFirebaseMessaging(
"nutricoreeventapp-firebase-adminsdk-iliil-bd9d39ca9c.json",
"nutricore"
);
}
@Bean(name = "DTFirebaseMessaging")
public FirebaseMessaging doctorleanFirebaseMessaging() throws IOException {
return createFirebaseMessaging(
"doctorleaneventapp-firebase-adminsdk-ysdbz-3e5496cb84.json",
"doctorlean"
);
}
private FirebaseMessaging createFirebaseMessaging(String fileName, String appName) throws IOException {
ClassPathResource serviceAccount = new ClassPathResource("firebase/" + fileName);
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount.getInputStream()))
.build();
FirebaseApp firebaseApp;
if (FirebaseApp.getApps().stream().noneMatch(app -> app.getName().equals(appName))) {
// FirebaseApp이 존재하지 않으면 새로 초기화
firebaseApp = FirebaseApp.initializeApp(options, appName);
} else {
// 이미 초기화된 FirebaseApp 사용
firebaseApp = FirebaseApp.getInstance(appName);
}
return FirebaseMessaging.getInstance(firebaseApp);
}
}

View File

@@ -0,0 +1,179 @@
package com.wb.domainserver.app.tasklet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import com.wb.domainserver.app.vo.AppPushVO;
import com.wb.domainserver.mapper.gcone.AppPushMapper;
import com.wb.domainserver.service.AppPushSendService;
import com.wb.domainserver.util.dataaccess.DataMap;
@Component
public class AppPushEvtDtTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(AppPushEvtDtTasklet.class);
@Autowired
private AppPushMapper appPushMapper;
@Autowired
private AppPushSendService pushSendService;
@Qualifier("DTFirebaseMessaging")
@Autowired
private FirebaseMessaging dtFirebaseMessaging;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
logger.info("푸시 이벤트건 전송 : DT");
AppPushVO vo = new AppPushVO();
vo.setSopmalCd("DT");
// 푸시 콜백 데이터 설정
Map<String, String> dataMap = new HashMap<>();
dataMap.put("url", "/sopmal/bnft/bnftMain");
dataMap.put("key", "");
dataMap.put("ext", "");
ObjectMapper objectMapper = new ObjectMapper();
String jsonData = objectMapper.writeValueAsString(dataMap);
List<DataMap> trgetList = appPushMapper.selectBOBnftPushTrgetList(vo);
for (DataMap trgetItem : trgetList) {
String bnfDvCd = trgetItem.get("bnfDvCd").toString();
String sndngYn = trgetItem.get("sndngYn").toString();
// 섭취챌린지를 제외한.. 나머지 혜택은 해당일&발송완료 일때 스킵
if (!"100".equals(bnfDvCd) && "Y".equals(sndngYn)) {
logger.info("기발송 혜택 스킵됨 - bnfDvCd={}, bnfPushEvtSetupInnb={}", bnfDvCd, trgetItem.get("bnfPushEvtSetupInnb"));
continue;
}
// 1. 푸시 발송 이력 insert
AppPushVO histVO = new AppPushVO();
histVO.setSopmalCd(vo.getSopmalCd());
histVO.setBnfPushEvtSetupInnb(Long.valueOf(trgetItem.get("bnfPushEvtSetupInnb").toString()));
histVO.setSndngAt("N");
histVO.setSndngTrgetCnt(0);
appPushMapper.insertBOBnftPushSndngDtls(histVO);
Long sndngDtlsInnb = histVO.getBnfPushSndngDtlsInnb();
int succCnt = 0;
int failCnt = 0;
List<DataMap> mbrList = null;
if ("070".equals(bnfDvCd)) { // 라이브쇼핑
AppPushVO lvVO = new AppPushVO();
lvVO.setSopmalCd(vo.getSopmalCd());
DataMap lvData = appPushMapper.selectBOBnftPushLvshopInfo(lvVO);
if (lvData == null) continue;
if (lvData.get("bnfInnb") != null) {
histVO.setBnfInnb(Long.valueOf(lvData.get("bnfInnb").toString()));
}
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd("070");
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
} else if ("100".equals(bnfDvCd)) { // 섭취챌린지
mbrList = appPushMapper.selectBOBnftPushNtakchlMbrList(vo);
} else { // 출석, ox퀴즈등
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd(bnfDvCd);
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
}
if (mbrList == null || mbrList.isEmpty()) continue;
// 발송최적화를 위해 한번에 200건씩 발송 (추후 조절이 필요하더라도 500건 미만으로 설정할것)
int pushSize = 200;
int mbrTotal = mbrList.size();
for (int i = 0; i < mbrTotal; i += pushSize) {
int end = Math.min(i + pushSize, mbrTotal);
List<DataMap> batchList = mbrList.subList(i, end);
logger.info("푸시 배치 처리: {} ~ {} (총 {}건 중)", i + 1, end, mbrTotal);
for (DataMap mbrItem : batchList) {
String fcmToken = Optional.ofNullable(mbrItem.get("fcmToken")).map(Object::toString).orElse("");
String pushSj = Optional.ofNullable(trgetItem.get("pushSj")).map(Object::toString).orElse("");
String pushCn = Optional.ofNullable(trgetItem.get("pushCn")).map(Object::toString).orElse("");
DataMap resultMap = pushSendService.sendPush(
dtFirebaseMessaging,
fcmToken,
pushSj,
pushCn,
"notice",
jsonData,
""
);
String resultCode = resultMap.get("resultCode").toString();
String resultStts = resultMap.get("resultStts").toString();
// 섭취챌린지의 경우 마지막 푸시발송일시를 업데이트한다
if ("100".equals(bnfDvCd)) {
AppPushVO ntakVO = new AppPushVO();
ntakVO.setBnfNtkNtcnInnb(Long.valueOf(mbrItem.get("bnfNtkNtcnInnb").toString()));
appPushMapper.updateBOBnftPushNtakchlSendDt(ntakVO);
}
if ("200".equals(resultCode)) {
succCnt++;
} else {
failCnt++;
AppPushVO errVO = new AppPushVO();
errVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
errVO.setErrorCode(resultStts);
errVO.setFcmToken(fcmToken);
errVO.setPushSj(pushSj);
errVO.setPushCn(pushCn);
errVO.setPushData(jsonData);
errVO.setImgFilCours("");
appPushMapper.insertBOBnftPushSndngErrlog(errVO);
}
}
// 발송최적화를 위한 딜레이
Thread.sleep(100);
}
// 3. 이력 업데이트
AppPushVO updVO = new AppPushVO();
updVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
updVO.setBnfInnb(histVO.getBnfInnb());
updVO.setSndngAt("Y");
updVO.setSndngTrgetCnt(mbrList.size());
updVO.setSndngSuccesCnt(succCnt);
updVO.setSndngFailrCnt(failCnt);
appPushMapper.updateBOBnftPushSndngDtls(updVO);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,176 @@
package com.wb.domainserver.app.tasklet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.firebase.messaging.FirebaseMessaging;
import com.wb.domainserver.app.vo.AppPushVO;
import com.wb.domainserver.mapper.gcone.AppPushMapper;
import com.wb.domainserver.service.AppPushSendService;
import com.wb.domainserver.util.dataaccess.DataMap;
@Component
public class AppPushEvtNcTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(AppPushEvtNcTasklet.class);
@Autowired
private AppPushMapper appPushMapper;
@Autowired
private AppPushSendService pushSendService;
@Qualifier("NCFirebaseMessaging")
@Autowired
private FirebaseMessaging ncFirebaseMessaging;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
logger.info("푸시 이벤트건 전송 : NC");
AppPushVO vo = new AppPushVO();
vo.setSopmalCd("NC");
// 푸시 콜백 데이터 설정
Map<String, String> dataMap = new HashMap<>();
dataMap.put("url", "/sopmal/bnft/bnftMain");
dataMap.put("key", "");
dataMap.put("ext", "");
ObjectMapper objectMapper = new ObjectMapper();
String jsonData = objectMapper.writeValueAsString(dataMap);
List<DataMap> trgetList = appPushMapper.selectBOBnftPushTrgetList(vo);
for (DataMap trgetItem : trgetList) {
String bnfDvCd = trgetItem.get("bnfDvCd").toString();
String sndngYn = trgetItem.get("sndngYn").toString();
// 섭취챌린지를 제외한.. 나머지 혜택은 해당일&발송완료 일때 스킵
if (!"100".equals(bnfDvCd) && "Y".equals(sndngYn)) {
logger.info("기발송 혜택 스킵됨 - bnfDvCd={}, bnfPushEvtSetupInnb={}", bnfDvCd, trgetItem.get("bnfPushEvtSetupInnb"));
continue;
}
// 1. 푸시 발송 이력 insert
AppPushVO histVO = new AppPushVO();
histVO.setSopmalCd(vo.getSopmalCd());
histVO.setBnfPushEvtSetupInnb(Long.valueOf(trgetItem.get("bnfPushEvtSetupInnb").toString()));
histVO.setSndngAt("N");
histVO.setSndngTrgetCnt(0);
appPushMapper.insertBOBnftPushSndngDtls(histVO);
Long sndngDtlsInnb = histVO.getBnfPushSndngDtlsInnb();
int succCnt = 0;
int failCnt = 0;
List<DataMap> mbrList = null;
if ("070".equals(bnfDvCd)) { // 라이브쇼핑
AppPushVO lvVO = new AppPushVO();
lvVO.setSopmalCd(vo.getSopmalCd());
DataMap lvData = appPushMapper.selectBOBnftPushLvshopInfo(lvVO);
if (lvData == null) continue;
if (lvData.get("bnfInnb") != null) {
histVO.setBnfInnb(Long.valueOf(lvData.get("bnfInnb").toString()));
}
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd("070");
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
} else if ("100".equals(bnfDvCd)) { // 섭취챌린지
mbrList = appPushMapper.selectBOBnftPushNtakchlMbrList(vo);
} else { // 출석, ox퀴즈등
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd(bnfDvCd);
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
}
if (mbrList == null || mbrList.isEmpty()) continue;
// 발송최적화를 위해 한번에 200건씩 발송 (추후 조절이 필요하더라도 500건 미만으로 설정할것)
int pushSize = 200;
int mbrTotal = mbrList.size();
for (int i = 0; i < mbrTotal; i += pushSize) {
int end = Math.min(i + pushSize, mbrTotal);
List<DataMap> batchList = mbrList.subList(i, end);
logger.info("푸시 배치 처리: {} ~ {} (총 {}건 중)", i + 1, end, mbrTotal);
for (DataMap mbrItem : batchList) {
String fcmToken = Optional.ofNullable(mbrItem.get("fcmToken")).map(Object::toString).orElse("");
String pushSj = Optional.ofNullable(trgetItem.get("pushSj")).map(Object::toString).orElse("");
String pushCn = Optional.ofNullable(trgetItem.get("pushCn")).map(Object::toString).orElse("");
DataMap resultMap = pushSendService.sendPush(
ncFirebaseMessaging,
fcmToken,
pushSj,
pushCn,
"notice",
jsonData,
""
);
String resultCode = resultMap.get("resultCode").toString();
String resultStts = resultMap.get("resultStts").toString();
// 섭취챌린지의 경우 마지막 푸시발송일시를 업데이트한다
if ("100".equals(bnfDvCd)) {
AppPushVO ntakVO = new AppPushVO();
ntakVO.setBnfNtkNtcnInnb(Long.valueOf(mbrItem.get("bnfNtkNtcnInnb").toString()));
appPushMapper.updateBOBnftPushNtakchlSendDt(ntakVO);
}
if ("200".equals(resultCode)) {
succCnt++;
} else {
failCnt++;
AppPushVO errVO = new AppPushVO();
errVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
errVO.setErrorCode(resultStts);
errVO.setFcmToken(fcmToken);
errVO.setPushSj(pushSj);
errVO.setPushCn(pushCn);
errVO.setPushData(jsonData);
errVO.setImgFilCours("");
appPushMapper.insertBOBnftPushSndngErrlog(errVO);
}
}
// 발송최적화를 위한 딜레이
Thread.sleep(100);
}
// 3. 이력 업데이트
AppPushVO updVO = new AppPushVO();
updVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
updVO.setBnfInnb(histVO.getBnfInnb());
updVO.setSndngAt("Y");
updVO.setSndngTrgetCnt(mbrList.size());
updVO.setSndngSuccesCnt(succCnt);
updVO.setSndngFailrCnt(failCnt);
appPushMapper.updateBOBnftPushSndngDtls(updVO);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,143 @@
package com.wb.domainserver.app.tasklet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.firebase.messaging.FirebaseMessaging;
import com.wb.domainserver.app.vo.AppPushVO;
import com.wb.domainserver.mapper.gcone.AppPushMapper;
import com.wb.domainserver.service.AppPushSendService;
import com.wb.domainserver.util.dataaccess.DataMap;
@Component
public class AppPushResveDtTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(AppPushResveNcTasklet.class);
@Autowired
private AppPushMapper appPushMapper;
@Autowired
private AppPushSendService pushSendService;
@Qualifier("DTFirebaseMessaging")
@Autowired
private FirebaseMessaging dtFirebaseMessaging;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
logger.info("푸시 예약건 전송 : DT");
AppPushVO vo = new AppPushVO();
vo.setSopmalCd("DT");
List<DataMap> resveList = appPushMapper.selectBOBnftPushResveList(vo);
ObjectMapper objectMapper = new ObjectMapper();
for (DataMap resveItem : resveList) {
String bnfDvCd = resveItem.get("bnfPushTrgetDvCd").toString();
// 푸시 콜백 데이터 설정
Map<String, String> dataMap = new HashMap<>();
dataMap.put("url", Optional.ofNullable(resveItem.get("dataUrl")).map(Object::toString).orElse(""));
dataMap.put("key", Optional.ofNullable(resveItem.get("dataKey")).map(Object::toString).orElse(""));
dataMap.put("ext", Optional.ofNullable(resveItem.get("dataExt")).map(Object::toString).orElse(""));
String jsonData = objectMapper.writeValueAsString(dataMap);
// 1. 푸시 발송 이력 insert
AppPushVO histVO = new AppPushVO();
histVO.setSopmalCd(vo.getSopmalCd());
histVO.setBnfPushInfoInnb(Long.valueOf(resveItem.get("bnfPushInfoInnb").toString()));
histVO.setSndngAt("N");
histVO.setSndngTrgetCnt(0);
appPushMapper.insertBOBnftPushSndngDtls(histVO);
Long sndngDtlsInnb = histVO.getBnfPushSndngDtlsInnb();
int succCnt = 0;
int failCnt = 0;
List<DataMap> mbrList = null;
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd(bnfDvCd);
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
if (mbrList == null || mbrList.isEmpty()) continue;
// 발송최적화를 위해 한번에 200건씩 발송 (추후 조절이 필요하더라도 500건 미만으로 설정할것)
int pushSize = 200;
int mbrTotal = mbrList.size();
for (int i = 0; i < mbrTotal; i += pushSize) {
int end = Math.min(i + pushSize, mbrTotal);
List<DataMap> batchList = mbrList.subList(i, end);
logger.info("푸시 배치 처리: {} ~ {} (총 {}건 중)", i + 1, end, mbrTotal);
for (DataMap mbrItem : batchList) {
String fcmToken = Optional.ofNullable(mbrItem.get("fcmToken")).map(Object::toString).orElse("");
String pushSj = Optional.ofNullable(resveItem.get("pushSj")).map(Object::toString).orElse("");
String pushCn = Optional.ofNullable(resveItem.get("pushCn")).map(Object::toString).orElse("");
String imgFilCours = Optional.ofNullable(resveItem.get("imgFilCours")).map(Object::toString).orElse("");
DataMap resultMap = pushSendService.sendPush(
dtFirebaseMessaging,
fcmToken,
pushSj,
pushCn,
"notice",
jsonData,
imgFilCours
);
String resultCode = resultMap.get("resultCode").toString();
String resultStts = resultMap.get("resultStts").toString();
if ("200".equals(resultCode)) {
succCnt++;
} else {
failCnt++;
AppPushVO errVO = new AppPushVO();
errVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
errVO.setErrorCode(resultStts);
errVO.setFcmToken(fcmToken);
errVO.setPushSj(pushSj);
errVO.setPushCn(pushCn);
errVO.setPushData(jsonData);
errVO.setImgFilCours(imgFilCours);
appPushMapper.insertBOBnftPushSndngErrlog(errVO);
}
}
// 발송최적화를 위한 딜레이
Thread.sleep(100);
}
// 3. 이력 업데이트
AppPushVO updVO = new AppPushVO();
updVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
updVO.setBnfInnb(histVO.getBnfInnb());
updVO.setSndngAt("Y");
updVO.setSndngTrgetCnt(mbrList.size());
updVO.setSndngSuccesCnt(succCnt);
updVO.setSndngFailrCnt(failCnt);
appPushMapper.updateBOBnftPushSndngDtls(updVO);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,143 @@
package com.wb.domainserver.app.tasklet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.firebase.messaging.FirebaseMessaging;
import com.wb.domainserver.app.vo.AppPushVO;
import com.wb.domainserver.mapper.gcone.AppPushMapper;
import com.wb.domainserver.service.AppPushSendService;
import com.wb.domainserver.util.dataaccess.DataMap;
@Component
public class AppPushResveNcTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(AppPushResveNcTasklet.class);
@Autowired
private AppPushMapper appPushMapper;
@Autowired
private AppPushSendService pushSendService;
@Qualifier("NCFirebaseMessaging")
@Autowired
private FirebaseMessaging ncFirebaseMessaging;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
logger.info("푸시 예약건 전송 : NC");
AppPushVO vo = new AppPushVO();
vo.setSopmalCd("NC");
List<DataMap> resveList = appPushMapper.selectBOBnftPushResveList(vo);
ObjectMapper objectMapper = new ObjectMapper();
for (DataMap resveItem : resveList) {
String bnfDvCd = resveItem.get("bnfPushTrgetDvCd").toString();
// 푸시 콜백 데이터 설정
Map<String, String> dataMap = new HashMap<>();
dataMap.put("url", Optional.ofNullable(resveItem.get("dataUrl")).map(Object::toString).orElse(""));
dataMap.put("key", Optional.ofNullable(resveItem.get("dataKey")).map(Object::toString).orElse(""));
dataMap.put("ext", Optional.ofNullable(resveItem.get("dataExt")).map(Object::toString).orElse(""));
String jsonData = objectMapper.writeValueAsString(dataMap);
// 1. 푸시 발송 이력 insert
AppPushVO histVO = new AppPushVO();
histVO.setSopmalCd(vo.getSopmalCd());
histVO.setBnfPushInfoInnb(Long.valueOf(resveItem.get("bnfPushInfoInnb").toString()));
histVO.setSndngAt("N");
histVO.setSndngTrgetCnt(0);
appPushMapper.insertBOBnftPushSndngDtls(histVO);
Long sndngDtlsInnb = histVO.getBnfPushSndngDtlsInnb();
int succCnt = 0;
int failCnt = 0;
List<DataMap> mbrList = null;
AppPushVO mbrVO = new AppPushVO();
mbrVO.setSopmalCd(vo.getSopmalCd());
mbrVO.setBnfDvCd(bnfDvCd);
mbrList = appPushMapper.selectBOBnftPushMbrList(mbrVO);
if (mbrList == null || mbrList.isEmpty()) continue;
// 발송최적화를 위해 한번에 200건씩 발송 (추후 조절이 필요하더라도 500건 미만으로 설정할것)
int pushSize = 200;
int mbrTotal = mbrList.size();
for (int i = 0; i < mbrTotal; i += pushSize) {
int end = Math.min(i + pushSize, mbrTotal);
List<DataMap> batchList = mbrList.subList(i, end);
logger.info("푸시 배치 처리: {} ~ {} (총 {}건 중)", i + 1, end, mbrTotal);
for (DataMap mbrItem : batchList) {
String fcmToken = Optional.ofNullable(mbrItem.get("fcmToken")).map(Object::toString).orElse("");
String pushSj = Optional.ofNullable(resveItem.get("pushSj")).map(Object::toString).orElse("");
String pushCn = Optional.ofNullable(resveItem.get("pushCn")).map(Object::toString).orElse("");
String imgFilCours = Optional.ofNullable(resveItem.get("imgFilCours")).map(Object::toString).orElse("");
DataMap resultMap = pushSendService.sendPush(
ncFirebaseMessaging,
fcmToken,
pushSj,
pushCn,
"notice",
jsonData,
imgFilCours
);
String resultCode = resultMap.get("resultCode").toString();
String resultStts = resultMap.get("resultStts").toString();
if ("200".equals(resultCode)) {
succCnt++;
} else {
failCnt++;
AppPushVO errVO = new AppPushVO();
errVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
errVO.setErrorCode(resultStts);
errVO.setFcmToken(fcmToken);
errVO.setPushSj(pushSj);
errVO.setPushCn(pushCn);
errVO.setPushData(jsonData);
errVO.setImgFilCours(imgFilCours);
appPushMapper.insertBOBnftPushSndngErrlog(errVO);
}
}
// 발송최적화를 위한 딜레이
Thread.sleep(100);
}
// 3. 이력 업데이트
AppPushVO updVO = new AppPushVO();
updVO.setBnfPushSndngDtlsInnb(sndngDtlsInnb);
updVO.setBnfInnb(histVO.getBnfInnb());
updVO.setSndngAt("Y");
updVO.setSndngTrgetCnt(mbrList.size());
updVO.setSndngSuccesCnt(succCnt);
updVO.setSndngFailrCnt(failCnt);
appPushMapper.updateBOBnftPushSndngDtls(updVO);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,156 @@
package com.wb.domainserver.app.vo;
import java.util.HashMap;
import java.util.List;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AppPushVO {
/** 쇼핑몰코드 */
private String sopmalCd;
// 알림 내용 항목
/** 혜택 알림 정보 고유번호 */
private Long bnfPushInfoInnb;
/** 알림 대상 구분 코드 */
private String bnfPushTrgetDvCd;
/** 알림 대상 구분 명 */
private String bnfPushTrgetDvNm;
/** 알림 대상 구분 */
private String trgetDv;
/** 알림 대상 전체수 */
private Integer trgetAllCnt;
/** 알림 제목 */
private String pushSj;
/** 알림 내용 */
private String pushCn;
/** 알림 내용 - 개행처리 */
private String pushCnRpl;
/** 알림 발송 일시 */
private String pushSendDt;
/** 알림 발송 일자 */
private String pushSendDe;
/** 알림 발송 시간 */
private String pushSendTme;
/** 이미지파일경로 */
private String imgFilCours;
/** 이미지파일명 */
private String imgFilNm;
/** 예약 여부 */
private String resveAt;
/** 예약 상태 */
private String resveSttus;
/** 삭제 여부 */
private String delAt;
/** 알림 유형 */
private String pushType;
/** callback 데이터 */
private String pushData;
/** callback 데이터 - url */
private String dataUrl;
/** callback 데이터 - key */
private String dataKey;
/** callback 데이터 - ext */
private String dataExt;
// 알림 발송 항목
/** 혜택 알림 발송내역 고유번호 */
private Long bnfPushSndngDtlsInnb;
/** 혜택 알림 이벤트별 설정 고유번호 */
private Long bnfPushEvtSetupInnb;
/** 혜택 섭취챌린지 알림 고유번호 */
private Long bnfNtkNtcnInnb;
/** 발송 여부 */
private String sndngAt;
/** 발송 상태 */
private String sndngSttus;
/** 발송 대상수 */
private Integer sndngTrgetCnt;
/** 발송 성공수 */
private Integer sndngSuccesCnt;
/** 발송 실패수 */
private Integer sndngFailrCnt;
/** 에러코드 */
private String errorCode;
// 알림 설정
/** 테스트 대상 회원ID 문자열 */
private String trgetMbrIds;
/** 발송제한 시작 시간1 */
private String lmttBgnTme1;
/** 발송제한 종료 시간1 */
private String lmttEndTme1;
/** 발송제한 시작 시간2 */
private String lmttBgnTme2;
/** 발송제한 종료 시간2 */
private String lmttEndTme2;
// 대상 회원 항목
/** 회원 디바이스 고유번호 */
private Long mbrDeviceInnb;
/** 회원 디바이스 고유번호 배열 */
private Long[] arrMbrDeviceInnb;
/** 회원고유번호 */
private Long mbrInnb;
/** 회원구분코드 */
private String mbrDvCd;
/** 회원ID */
private String mbrId;
/** 회원명 */
private String mbrNm;
/** FCM 토큰 */
private String fcmToken;
/** FCM 토큰 배열 */
private String[] arrFcmToken;
/** 알림 동의 여부 */
private String pushAgreAt;
/** 디바이스 고유ID */
private String deviceId;
/** 운영체제 이름 */
private String deviceOsNm;
/** 운영체제 버전 */
private String deviceOsVer;
/** 앱 버전 */
private String deviceAppVer;
// 혜택별 동의 항목
/** 혜택 동의 고유번호 */
private Long bnfAgreInnb;
/** 혜택 구분코드 */
private String bnfDvCd;
/** 혜택 동의 구분코드 */
private String bnfAgreDvCd;
/** 혜택 설정 고유번호 */
private Long bnfInnb;
/** 동의여부 */
private String agreAt;
/** 이미지 파일 업로드 */
private List<HashMap<String, Object>> fileInfo;
/** CDN URL */
private String imgCdnurl;
// 검색 조건
/** 검색구분 */
private String srchDv;
/** 검색_검색어 */
private String srchKeyword;
/** 검색_날짜_구분 */
private String srchPdDv;
/** 검색_상태_구분 */
private String srchSttDv;
/** 검색_사용여부_구분 */
private String srchUseAt;
/** 검색_시작일 */
private String srchStartDt;
/** 검색_종료일 */
private String srchEndDt;
}

View File

@@ -0,0 +1,175 @@
package com.wb.domainserver.atmcrcpmny.jobs;
import com.wb.domainserver.atmcrcpmny.tasklet.*;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class AtmcrcpmnyConfig extends DefaultBatchConfiguration{
private static final Logger logger = LoggerFactory.getLogger(AtmcrcpmnyConfig.class);
private final SqlSessionFactory sqlSessionFactory;
private final InsertTsRcpmnyDtlsColctTasklet insertTsRcpmnyDtlsColctTasklet;
private final UpdateTsRcpmnyCnfirmAtmcMtchgTasklet updateTsRcpmnyCnfirmAtmcMtchgTasklet;
private final UpdateTsCshRciptRegistTasklet updateTsCshRciptRegistTasklet;
private final SelectTsOrderCancelTasklet selectTsOrderCancelTasklet;
private final UpdateClearPersonalInfoShopTasklet updateClearPersonalInfoShopTasklet;
/**
* 뱅크다 api 호출 후 입금내역 테이블에 insert, update
* 배치 30분에 한번 실행
*/
@Bean
public Job autodepositCronJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("autodepositCronJob", jobRepository)
.start(insertRcpmnyDtlsColct(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 뱅크다 api 호출 후 입금내역 테이블에 insert, update
*/
@Bean
public Step insertRcpmnyDtlsColct(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("insertRcpmnyDtlsColct", jobRepository)
.tasklet(insertTsRcpmnyDtlsColctTasklet, transactionManager)
.build();
}
/** ------------------------------------------------------------------------------------------------------------------ */
/**
* 입금내역(주문접수+무통장)에 대하여 자동 매칭
* 입금내역(주문접수+무통장) 조회 후
* 주문 테이블, 입금내역 테이블 update
* 배치 30분에 한번 실행
*/
@Bean
public Job rcpmnyCnfirmAtmcMtchgJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("rcpmnyCnfirmAtmcMtchgJob", jobRepository)
.start(updateRcpmnyCnfirmAtmcMtchg(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 입금내역(주문접수+무통장)에 대하여 자동 매칭
* 입금내역(주문접수+무통장) 조회 후
* 주문 테이블, 입금내역 테이블 update
*/
@Bean
public Step updateRcpmnyCnfirmAtmcMtchg(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("updateRcpmnyCnfirmAtmcMtchg", jobRepository)
.tasklet(updateTsRcpmnyCnfirmAtmcMtchgTasklet, transactionManager)
.build();
}
/** ------------------------------------------------------------------------------------------------------------------ */
/**
* 현금영수증 신청할 데이터 조회 후 현금영수증 신청.
* 매출증빙 테이블 update, 매출증빙로그 테이블 insert
* 배치 시간 미정
*/
@Bean
public Job cshRciptRegistJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("cshRciptRegistJob", jobRepository)
.start(updateCshRciptRegist(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 현금영수증 신청할 데이터 조회 후 현금영수증 신청.
* 매출증빙 테이블 update, 매출증빙로그 테이블 insert
*/
@Bean
public Step updateCshRciptRegist(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("updateCshRciptRegist", jobRepository)
.tasklet(updateTsCshRciptRegistTasklet, transactionManager)
.build();
}
/** ------------------------------------------------------------------------------------------------------------------ */
/** ------------------------------------------------------------------------------------------------------------------ */
/**
* 자동주문무효
* step=15, 접수일 7일전, Npay가 아닌거
* 새벽 1시 배치
*/
@Bean
public Job orderCancelJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("orderCancelJob", jobRepository)
.start(selectOrderCancel(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 자동주문무효
* step=15, 접수일 7일전, Npay가 아닌거
*
*/
@Bean
public Step selectOrderCancel(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("selectOrderCancel", jobRepository)
.tasklet(selectTsOrderCancelTasklet, transactionManager)
.build();
}
/** ------------------------------------------------------------------------------------------------------------------ */
/**
* 자사몰/독립몰 개인정보 마스킹 처리
* (1년 경과 후 문자/메일 로그, 주문관련)
* 배치 시간 :
*/
@Bean
public Job clearPersonalInfoShopJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("clearPersonalInfoShopJob", jobRepository)
.start(updateClearPersonalInfoShop(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
*
*/
@Bean
public Step updateClearPersonalInfoShop(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("updateClearPersonalInfoShop", jobRepository)
.tasklet(updateClearPersonalInfoShopTasklet, transactionManager)
.build();
}
/** ------------------------------------------------------------------------------------------------------------------ */
}

View File

@@ -0,0 +1,308 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import com.wb.domainserver.mapper.gcone.MssageMapper;
import com.wb.domainserver.ntcn.vo.TsEmailVO;
import com.wb.domainserver.ntcn.vo.TsMssageVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import com.wb.domainserver.util.ntcn.DataShareBean;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@Slf4j
@RequiredArgsConstructor
public class InsertTsDepositTrgtListTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsDepositTrgtListTasklet.class);
@Autowired
private MssageMapper mapper;
private final DataShareBean dataShareBean;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
Map<String, Object> message = dataShareBean.getData("message");
//조회 양식 코드 세팅
DataMap paramMap = new DataMap();
paramMap.put("formDtlDvCd", StringUtil.isNullToString(message.get("formDtlDvCd")));
paramMap.put("formDvCd", StringUtil.isNullToString(message.get("formDvCd")));
List<DataMap> atmcsndngMngtEmailList = (List<DataMap>) message.get("atmcsndngMngtEmailList");
List<DataMap> atmcsndngMngtSmsList = (List<DataMap>) message.get("atmcsndngMngtSmsList");
List<DataMap> atmcsndngMngtNtcnTalkList = (List<DataMap>) message.get("atmcsndngMngtNtcnTalkList");
List<DataMap> mbrGradTrgtList = mapper.selectCouponEndTrgtList(paramMap);
log.debug("mbrGradTrgtList {}", mbrGradTrgtList);
//이메일
if (atmcsndngMngtEmailList != null || !atmcsndngMngtEmailList.isEmpty()) {
//이메일 가능 브랜드
List<String> emailSopmalCd = atmcsndngMngtSmsList.stream()
.map(map -> StringUtil.isNullToString(map.get("sopmalCd")))
.toList();
//쇼핑몰로 필터링
List<DataMap> selectMbrGardEmailTrgtList = mbrGradTrgtList.stream()
.filter(map ->
emailSopmalCd.contains(StringUtil.isNullToString(map.get("mainSopmalCd"))))
.toList();
log.debug("selectMbrGardEmailTrgtList {}", selectMbrGardEmailTrgtList);
Map<String, List<TsEmailVO>> makeGroupedEmailData = makeGroupedEmailData(selectMbrGardEmailTrgtList);
List<BigInteger> emailSndngInnbList = processGroupedEmailData(makeGroupedEmailData);
message.put("emailSndngInnbList", emailSndngInnbList);
}
//sms
if (!atmcsndngMngtSmsList.isEmpty()) {
String dv = "";
//sms 가능 브랜드
List<String> smsSopmalCd = atmcsndngMngtSmsList.stream()
.map(map -> StringUtil.isNullToString(map.get("sopmalCd")))
.toList();
//쇼핑몰로 필터링
List<DataMap> selectMbrGradSmsTrgtList = mbrGradTrgtList.stream()
.filter(map ->
smsSopmalCd.contains(StringUtil.isNullToString(map.get("mainSopmalCd"))))
.toList();
log.debug("selectMbrGradSmsTrgtList {}", selectMbrGradSmsTrgtList);
//양식 조회
Map<String, List<TsMssageVO>> makeGroupedSmsData
= makeGroupedMssageData(selectMbrGradSmsTrgtList, dv);
log.debug("makeGroupedSmsData {}", makeGroupedSmsData);
List<BigInteger> smsInnbList = processGroupedMssageData(makeGroupedSmsData);
message.put("smsInnbList", smsInnbList);
}
//알림톡
if (!atmcsndngMngtNtcnTalkList.isEmpty()) {
String dv = "AT";
//sms 가능 브랜드
List<String> ntcnSopmalCd = atmcsndngMngtNtcnTalkList.stream()
.map(map -> StringUtil.isNullToString(map.get("sopmalCd")))
.toList();
//쇼핑몰로 필터링
List<DataMap> selectMbrGradNtcnTalkTrgtList = mbrGradTrgtList.stream()
.filter(map ->
ntcnSopmalCd.contains(StringUtil.isNullToString(map.get("mainSopmalCd"))))
.toList();
log.debug("selectMarktAgreNtcnTalkTrgtList {}", selectMbrGradNtcnTalkTrgtList);
//양식 조회
Map<String, List<TsMssageVO>> makeGroupeNtcnTalkData
= makeGroupedMssageData(selectMbrGradNtcnTalkTrgtList, dv);
List<BigInteger> smsInnbNtcnList = processGroupedMssageData(makeGroupeNtcnTalkData);
message.put("smsInnbNtcnList", smsInnbNtcnList);
}
return RepeatStatus.FINISHED;
}
/**
* 발송 대상 그룹 처리
* 발송 대상 목록을 쇼핑몰 별로 그룹화하여 새로운 리스트로 분리 생성
*
* @param groupedData
*/
public Map<String, List<TsMssageVO>> makeGroupedMssageData(List<DataMap> selectedList, String dv) {
return selectedList.stream()
.map(map -> {
TsMssageVO tsMssageVO = new TsMssageVO();
tsMssageVO.setSopmalCd(StringUtil.isNullToString(map.get("mainSopmalCd")));
tsMssageVO.setRegusrDv("03");//시스템
tsMssageVO.setStrInnb(BigInteger.ZERO);
tsMssageVO.setStrNm("");
tsMssageVO.setStrDv("99");
tsMssageVO.setChrSttus("REG");
tsMssageVO.setHead("");
String cn = StringUtil.isNullToString("AT".equals(dv) ? map.get("msg") : map.get("smsCn"));
tsMssageVO.setCn(fixStr(cn));
tsMssageVO.setTail("");
//dv가 AT면 AT설정, 아니면 길이 계산 dv (sms, lms)
tsMssageVO.setDv("AT".equals(dv) ? dv : msgType(cn));
tsMssageVO.setSmsNm("surem");
tsMssageVO.setSndngNb(StringUtil.isNullToString(map.get("sndngNb")));
//FM_SMS_TO 등록 정보
tsMssageVO.setRecptnNb(StringUtil.isNullToString(map.get("mbtlnb")));
String mbrInnbStr = StringUtil.isNullToString(map.get("mbrInnb"));
log.debug("map {}", map);
tsMssageVO.setCstmrIdnb(new BigInteger(mbrInnbStr));
tsMssageVO.setCstmrNm(StringUtil.isNullToString(map.get("mbrNm")));
tsMssageVO.setSubstWrd1("0");
tsMssageVO.setSubstWrd2("0");
tsMssageVO.setSubstWrd3("0");
tsMssageVO.setSubstWrd4("0");
tsMssageVO.setSubstWrd5("0");
return tsMssageVO;
})
.collect(Collectors.groupingBy(TsMssageVO::getSopmalCd));
}
/**
* 쇼핑몰별 그룹화된 데이터 메시지 처리
*
* @param map
* @return
*/
public List<BigInteger> processGroupedMssageData(Map<String, List<TsMssageVO>> groupedData) {
//그룹 처리 목록 FM_SMS 입력, FM_SMS에는 쇼핑몰코드별 입력
List<BigInteger> smsInnbList = new ArrayList<>();
for (Map.Entry<String, List<TsMssageVO>> entry : groupedData.entrySet()) {
if (!entry.getValue().isEmpty()) {
List<TsMssageVO> list = entry.getValue();
TsMssageVO tsMsgVO = list.get(0);
//FM_SMS 등록
mapper.insertMssageRegist(tsMsgVO);
smsInnbList.add(tsMsgVO.getSmsInnb());
//SMS_INNB 입력
list.forEach(tsMssageToVO ->
tsMssageToVO.setSmsInnb(tsMsgVO.getSmsInnb())
);
mapper.insertMssageToListRegist(list);
}
}
//대상수 설정 -> cnt 항목 수정
log.debug("smsInnbList {}", smsInnbList);
mapper.updateMssageCntUpdt(smsInnbList);
return smsInnbList;
}
/**
* 발송 대상 그룹 처리 - 이메일
* 발송 대상 목록을 쇼핑몰 별로 그룹화하여 새로운 리스트로 분리 생성
*
* @param groupedData
*/
public Map<String, List<TsEmailVO>> makeGroupedEmailData(List<DataMap> selectedList) {
return selectedList.stream()
.map(map -> {
TsEmailVO tsEmailVo = new TsEmailVO();
tsEmailVo.setSopmalCd(StringUtil.isNullToString(map.get("mainSopmalCd")));
tsEmailVo.setSndngLc("");
tsEmailVo.setRegusrDv("03");//시스템
tsEmailVo.setSj(StringUtil.isNullToString(map.get("emailSj")));
tsEmailVo.setCn(StringUtil.isNullToString(map.get("emailCn")));
tsEmailVo.setSndrEmail(StringUtil.isNullToString(map.get("email")));
return tsEmailVo;
})
.collect(Collectors.groupingBy(TsEmailVO::getSopmalCd));
}
/**
* 쇼핑몰별 그룹화된 데이터 메시지 처리
*
* @param map
* @return
*/
public List<BigInteger> processGroupedEmailData(Map<String, List<TsEmailVO>> groupedData) {
//그룹 처리 목록 FM_SMS 입력, FM_SMS에는 쇼핑몰코드별 입력
List<BigInteger> emailSndngInnbList = new ArrayList<>();
for (Map.Entry<String, List<TsEmailVO>> entry : groupedData.entrySet()) {
if (!entry.getValue().isEmpty()) {
List<TsEmailVO> list = entry.getValue();
TsEmailVO tsEmailVO = list.get(0);
mapper.insertBOEmailSndngDtls(tsEmailVO);
emailSndngInnbList.add(tsEmailVO.getEmailSndngInnb());
//SMS_INNB 입력
list.forEach(tsEmailToVO ->
tsEmailToVO.setEmailSndngInnb(tsEmailVO.getEmailSndngInnb())
);
log.debug("list {}", list);
}
}
return emailSndngInnbList;
}
//문자열 오류 처리
public String fixStr(String convertCn) {
Map<String, String> replacementMap = new HashMap<>();
replacementMap.put("&#x20a9;", "₩");
replacementMap.put("&yen;", "¥");
replacementMap.put("&euro;", "€");
replacementMap.put("&#x24;", "$");
replacementMap.put("US&dollar;", "US$");
replacementMap.put("&amp;", "&");
replacementMap.put("&lt;", "<");
replacementMap.put("&gt;", ">");
//문자열 오류 수정
return replacementMap.entrySet().stream()
.map(entry -> convertCn.replaceAll(entry.getKey(), entry.getValue()))
.reduce((str1, str2) -> str2)
.orElse(convertCn);
}
//메시지 타입 설정
public String msgType(String msg) {
//바이트 타입 변환
byte[] bytes = null;
int length = 0;
try {
bytes = msg.getBytes("UTF-8");
byte[] convertedBytes = new byte[bytes.length];
int convertedLength = 0;
for (byte b : bytes) {
if (b >= 0) {
convertedBytes[convertedLength++] = b;
}
}
length = new String(convertedBytes, 0, convertedLength, "EUC-KR").length();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String sendType = length <= 90 ? "SMS" : "LMS";
return sendType;
}
}

View File

@@ -0,0 +1,39 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import java.util.Map;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.SendToResrc;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class InsertTsRcpmnyDtlsColctTasklet implements Tasklet {
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
Map<String, Object> result = responseHandler.handleResponseAsMap(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/ordr/atmcrcpmny/insertBORcpmnyDtlsColctBatch", "")
);
log.debug("result = {}", result);
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,51 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import java.util.List;
import java.util.Map;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wb.domainserver.mapper.gcone.AtmcrcpmnyMapper;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class SelectTsOrderCancelTasklet implements Tasklet {
@Autowired
private AtmcrcpmnyMapper mapper;
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
List<DataMap> list = mapper.selectOrderCancel();
if(!list.isEmpty()) {
Map<String, Object> result = responseHandler.handleResponseAsMap(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/ordr/atmcrcpmny/selectBOOrderCancel", list)
);
log.debug("result = {}", result);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,133 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wb.domainserver.atmcrcpmny.vo.TsUpdateClearPersonalInfoShopVO;
import com.wb.domainserver.mapper.gcone.AtmcrcpmnyMapper;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class UpdateClearPersonalInfoShopTasklet implements Tasklet {
@Autowired
private AtmcrcpmnyMapper mapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
// 날짜 포맷
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 현재 날짜
// LocalDate currentDate = LocalDate.now();
// LocalDate oneYearsAgoDate = currentDate.minusMonths(12); // 현재 날짜에서 12개월 전 날짜
// LocalDate fiveYearsAgoDate = currentDate.minusMonths(60); // 현재 날짜에서 60개월 전 날짜
// String oneYearsAgo = oneYearsAgoDate.format(formatter) + " 00:00:00"; // 1년 전
// String fiveYearsAgo = fiveYearsAgoDate.format(formatter) + " 00:00:00"; // 5년 전
// 파라미터용 객체
TsUpdateClearPersonalInfoShopVO paramVO = new TsUpdateClearPersonalInfoShopVO();
// paramVO.setDeleteDate(oneYearsAgo); // 1년 전
// paramVO.setUpdateDate(fiveYearsAgo); // 5년 전
paramVO.setDeleteMonths(-12); // 현재 날짜에서 12개월 전 날짜(1년 전+일주일전 ~ 1년전)
paramVO.setUpdateMonths(-24); // 현재 날짜에서 24개월 전 날짜(2년 전+일주일전 ~ 2년전)
paramVO.setBufferDays(-7); // 현재 날짜에서 DeleteMonths or UpdateMonths 개월 전 날짜에서 일주일전을 세팅
// log.debug("paramVO = {}", paramVO);
// List<DataMap> list = mapper.selectGcSms(paramVO);
// log.debug("list = {}", list);
// String[] smsToInnb = new String[list.size()];
// for(int i = 0; i < list.size(); i++) {
// smsToInnb[i] = list.get(i).get("smsToInnb").toString();
// }
// paramVO.setSmsToInnb(smsToInnb);
// 문자/메일 관련 개인정보 삭제 쿼리
mapper.deleteGcSmsTo(paramVO);
// 이메일 발송로그
mapper.deleteGcEmailLog(paramVO);
// 이메일 대상관리
mapper.deleteGcEmailTo(paramVO);
// 주문결제
mapper.updateGcOrderSetle(paramVO);
// 배송
mapper.updateGcOrderShipping(paramVO);
// 반품
mapper.updateGcOrderRefund(paramVO);
// 매출증빙
mapper.updateGcSales(paramVO);
// 주문(마지막에 실행)
mapper.updateGcOrder(paramVO);
// // 대상 주문 선정 (개인정보 보유기한 5년, 매일 최대 100000개 까지만 처리)
// List<TsUpdateClearPersonalInfoShopVO> resultListVO = mapper.selectUpdateTrget(paramVO);
// log.debug("resultListVO = {}", resultListVO);
//
// // 주문 업데이트를할 대상이 있으면
// if(resultListVO.size() != 0) {
// String[] ordrInnbs = new String[resultListVO.size()];
//
// // select 결과 데이터 배열에 담음.
// for(int i = 0; i < resultListVO.size(); i++) {
// ordrInnbs[i] = resultListVO.get(i).getOrdrInnb();
// log.debug("ordrInnbs {} = {}", i, ordrInnbs[i]);
// }
//
// int limitCnt = 1000; // 한번에 1000개씩
// int arrCnt = (int) Math.ceil((double) resultListVO.size() / limitCnt);
//
// String[][] temp = new String[arrCnt][];
//
// // 2차원 배열에 1000개씩 나눠서 담음.
// for(int i = 0; i < arrCnt; i++) {
// int start = i * limitCnt;
// int end = Math.min(start + limitCnt, resultListVO.size());
// temp[i] = new String[end - start];
//
// System.arraycopy(ordrInnbs, start, temp[i], 0, end - start);
// }
//
// for(int i = 0; i < temp.length; i++) {
// paramVO.setOrdrInnbs(temp[i]);
//
// // 배송
// mapper.updateGcOrderShipping(paramVO);
// // 반품
// mapper.updateGcOrderRefund(paramVO);
// // 매출증빙
// mapper.updateGcSales(paramVO);
// // 주문
// mapper.updateGcOrder(paramVO);
// // 주문결제
// mapper.updateGcOrderSetle(paramVO);
// }
// }
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,49 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import java.util.List;
import java.util.Map;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wb.domainserver.mapper.gcone.AtmcrcpmnyMapper;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class UpdateTsCshRciptRegistTasklet implements Tasklet {
@Autowired
private AtmcrcpmnyMapper mapper;
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
// 현금영수증 신청 할 데이터 조회
List<DataMap> resultList = mapper.selectCshRciptRegist();
Map<String, Object> result = responseHandler.handleResponseAsMap(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/ordr/selngpruf/insertBOCshRciptRegistBatch", resultList)
);
log.debug("result = {}", result);
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,45 @@
package com.wb.domainserver.atmcrcpmny.tasklet;
import java.util.Map;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wb.domainserver.mapper.gcone.AtmcrcpmnyMapper;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.SendToResrc;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class UpdateTsRcpmnyCnfirmAtmcMtchgTasklet implements Tasklet {
@Autowired
private AtmcrcpmnyMapper mapper;
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
Map<String, Object> result = responseHandler.handleResponseAsMap(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/ordr/atmcrcpmny/updateBORcpmnyCnfirmExecutBatch", "")
);
log.debug("result = {}", result);
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,57 @@
package com.wb.domainserver.atmcrcpmny.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
* 해당 클래스에 대한 설명을 입력하세요.
* @author 임수영.
* @since 2024-07-08
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-07-08 임수영 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsCshRciptRegistVO {
private static final long serialVersionUID = 1L;
/** 쇼핑몰코드 */
private String sopmalCd;
/** 매출증빙고유번호 */
private String selngPrufInnb;
/** 주문결제번호 */
private String ordrSetleInnb;
/** 주문고유번호 */
private String ordrInnb;
/** 주문자명 */
private String ordrrNm;
/** 주문자email */
private String ordrrEmail;
/** 인증번호 */
private String crtnb;
/** 상품명 */
private String goodsNm;
/** 발급대상구분코드 */
private String issuTrgetDvCd;
/** 금액 */
private String amt;
/** 공급가액 */
private String splpric;
/** 부가세액 */
private String vatAmt;
}

View File

@@ -0,0 +1,25 @@
package com.wb.domainserver.atmcrcpmny.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsDepositRequestVO {
private static final long serialVersionUID = 1L;
// 주문(fm_order)
/** 쇼핑몰코드*/
private String sopmalCd;
/** 주문고유번호 */
private String ordrInnb;
/** 주문자 휴대전화 */
private String ordrrMbtlnb;
/** 회원고유번호 */
private String mbrInnb;
/** 주문자명 */
private String ordrrNm;
}

View File

@@ -0,0 +1,19 @@
package com.wb.domainserver.atmcrcpmny.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsOrderCancelVO {
private static final long serialVersionUID = 1L;
/** 쇼핑몰코드*/
private String sopmalCd;
/** 주문고유번호 */
private String ordrInnb;
//
}

View File

@@ -0,0 +1,53 @@
package com.wb.domainserver.atmcrcpmny.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
* 해당 클래스에 대한 설명을 입력하세요.
* @author 임수영.
* @since 2024-07-30
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-07-30 임수영 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsUpdateClearPersonalInfoShopVO {
private static final long serialVersionUID = 1L;
/** 쇼핑몰코드 */
private String sopmalCd;
/** 주문고유번호 */
private String ordrInnb;
/** 주문고유번호 */
private String ordrInnbs[];
/** 수정일 */
private String updateDate;
/** 삭제일 */
private String deleteDate;
/** SMS 대상고유번호 */
private String smsToInnb[];
/** 삭제월수 */
private Integer deleteMonths;
/** 수정월수 */
private Integer updateMonths;
/** 수정 버퍼수 */
private Integer bufferDays;
}

View File

@@ -0,0 +1,69 @@
package com.wb.domainserver.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class ApiSvc {
public String getConnect(String Url) throws Exception {
HttpURLConnection con = connect(Url);
try {
con.setRequestMethod("GET");
con.setRequestProperty("Content-Type", "application/json");
int responseCode = con.getResponseCode();
log.debug("responseCode : " + responseCode);
if(responseCode == HttpURLConnection.HTTP_OK) {
return readBody(con.getInputStream());
} else {
return readBody(con.getErrorStream());
}
}catch (IOException e) {
throw new Exception("API 요청과 응답 실패",e);
}finally {
con.disconnect();
}
}
public HttpURLConnection connect(String apiUrl) throws Exception {
try {
URL url = new URL(apiUrl);
return (HttpURLConnection)url.openConnection();
}catch (MalformedURLException e) {
throw new Exception("API URL이 잘못되었습니다. : "+apiUrl,e);
}catch (IOException e) {
throw new Exception("연결이 실패했습니다. : "+apiUrl,e);
}
}
public String readBody(InputStream body) throws Exception {
InputStreamReader streamReader = new InputStreamReader(body, "UTF-8");
try (BufferedReader lineReader = new BufferedReader(streamReader)){
StringBuilder responseBody = new StringBuilder();
String line;
while((line = lineReader.readLine()) != null) {
responseBody.append(line);
}
return responseBody.toString();
} catch (IOException e) {
throw new Exception("API 응답을 읽는데 실패했습니다.",e);
}
}
}

View File

@@ -0,0 +1,19 @@
package com.wb.domainserver.common;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class CommonService {
@Value("${secret.key}")
private String secretKey;
/**
* 암호화키 조회
* @return String
*/
public String selectSecretkey() {
return secretKey;
}
}

View File

@@ -0,0 +1,51 @@
package com.wb.domainserver.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@MapperScan(
basePackages = "com.wb.domainserver.mapper.crm",
sqlSessionFactoryRef = "crmSqlSessionFactory"
)
public class CrmDataSourceConfig {
@Bean(name = "crmDataSource")
@ConfigurationProperties(prefix = "spring.datasource.crmdatasource")
public DataSource crmDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "crmSqlSessionFactory")
public SqlSessionFactory crmSqlSessionFactory(@Qualifier("crmDataSource") DataSource crmDataSource) throws Exception {
// SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
SqlSessionFactoryBean sessionFactory = new RefreshableSqlSessionFactoryBean();
sessionFactory.setDataSource(crmDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/xml/mapper/crm/**/*.xml"));
sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis/xml/config/mapper-config.xml"));
return sessionFactory.getObject();
}
@Bean(name = "crmTransactionManager")
public PlatformTransactionManager crmTransactionManager(@Qualifier("crmDataSource") DataSource crmDataSource) {
return new DataSourceTransactionManager(crmDataSource);
}
}

View File

@@ -0,0 +1,74 @@
package com.wb.domainserver.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@MapperScan(
basePackages = "com.wb.domainserver.mapper.gcone",
sqlSessionFactoryRef = "gconeSqlSessionFactory"
)
public class GconeSourceConfig {
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.defaultdatasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "gconeDataSource")
@ConfigurationProperties(prefix = "spring.datasource.gconedatasource")
public DataSource gconeDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "gconeSqlSessionFactory")
@Primary
public SqlSessionFactory gconeSqlSessionFactory(@Qualifier("gconeDataSource") DataSource gconeDataSource) throws Exception {
// SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
SqlSessionFactoryBean sessionFactory = new RefreshableSqlSessionFactoryBean();
sessionFactory.setDataSource(gconeDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/xml/mapper/gcone/**/*.xml"));
sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis/xml/config/mapper-config.xml"));
return sessionFactory.getObject();
}
@Bean(name = "transactionManager")
@Primary
public PlatformTransactionManager transactionManager(@Qualifier("gconeDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "gconeTransactionManager")
public PlatformTransactionManager gconeTransactionManager(@Qualifier("gconeDataSource") DataSource gconeDataSource) {
return new DataSourceTransactionManager(gconeDataSource);
}
@Bean
public JobRepository jobRepository( @Qualifier("gconeTransactionManager") PlatformTransactionManager transactionManager, @Qualifier("gconeDataSource") DataSource gconeDataSource) throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(gconeDataSource);
factory.setTransactionManager(transactionManager);
factory.afterPropertiesSet();
return factory.getObject();
}
}

View File

@@ -0,0 +1,51 @@
package com.wb.domainserver.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@MapperScan(
basePackages = "com.wb.domainserver.mapper.mq",
sqlSessionFactoryRef = "mqSqlSessionFactory"
)
public class MqDataSourceConfig {
@Bean(name = "mqDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mqdatasource")
public DataSource mqDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "mqSqlSessionFactory")
public SqlSessionFactory mqSqlSessionFactory(@Qualifier("mqDataSource") DataSource mqDataSource) throws Exception {
// SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
SqlSessionFactoryBean sessionFactory = new RefreshableSqlSessionFactoryBean();
sessionFactory.setDataSource(mqDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/xml/mapper/mq/**/*.xml"));
sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis/xml/config/mapper-config.xml"));
return sessionFactory.getObject();
}
@Bean(name = "mqTransactionManager")
public PlatformTransactionManager mqTransactionManager(@Qualifier("mqDataSource") DataSource mqDataSource) {
return new DataSourceTransactionManager(mqDataSource);
}
}

View File

@@ -0,0 +1,156 @@
package com.wb.domainserver.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {
private static final Logger LOG = LoggerFactory.getLogger(RefreshableSqlSessionFactoryBean.class);
private SqlSessionFactory proxy;
private int interval = 1000;
private Timer timer;
private TimerTask task;
private Resource[] mapperLocations;
private boolean running = false;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public void setMapperLocations(Resource[] mapperLocations) {
super.setMapperLocations(mapperLocations);
this.mapperLocations = mapperLocations;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void refresh() throws Exception {
w.lock();
try {
super.afterPropertiesSet();
} finally {
w.unlock();
}
LOG.info("sqlMapClient refreshed.");
}
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
}
private void setRefreshable() {
proxy = (SqlSessionFactory) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSessionFactory.class}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(getParentObject(), args);
}
});
task = new TimerTask() {
private Map<Resource, Long> map = new HashMap<Resource, Long>();
public void run() {
if (isModified()) {
try {
refresh();
} catch (Exception e) {
LOG.error("caught exception", e);
}
}
}
private boolean isModified() {
boolean retVal = false;
if (mapperLocations != null) {
for (int i = 0; i < mapperLocations.length; i++) {
Resource mappingLocation = mapperLocations[i];
retVal |= findModifiedResource(mappingLocation);
}
}
return retVal;
}
private boolean findModifiedResource(Resource resource) {
boolean retVal = false;
List<String> modifiedResources = new ArrayList<String>();
try {
long modified = resource.lastModified();
if (map.containsKey(resource)) {
long lastModified = map.get(resource).longValue();
if (lastModified != modified) {
map.put(resource, modified);
modifiedResources.add(resource.getDescription());
retVal = true;
}
} else {
map.put(resource, modified);
}
} catch (IOException e) {
LOG.error("caught exception", e);
}
if (retVal) {
LOG.info("modified files : " + modifiedResources);
}
return retVal;
}
};
timer = new Timer(true);
resetInterval();
}
private Object getParentObject() throws Exception {
r.lock();
try {
return super.getObject();
} finally {
r.unlock();
}
}
public SqlSessionFactory getObject() throws Exception {
if (this.proxy == null) {
setRefreshable();
}
return this.proxy;
}
public Class<? extends SqlSessionFactory> getObjectType() {
return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class);
}
public boolean isSingleton() {
return true;
}
public void setCheckInterval(int ms) {
interval = ms;
if (timer != null) {
resetInterval();
}
}
private void resetInterval() {
if (running) {
timer.cancel();
running = false;
}
if (interval > 0) {
timer.schedule(task, 0, interval);
running = true;
}
}
public void destroy() throws Exception {
timer.cancel();
}
}

View File

@@ -0,0 +1,49 @@
package com.wb.domainserver.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@MapperScan(
basePackages = "com.wb.domainserver.mapper.sure",
sqlSessionFactoryRef = "sureSqlSessionFactory"
)
public class SureDataSourceConfig {
@Bean(name = "sureDataSource")
@ConfigurationProperties(prefix = "spring.datasource.suredatasource")
public DataSource sureDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sureSqlSessionFactory")
public SqlSessionFactory sureSqlSessionFactory(@Qualifier("sureDataSource") DataSource sureDataSource) throws Exception {
// SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
SqlSessionFactoryBean sessionFactory = new RefreshableSqlSessionFactoryBean();
sessionFactory.setDataSource(sureDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/xml/mapper/sure/**/*.xml"));
sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis/xml/config/mapper-config.xml"));
return sessionFactory.getObject();
}
@Bean(name = "sureTransactionManager")
public PlatformTransactionManager mqTransactionManager(@Qualifier("sureDataSource") DataSource sureDataSource) {
return new DataSourceTransactionManager(sureDataSource);
}
}

View File

@@ -0,0 +1,41 @@
package com.wb.domainserver.common.vo;
import lombok.Data;
import java.io.Serializable;
import java.sql.Date;
@Data
public abstract class AbstractVO implements Serializable {
private static final long serialVersionUID = 1L;
/** 사용여부 */
private String useAt;
/** 등록자 */
private int regusr;
/** 등록일시 */
private Date registDt;
/** 등록일자 */
private String registDe;
/** 수정자 */
private int updusr;
/** 수정일시 */
private Date updtDt;
/** 수정일자 */
private String updtDe;
/** 현재페이지 */
private int pageIndex = 1;
/** 페이지갯수 */
private int pageUnit = 10;
/** 페이지사이즈 */
private int pageSize = 10;
/** 첫페이지 인덱스 */
private int firstIndex = 1;
/** 마지막페이지 인덱스 */
private int lastIndex = 1;
/** 페이지당 레코드 개수 */
private int recordCountPerPage = 10;
/** pagination객체 */
// private PaginationInfo paginationInfo;
}

View File

@@ -0,0 +1,15 @@
package com.wb.domainserver.common.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommVO {
private String sopmalCd;
}

View File

@@ -0,0 +1,149 @@
package com.wb.domainserver.controller;
import com.wb.domainserver.common.vo.CommVO;
import com.wb.domainserver.pos.vo.PosReqVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.wb.domainserver.response.ApiResponse;
import com.wb.domainserver.util.dataaccess.DataMap;
import java.util.UUID;
@RestController
@RequestMapping("/batch")
@Slf4j
public class BatchJobController {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private ApplicationContext applicationContext;
@PostMapping("/run/{jobName}")
public ResponseEntity<?> runBatchJob(@PathVariable String jobName) {
log.debug(" 파라미터 받은 jobName 확인 : " + jobName);
JobParameters params = new JobParametersBuilder()
.addLong("currTime", System.currentTimeMillis()) // 고유값 추가
.toJobParameters();
log.debug(" jobParameters : " + params);
DataMap message = new DataMap();
try {
// JobExecution 객체로 실행 결과 받기
Job job = (Job) applicationContext.getBean(jobName);
JobExecution jobExecution = jobLauncher.run(job, params);
// Job의 실행 상태 확인
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
message.put("result", "Job executed successfully");
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
} else {
message.put("result", "Job failed or is still running: " + jobExecution.getStatus());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
message.put("result", "Job execution failed: " + e.getMessage());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
};
@PostMapping("/run/mq/{jobName}")
public ResponseEntity<?> runBatchJob(@PathVariable String jobName, @RequestBody CommVO vo) {
System.out.println(" 파라미터 받은 jobName 확인 : " + jobName);
System.out.println(" 파라미터 받은 VO 확인33 : " + vo);
JobParameters params = new JobParametersBuilder()
.addString("currTime", vo.getSopmalCd()+":"+System.currentTimeMillis()) // 고유값 추가
.toJobParameters();
System.out.println(" jobParameters : " + params);
DataMap message = new DataMap();
try {
// JobExecution 객체로 실행 결과 받기
Job job = (Job) applicationContext.getBean(jobName);
JobExecution jobExecution = jobLauncher.run(job, params);
String resultMsg = "";
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
ExecutionContext stepContext = stepExecution.getExecutionContext();
if (stepContext.containsKey("resultMsg")) {
resultMsg = stepContext.getString("resultMsg");
break;
}
}
log.debug(" stepExecution : resultMsg " + resultMsg);
// Job의 실행 상태 확인
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
message.put("result", "Job executed successfully");
message.put("resultMsg", resultMsg); // 추가된 resultMsg 반환
log.debug(" 배치 컨트롤러에서 성공하고 결과값 확인 : {} " + message);
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
} else {
message.put("result", "Job failed or is still running: " + jobExecution.getStatus());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
message.put("result", "Job execution failed: " + e.getMessage());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
};
/**
* 포스 수동 조회
* @return
*/
@RequestMapping("/run/pos/{jobName}")
public ResponseEntity<?> runPosBatchJob(@PathVariable String jobName, @RequestBody PosReqVO vo) {
log.debug(" 파라미터 받은 jobName 확인 : {} ", jobName);
log.debug(" 받은 파라미터 확인 : {}", vo);
String paramSet = System.currentTimeMillis() + ":" + vo.toString() ;
JobParameters params = new JobParametersBuilder()
.addString("currTime", paramSet) // 고유값 추가
.toJobParameters();
log.debug(" jobParameters : {}",params);
DataMap message = new DataMap();
try {
// JobExecution 객체로 실행 결과 받기
Job job = (Job) applicationContext.getBean(jobName);
JobExecution jobExecution = jobLauncher.run(job, params);
// Job의 실행 상태 확인
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
message.put("result", "Job executed successfully");
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
} else {
message.put("result", "Job failed or is still running: " + jobExecution.getStatus());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
message.put("result", "Job execution failed: " + e.getMessage());
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.NOT_FOUND);
}
};
}

View File

@@ -0,0 +1,86 @@
package com.wb.domainserver.controller;
import com.wb.domainserver.response.ApiResponse;
import com.wb.domainserver.service.MssageJobService;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/batch/mssage")
@RequiredArgsConstructor
public class MssageJobController {
private final MssageJobService service;
/**
* 회원 등급 변경 메시지
*/
/**
* 광고 동의 안내 메시지
* @return
*/
@GetMapping(value = "/marktAgreMbr")
public ResponseEntity<?> runMssageMarktAgreMbrJob() {
DataMap message = new DataMap();
message.put("result", service.runMssageMarktAgreJob("force"));
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
}
/**
* 만료 마일리지 안내
* @return
*/
@GetMapping(value = "/mlgExp")
public ResponseEntity<?> runMessageMlgExpJob() {
DataMap message = new DataMap();
service.runMssageMlgExpJob("force");
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
}
/**
* 입금 요청 안내
* @return
*/
@GetMapping(value = "/depositRequest")
public ResponseEntity<?> runMssageDepositRequestJob() {
DataMap message = new DataMap();
service.runMssageDepositRequestJob("force");
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
}
/**
* 문자 상태 갱신
* @return
*/
@GetMapping(value = "/updtSttus")
public ResponseEntity<?> runMssageUpdtSttusJob() {
DataMap message = new DataMap();
message.put("result", service.runMssageUpdtSttusJob("force"));
return ApiResponse.of(message).ifPresentOrElse(HttpStatus.OK, HttpStatus.NOT_FOUND);
}
}

View File

@@ -0,0 +1,119 @@
package com.wb.domainserver.coupon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
* 쿠폰 VO
* @author 추지훈
* @since 2023-12-27
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-27 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsCouponPkSndngVO {
private static final long serialVersionUID = 1L;
// 쿠폰(팩) 발송 정보
/** 쇼핑몰코드 */
private String sopmalCd;
/** 쿠폰발송 고유번호 */
private Integer couponSndngInnb;
/** 이메일 발송양식 고유번호 */
private String emailSndngFormInnb;
/** SMS발송양식 고유번호 */
private String smsSndngFormInnb;
/** 알림톡 발송양식 고유번호 */
private String ntcntalkSndngFormInnb;
/** 발송구분 */
private String sndngDv;
/** 쿠폰발송유형 */
private String couponSndngTy;
/** 쿠폰발송명 */
private String couponSndngNm;
/** 쿠폰발송설명 */
private String couponSndngDc;
/** 쿠폰발송 사용여부 */
private String couponSndngUseAt;
/** 다운로드 기간 제한 여부 */
private String dwldPdLmttAt;
/** 다운시작일시 */
private String dwldBgnDt;
/** 다운종료일시 */
private String dwldEndDt;
/** 발송일시구분 */
private String sndngDtDvCd;
/** 발송일시 */
private String sndngDt;
/** 발송주기 */
private String sndngCycle;
/** 월발송주기일자 */
private String mtSndngCycleDe;
/** 발송대상 구분 */
private String sndngTrgetDv;
/** 사용 여부 */
private String useAt;
// 검색
/** 검색_쿠폰발송명 */
private String searchCouponPkSndngNm;
/** 검색_발송구분 */
private String searchSndngDv;
/** 검색_쿠폰발송 사용여부 */
private String searchCouponSndngUseAt;
/** 검색_쿠폰발송유형 */
private String[] searchCouponSndngTy;
/** 검색_사용여부 */
private String searchUseAt;
/**
* 쿠폰(팩) 등급대상
*/
/** 쿠폰등급제한 고유번호 */
private Integer couponGradLmttInnb;
/** 회원등급 고유번호 등급 대상을 받을 문자열 */
private String trgetMbrGradeInnbs;
/** 회원등급 고유번호 등급 대상 배열 */
private int[] trgetMbrGradeArray;
/** 회원등급 고유번호 등급 대상 */
private Integer mbrGradInnb;
/**
* 쿠폰(팩) 발송대상쿠폰
*/
/** 발송대상 고유번호 */
private Integer sndngTrgetInnb;
/** 쿠폰 고유번호 */
private Integer couponInnb;
/** 쿠폰팩에 매칭된 쿠폰들을 받을 문자열 */
private String packedCouponInnbs;
/** packedCouponInnbs 문자열을 배열로 전환 */
private int[] packedCouponArray;
/** 쿠폰팩 고유번호 */
private Integer cupnpkInnb;
}

View File

@@ -0,0 +1,237 @@
package com.wb.domainserver.coupon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
*
* 쿠폰 VO
* @author 추지훈
* @since 2023-12-11
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-11 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsCouponVO {
private static final long serialVersionUID = 1L;
/**
* 쿠폰정보
*/
/** 인증번호 개수 */
private Integer offlineCnt;
// 발송 대상 쿠폰 조회
/** 쿠폰팩 고유번호 */
private Integer cupnpkInnb;
/** 쿠폰 발송 대상 고유번호 */
private String sndngTrgetInnb;
/** 쿠폰발송 고유번호 */
private String couponSndngInnb;
/** 쿠폰 고유번호 */
private Integer couponInnb;
/** 쇼핑몰 코드 */
private String sopmalCd;
/** 쿠폰명 */
private String coupNm;
/** 쿠폰 설명 */
private String couponDc;
/** 사용환경코드 */
private String useEnvrnCd;
/** 단독사용, 공동사용 */
private String otrCouponSmtmUseAt;
/** 중복다운로드여부 */
private String dplctDwldAt;
/** 중복할인여부 */
private String dplctDscntAt;
/** 사용가능금액 */
private String usePosblAmt;
/** 상품카테고리 제한구분( 전체상품(all), 상품/카테고리(issue) ) */
private String goodsCtgryLmttDv;
/** 수량 제한여부 */
private String qyLmttAt;
/** 제한수량 */
private String lmttQy;
/** 기간설정, 발금(다운로드)일 기준 */
private String validpdKnd;
/** 유효기간시작일시 */
private String validpdBgnDt;
/** 유효기간시작일시 포맷 yyyy-mm-dd */
private String validpdBgnDe;
/** 유효기간종료일시 */
private String validpdEndDt;
/** 유효기간종료일시 포맷 yyyy-mm-dd */
private String validpdEndDe;
/** 유효기간일수 */
private String validpdDeCnt;
/** 유효기간일수 */
private String validpdCntDe;
/** 쿠폰팩 등록가능여부 */
private String cupnpkRegistPosblAt;
/** 타브랜드 쿠폰팩 등록가능여부 */
private String otrBrndCpnpkRgstPsblAt;
/** 쿠폰 사용여부 */
private String couponUseAt;
// 쿠폰 혜택
/** 쿠폰 혜택 고유번호 */
private Integer couponBnefInnb;
/** 혜택구분 */
private String bnefDv;
/** 상품할인구분 */
private String goodsDscntDv;
/** */
// private String selectAditDscnt;
/** 추가할인금액 */
private String aditDscntAmt;
/** 추가할인비율 */
private String aditDscntRt;
/** 할인최대금액 */
private String dscntMxmmAmt;
/** 무료, 금액 */
private String dlvyAmtDscntDv;
/** 배송비할인금액 */
private String dlvyAmtDscntAmt;
/** 배송비최대할인금액 */
private String dlvyAmtMxmmDscntAmt;
// 쿠폰 적용 상품
/** 상품 적용 구분 코드 */
private String goodsApplcDvCd;
/** 선택한 카테고리 */
private String[] reprsntCtgryId;
/** 선택한 상품 */
private String[] relatedGoodsId;
/** 상품 고유번호 */
private String goodsInnb;
/** 상위 카테고리 */
private String upperCtgryId;
/** 쿠폰 적용상품 고유번호 */
private Integer couponApplcGoodsInnb;
/** 상품적용구분 */
private String goodsApplcDv;
/** 판매상품 고유번호 */
private Integer sleGoodsInnb;
/** 혜택 적용 판매상품 고유번호 리스트 */
private List<Integer> sleGoodsInnbList;
/** 혜택 제외 판매상품 고유번호 리스트 */
private List<Integer> ExclSleGoodsInnbList;
/** 카테고리 ID */
private Integer ctgryId;
/** 혜택 적용 카테고리 ID 리스트 */
private List<Integer> ctgryIdList;
/** 혜택 제외 카테고리 ID 리스트 */
private List<Integer> ExclCtgryIdList;
// 쿠폰매장연동
/** POS 본부코드 */
private String posHdqrtrsCd;
private List<String> posHdqrtrsCdList;
/** POS 등록년도 */
private String posCouponRegistYear;
private List<String> posCouponRegistYearList;
/** POS 쿠폰코드 */
private String posCouponCd;
private List<String> posCouponCdList;
// 쇼핑몰
/** 쇼핑몰 명 */
private String sopmalNm;
// 검색조건
/** 검색_쿠폰명 */
private String searchCoupNm;
/** 검색_혜택구분 */
private String[] searchBnefDv;
/** 검색_타 쿠폰동시사용여부 */
private String searchOtrCouponSmtmUseAt;
/** 검색_사용여부 */
private String searchUseAt;
/** 검색_사용환경코드 */
private String[] searchUseEnvrnCd;
/** 검색_중복할인 */
private String searchDplctDscntAt;
/** 검색_쇼핑몰 코드 */
private String searchSopmalCd;
/** 검색_인증번호 */
private String srchCrtnb;
/** 그룹 코드 */
private String groupCd;
/** 쿠폰 발송 유형 코드 */
private String couponSndngTy;
/** 쿠폰발송 대상 고유번호 */
private Integer couponSndngTrgetInnb;
/***************************************************
* 인증번호
***************************************************/
/** 인증번호 생성 개수 */
private String createQy;
/** 오프라인쿠폰 고유번호 */
private Integer oflneCouponInnb;
/** 오프라인쿠폰 생성번호 */
private String oflneCouponCreateNb;
/** 오프라인쿠폰 인증번호 */
private String oflneCouponCrtnb;
/** 사용 건수 */
private String useCnt;
/** 발송대상자명 */
private String sndngTrgetrNm;
/** 발송대상전화번호 */
private String sndngTrgetTelnb;
}

View File

@@ -0,0 +1,230 @@
package com.wb.domainserver.coupon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigInteger;
import java.util.List;
/**
*
* 쿠폰 VO
* @author 추지훈
* @since 2023-12-11
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-11 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsDwldCouponVO {
private static final long serialVersionUID = 1L;
/**
* 쿠폰정보
*/
/** 다운로드 쿠폰 고유번호 */
private Integer dwldCouponInnb;
/** 쿠폰 고유번호 */
private Integer couponInnb;
/** 회원 고유번호 */
private BigInteger mbrInnb;
/** 회원 구분 코드 */
private String mbrDvCd;
/** 회원 명 */
private String mbrNm;
/** 회원 휴대폰번호 */
private String mbtlnb;
/** 쿠폰팩 고유번호 */
private Integer cupnpkInnb;
/** 오프라인쿠폰 고유번호 */
private Integer oflneCouponInnb;
/** 쿠폰 발송 고유번호 */
private Integer couponSndngInnb;
/** 쿠폰 발송 유형코드 */
private String couponSndngTy;
/** 발송구분 */
private String sndngDv;
/** 발송대상 구분 */
private String sndngTrgetDv;
/** 쇼핑몰 코드 */
private String sopmalCd;
/** 다운로드 쿠폰팩명 */
private String cupnpkNm;
/** 다운로드 쿠폰팩 설명 */
private String cupnpkDc;
/** 다운로드 쿠폰명 */
private String coupNm;
/** 다운로드 쿠폰 설명 */
private String couponDc;
/** 사용환경코드 */
private String useEnvrnCd;
/** 단독사용, 공동사용 */
private String otrCouponSmtmUseAt;
/** 중복다운로드여부 */
private String dplctDwldAt;
/** 중복할인여부 */
private String dplctDscntAt;
/** 사용가능금액 */
private String usePosblAmt;
/** 상품카테고리 제한구분( 전체상품(all), 상품/카테고리(issue) ) */
private String goodsCtgryLmttDv;
/** 유효기간 종류 구분 코드 */
private String validpdKndCd;
/** 유효기간시작일시 */
private String validpdBgnDt;
/** 유효기간시작일시 포맷 yyyy-mm-dd */
private String validpdBgnDe;
/** 유효기간종료일시 */
private String validpdEndDt;
/** 유효기간종료일시 포맷 yyyy-mm-dd */
private String validpdEndDe;
/** 유효기간 남은 일수 */
private String validpdDay;
/** 쿠폰 사용여부 */
private String couponUseAt;
/** 쿠폰 사용 일시 */
private String couponUseDt;
/** 오프라인쿠폰 인증번호 */
private String oflneCouponCrtnb;
/** 사용처구분 */
private String useplcDvCd;
/** 복원 원본쿠폰 */
private String recovryOrginlCoupon;
/** 쿠폰상태코드 */
private String couponSttusCd;
/** 사용자 다운로드할 쿠폰 목록 */
private List<TsUserDwldVO> downloadCouponList;
// 쿠폰 혜택
/** 다운로드 쿠폰 혜택 고유번호 */
private Integer dwldCouponBnefInnb;
/** 혜택구분 */
private String bnefDv;
/** 상품할인구분 */
private String goodsDscntDv;
/** 추가할인금액 */
private String aditDscntAmt;
/** 추가할인비율 */
private String aditDscntRt;
/** 할인최대금액 */
private String dscntMxmmAmt;
/** 무료, 금액 */
private String dlvyAmtDscntDv;
/** 배송비할인금액 */
private String dlvyAmtDscntAmt;
/** 배송비최대할인금액 */
private String dlvyAmtMxmmDscntAmt;
// 쿠폰 적용 상품
/** 쿠폰 적용상품 고유번호 */
private Integer dwldCouponApplcGoodsInnb;
/** 상품적용구분 */
private String goodsApplcDv;
/** 판매상품 고유번호 */
private Integer sleGoodsInnb;
/** 혜택 적용 판매상품 고유번호 리스트 */
private List<Integer> sleGoodsInnbList;
/** 혜택 제외 판매상품 고유번호 리스트 */
private List<Integer> ExclSleGoodsInnbList;
/** 카테고리 ID */
private String ctgryId;
/** 대상 상품 고유번호 */
private String goodsInnb;
/** 혜택 적용 카테고리 ID 리스트 */
private List<Integer> ctgryIdList;
/** 혜택 제외 카테고리 ID 리스트 */
private List<Integer> ExclCtgryIdList;
// 검색조건
/** 검색_회원아이디, 회원명 */
private String searchKeyword;
/** 검색_발급일 시작 */
private String srchStartDate;
/** 검색_발급일 종료 */
private String srchEndDate;
/** 검색_다운로드쿠폰사용여부 */
private String srchUseAt;
/** 쿠폰 발급 혹은 쿠폰 등록 시 */
private String[] couponArray;
/** 그룹 코드 */
private String groupCd;
/** 주문 고유번호 ( 주문 쿠폰 사용 내역 조회 ) */
private String ordrInnb;
private String ordrRefundInnb;
/** JSON 형태의 회원 리스트 ( 발급하기 ) */
private String jsonMbrList;
/** 발송 대상 구분 ( 사람, 업체 ) */
private String targetDv;
/** 발송대상자명 */
private String sndngTrgetNm;
/** 발송대상전화번호 */
private String sndngTrgetTelnb;
/** 발송 수량 _ 발송 대상 구분이 업체일 경우에만 해당됨. */
private String sndngQy;
//메시지 관련
/** 발송 일시 구분 */
private String sndngDtDvCd;
// 쿠폰 사용처리
/** 포스본부코드 */
private String posHdqrtrsCd;
private String couponUseDtlsInnb;
private String manageMemo;
/**
* 서버 구분
*/
private String serverDv;
private String regusr;
private String registDt;
private String updusr;
private String updDt;
}

View File

@@ -0,0 +1,46 @@
package com.wb.domainserver.coupon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
* 발송 대상 VO
* @author 추지훈
* @since 2023-12-11
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-11 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsSndngMbrJsonVO {
private static final long serialVersionUID = 1L;
/** 쇼핑몰 코드 */
private String sopmalCd;
/** 회원 고유번호 */
private String mbrInnb;
/** 회원 구분 코드 */
private String mbrDvCd;
/** 대상자명 */
private String recpntNm;
/** 대상자 휴대폰번호 */
private String sndngMbtlnb;
/** 대상자 이메일 */
private String sndngEmail;
}

View File

@@ -0,0 +1,65 @@
package com.wb.domainserver.coupon.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
* 쿠폰 VO
* @author 추지훈
* @since 2023-12-11
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2023-12-11 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsUserDwldVO {
private static final long serialVersionUID = 1L;
/** 다운로드쿠폰 고유번호 */
private Integer dwldCouponInnb;
/** 쿠폰 고유번호 */
private Integer couponInnb;
/** 쿠폰명 */
private String coupNm;
/** 쿠폰설명 */
private String couponDc;
/** 쇼핑몰 코드 */
private String sopmalCd;
/** 회원고유번호 */
private Integer mbrInnb;
/** 회원구분코드 */
private String mbrDvCd;
/** 쿠폰팩고유번호 */
private Integer cupnpkInnb;
/** 오프라인쿠폰 고유번호 */
private Integer oflneCouponInnb;
/** 쿠폰발송 고유번호 */
private Integer couponSndngInnb;
/** 쿠폰팩 명 */
private String cupnpkNm;
/** 쿠폰팩 설명 */
private String cupnpkDc;
/** 회원 명 */
private String mbrNm;
/** 휴대폰번호 */
private String mbtlnb;
/** 오프라인쿠폰 인증번호 */
private String oflneCouponCrtnb;
/** 사용처 구분 */
private String useplcDvCd;
}

View File

@@ -0,0 +1,73 @@
package com.wb.domainserver.crm.jobs;
import com.wb.domainserver.crm.tasklet.InsertExtOrdrTasklet;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.listener.ExecutionContextPromotionListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
/**
* CRM(ERP) 관련 배치
*
* @author 추지훈
* @since 2024.06.10
* @version 1.0
*/
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class CrmExtOrdrConfig extends DefaultBatchConfiguration{
private static final Logger logger = LoggerFactory.getLogger(CrmExtOrdrConfig.class);
private final SqlSessionFactory sqlSessionFactory;
private final InsertExtOrdrTasklet insertExtOrdrTasklet;
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[]{"message"});
return listener;
}
/* ##############################################################################################
외부 주문 등록
################################################################################################# */
/* @param jobRepository
* @param transactionManager
* @return
*/
@Bean
public Job crmGetExtOrdrJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new JobBuilder("crmGetExtOrdrJob", jobRepository)
.start(insertExtOrdrStep(jobRepository, transactionManager, promotionListener))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 1. GCONE 외부 주문 MAX값 조회
* 2.erp GC_ERP_PURCHSR_INFO에서 외부주문 조회
* 3. GCONE GC_ERP_ORDER 등록
*/
@Bean
public Step insertExtOrdrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertExtOrdrStep", jobRepository)
.tasklet(insertExtOrdrTasklet, transactionManager)
.listener(promotionListener)
.build();
}
}

View File

@@ -0,0 +1,103 @@
package com.wb.domainserver.crm.jobs;
import com.wb.domainserver.crm.tasklet.InsertTsDelMbrAppnRegistTasklet;
import com.wb.domainserver.crm.tasklet.InsertTsMbrAppnRegistTasklet;
import com.wb.domainserver.crm.tasklet.InsertTsRegMbrAppnRegistTasklet;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.listener.ExecutionContextPromotionListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
/**
* CRM(ERP) 관련 배치
*
* @author 추지훈
* @since 2024.06.10
* @version 1.0
*/
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class CrmMemberAppnConfig extends DefaultBatchConfiguration{
private static final Logger logger = LoggerFactory.getLogger(CrmMemberAppnConfig.class);
private final SqlSessionFactory sqlSessionFactory;
private final InsertTsDelMbrAppnRegistTasklet insertTsDelMbrAppnRegistTasklet;
private final InsertTsMbrAppnRegistTasklet insertTsMbrAppnRegistTasklet;
private final InsertTsRegMbrAppnRegistTasklet insertTsRegMbrAppnRegistTasklet;
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[]{"message"});
return listener;
}
/* ##############################################################################################
블랙리스트
################################################################################################# */
/* @param jobRepository
* @param transactionManager
* @return
*/
@Bean
public Job mqGetMbrAppnJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new JobBuilder("mqGetMbrAppnJob", jobRepository)
.start(insertDelAppnLogRegistStep(jobRepository, transactionManager, promotionListener))
.next(insertDelRslrlistRegistStep(jobRepository, transactionManager, promotionListener))
.next(insertRegAppnLogRegistStep(jobRepository, transactionManager, promotionListener))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 1.삭제 로그 등록
*/
@Bean
public Step insertDelAppnLogRegistStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertDelAppnLogRegistStep", jobRepository)
.tasklet(insertTsDelMbrAppnRegistTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/**
* 2. erp 조회, appn 테이블 삭제후 등록하고
*/
@Bean
public Step insertDelRslrlistRegistStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertDelRslrlistRegistStep", jobRepository)
.tasklet(insertTsMbrAppnRegistTasklet, transactionManager)
.listener(promotionListener)
.build();
}
/**
* 3. 등록 로그 등록
*/
@Bean
public Step insertRegAppnLogRegistStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("insertRegAppnLogRegistStep", jobRepository)
.tasklet(insertTsRegMbrAppnRegistTasklet, transactionManager)
.listener(promotionListener)
.build();
}
}

View File

@@ -0,0 +1,73 @@
package com.wb.domainserver.crm.tasklet;
import com.wb.domainserver.crm.vo.TsExtOrdrVO;
import com.wb.domainserver.mapper.gcone.ExtOrdrMapper;
import com.wb.domainserver.mapper.mq.CrmExtOrdrMapper;
import com.wb.domainserver.util.dataaccess.DataMap;
import com.wb.domainserver.util.ntcn.DataShareBean;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertExtOrdrTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertExtOrdrTasklet.class);
private StepExecution stepExecution;
@Autowired
private ExtOrdrMapper mapper;
@Autowired
private CrmExtOrdrMapper crmExtOrdrMapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
Map<String, Object> message = (Map<String, Object>) stepContext.getStepExecution().getJobExecution().getExecutionContext().get("message");
log.debug("message {}", message);
try {
//gcone max값 가져오기
DataMap map = mapper.selectExtOrdrMaxInnb();
//mq에서 select 하기
TsExtOrdrVO vo = new TsExtOrdrVO();
BigDecimal maxInnb = (BigDecimal) map.get("maxErpOrderInnb");
vo.setMaxExtOrdrInnb(maxInnb);
List<TsExtOrdrVO> extOrdrInfo = crmExtOrdrMapper.selectCrmExtOrdrInfo(vo);
//gcone 등록
if (extOrdrInfo != null) {
if (extOrdrInfo != null) {
for (TsExtOrdrVO extVO : extOrdrInfo) {
int result = mapper.insertExtOrdr(extVO);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,63 @@
package com.wb.domainserver.crm.tasklet;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.mapper.gcone.MemberAppnMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertTsDelMbrAppnRegistTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
@Autowired
private MemberAppnMapper memberAppnMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("MemberAppnLogDelTasklet 실행");
Map<String,Object> message = new HashMap<>();
try {
TsMemberAppnVO vo = new TsMemberAppnVO();
//삭제 로그 등록
memberAppnMapper.insertAppnLog(vo);
message.put("status", "1");
message.put("log_message", "GC_ERP_MEMBER_APPN_LOG 테이블에 insert 성공!!");
} catch (Exception e) {
e.printStackTrace();
message.put("status", "0");
message.put("message", "GC_ERP_MEMBER_APPN_LOG 테이블에 insert 실패!!");
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("MemberAppnLogDelTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,89 @@
package com.wb.domainserver.crm.tasklet;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.mapper.gcone.MemberAppnMapper;
import com.wb.domainserver.mapper.mq.CrmMemberAppnMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertTsMbrAppnRegistTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsMbrAppnRegistTasklet.class);
@Autowired
private MemberAppnMapper memberAppnMapper;
@Autowired
private CrmMemberAppnMapper crmMemberAppnMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
System.out.println("==========================================");
System.out.println("MemberAppnLogTasklet 실행");
Map<String,Object> message = new HashMap<>();
try {
//1.erp 테이블 블랙리스트 조회
List<TsMemberAppnVO> rslrList = crmMemberAppnMapper.selectCrmRslrlistInqire();
//2. gcone 테이블에 구분자가 '03'인 데이터 삭제
memberAppnMapper.deleteRslrAppn();
//3. gc_member_appn 등록
List<String> appnInnbList = new ArrayList<>();
//2.gcone 테이블에 블랙리스트 등록
if(rslrList != null){
for (TsMemberAppnVO vo : rslrList) {
memberAppnMapper.insertRslrAppn(vo);
/*고유번호 get*/
appnInnbList.add(vo.getAppnInnb());
}
}
/*로그에 등록할 고유번호*/
message.put("appnInnbList",appnInnbList);
message.put("status", "1");
message.put("log_message", "GC_ERP_MEMBER_APPN 테이블에 insert 성공!!");
} catch (Exception e) {
e.printStackTrace();
message.put("status", "0");
message.put("message", "GC_ERP_MEMBER_APPN 실패!!");
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", message);
System.out.println("MemberAppnLogTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,77 @@
package com.wb.domainserver.crm.tasklet;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.mapper.gcone.MemberAppnMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class InsertTsRegMbrAppnRegistTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsRegMbrAppnRegistTasklet.class);
@Autowired
private MemberAppnMapper memberAppnMapper;
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
Map<String, Object> message = (Map<String, Object>) stepContext.getStepExecution().getJobExecution().getExecutionContext().get("message");
System.out.println("로그 찍기 전 Step 결과: " + message);
System.out.println("==========================================");
System.out.println("InsertTsRegMbrAppnRegistTasklet 실행");
Map<String, Object> result = new HashMap<>();
try {
if(message != null){
List<String> appnInnbList = (List<String>) message.get("appnInnbList");
TsMemberAppnVO vo = new TsMemberAppnVO();
vo.setAppnInnbArr(appnInnbList);
memberAppnMapper.insertAppnLog(vo);
}
result.put("status", "1");
result.put("log_message", "GC_ERP_MEMBER_APPN_LOG 테이블에 등록 로그 insert 성공!!");
} catch (Exception e) {
e.printStackTrace();
result.put("status", "0");
result.put("message", "GC_ERP_MEMBER_APPN_LOG 등록 로그 insert 실패!!");
}
stepContext = StepSynchronizationManager.getContext();
stepContext.getStepExecution().getExecutionContext().put("message", result);
System.out.println("MemberAppnLogTasklet 종료");
System.out.println("==========================================");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,52 @@
package com.wb.domainserver.crm.tasklet;
import com.wb.domainserver.crm.vo.TsExtOrdrVO;
import com.wb.domainserver.mapper.mq.CrmExtOrdrMapper;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@JobScope
@Slf4j
public class SelectCrmExtOrdrInfoTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertTsMbrAppnRegistTasklet.class);
private StepExecution stepExecution;
@Autowired
private CrmExtOrdrMapper crmExtOrdrMapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
StepContext stepContext = StepSynchronizationManager.getContext();
log.debug("상태확인 {}",stepContext.getStepExecution().getJobExecution().getExecutionContext());
DataMap map = (DataMap) stepContext.getStepExecution().getJobExecution().getExecutionContext().get("message");
Map<String, Object> message = new HashMap<>();
TsExtOrdrVO vo = new TsExtOrdrVO();
String maxInnb = (String) map.get("maxErpOrderInnb");
List<TsExtOrdrVO> extOrdrInfo = crmExtOrdrMapper.selectCrmExtOrdrInfo(vo);
message.put("extOrdrInfo",extOrdrInfo);
log.debug("extOrdrInfo 결과{}", extOrdrInfo);
log.debug("message 내용 {}", message);
stepContext.getStepExecution().getExecutionContext().put("message", message);
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,51 @@
package com.wb.domainserver.crm.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsExtOrdrVO implements Serializable {
private static final long serialVersionUID = 1L;
/**외부주문고유번호(PK)*/
private String erpOrderInnb;
/**법인코드*/
private String cprCd;
/**브랜드코드*/
private String brandCd;
/**쇼핑몰구분*/
private String sopmalDv;
/**쇼핑몰*/
private String sopmal;
/**주문코드(번호)*/
private String ordrNb;
/**주문일시*/
private String ordrDt;
/**출고일시*/
private String dlivyDt;
/**휴대전화(숫자만)*/
private String mbtlnb;
/**이름*/
private String nm;
/**주소(상세주소제외)*/
private String adres;
/**전자우편(재확인용)*/
private String email;
/**메모*/
private String memo;
/**업로드작업그룹*/
private String uploadGroup;
/**등록일시*/
private String registDt;
/**수정일시*/
private String updtDt;
/*max 고유번호*/
private BigDecimal maxExtOrdrInnb;
}

View File

@@ -0,0 +1,46 @@
package com.wb.domainserver.crm.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsMemberAppnVO implements Serializable {
private static final long serialVersionUID = 1L;
/**지정로그고유번호*/
private String appnLogInnb;
/**지정고유번호(PK)*/
private String appnInnb;
/**지정고유번호 배열*/
private List<String> appnInnbArr;
/**쇼핑몰코드(PK)*/
private String sopmalCd;
/**지정구분코드*/
private String appnDvCd;
/**식별기준코드*/
private String idntfcStdrCd;
/**식별정보(FK)*/
private String idntfcInfo;
/**메모*/
private String appnMemo;
/**등록자*/
private String regusr;
/**수정자*/
private String updusr;
/*등록일자*/
private String registDt;
}

View File

@@ -0,0 +1,44 @@
package com.wb.domainserver.ep.form;
public class GoogleEpForm {
public static String googleEpForm(){
return """
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<script/>
<script/>
<script/>
<channel>
<title>#TITLE#</title>
<link>#LINK#</link>
<description>#DESCRIPTION#</description>
""";
}
public static String googleEpItemForm(){
return """
<item>
<g:id>#GOODS_INNB#</g:id>
<g:title>#GOODS_NM#</g:title>
<g:description>#REPRSNT_DC#</g:description>
<g:link>#PC_GOODS_LINK#</g:link>
<g:image_link>#IMG#</g:image_link>
<g:price>#PRICE#</g:price>
<g:sale_price>#SALE_PRICE#</g:sale_price>
<g:product_type>#PRODUCT_TYPE#</g:product_type>
<g:brand>#BRAND#</g:brand>
<g:condition>new</g:condition>
<g:availability>#IN_STOCK#</g:availability>
</item>
""";
}
public static String googleEpEndForm(){
return """
</channel>
</rss>
""";
}
}

View File

@@ -0,0 +1,43 @@
package com.wb.domainserver.ep.form;
public class MetaEpForm {
public static String metaEpForm(){
return """
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<script/>
<script/>
<script/>
<channel>
<title>#TITLE#</title>
<link>#LINK#</link>
<description>#DESCRIPTION#</description>
""";
}
public static String metaEpItemForm(){
return """
<item>
<g:id>#GOODS_INNB#</g:id>
<g:title>#GOODS_NM#</g:title>
<g:description>#REPRSNT_DC#</g:description>
<g:link>#PC_GOODS_LINK#</g:link>
<g:image_link>#IMG#</g:image_link>
<g:price>#PRICE#</g:price>
<g:sale_price>#SALE_PRICE#</g:sale_price>
<g:brand>#BRAND#</g:brand>
<g:condition>new</g:condition>
<g:availability>#IN_STOCK#</g:availability>
</item>
""";
}
public static String metaEpEndForm(){
return """
</channel>
</rss>
""";
}
}

View File

@@ -0,0 +1,70 @@
package com.wb.domainserver.ep.form;
public class MobionEpForm {
public static String mobionEpForm(){
return """
<products>
<script/>
<script/>
<script/>
""";
}
public static String mobionEpItemForm(){
return """
<product id="#GOODS_INNB#">
<title>
<![CDATA[ #GOODS_NM# ]]>
</title>
<price_pc>
<![CDATA[ #PRICE_PC# ]]>
</price_pc>
<price_mobile>
<![CDATA[ #PRICE_MOBILE# ]]>
</price_mobile>
<normal_price>
<![CDATA[ #NORMAL_PRICE# ]]>
</normal_price>
<link>
<![CDATA[ #LINK# ]]>
</link>
<mobile_link>
<![CDATA[ #MOBILE_LINK# ]]>
</mobile_link>
<image_link1>
<![CDATA[ #IMAGE_LINK1# ]]>
</image_link1>
<image_link2>
<![CDATA[ #IMAGE_LINK2# ]]>
</image_link2>
<image_link3>
<![CDATA[ #IMAGE_LINK3# ]]>
</image_link3>
<image_link4>
<![CDATA[ #IMAGE_LINK4# ]]>
</image_link4>
<category_name1>
<![CDATA[ #CATEGORY_NAME1# ]]>
</category_name1>
<category_name2>
<![CDATA[ #CATEGORY_NAME2# ]]>
</category_name2>
<category_name3>
<![CDATA[ #CATEGORY_NAME3# ]]>
</category_name3>
<category_name4>
<![CDATA[ #CATEGORY_NAME4# ]]>
</category_name4>
</product>
""";
}
public static String mobionEpEndForm(){
return """
</products>
""";
}
}

View File

@@ -0,0 +1,15 @@
package com.wb.domainserver.ep.form;
import lombok.Data;
@Data
public class NaverEpForm {
public String naverEpFormHeader(){
return """
id title price_pc price_mobile normal_price link mobile_link image_link add_image_link category_name1 category_name2 category_name3 category_name4 naver_category naver_product_id condition import_flag parallel_import order_made product_flag adult goods_type barcode manufacture_define_number model_number brand maker origin card_event event_words coupon partner_coupon_download interest_free_event point installation_costs pre_match_code search_tag group_id vendor_id coordi_id minimum_purchase_quantity review_count shipping delivery_grade delivery_detail attribute option_detail seller_id age_group gender
""";
}
}

View File

@@ -0,0 +1,80 @@
package com.wb.domainserver.ep.jobs;
import com.wb.domainserver.ep.tasklet.GoogleEpTasklet;
import com.wb.domainserver.ep.tasklet.MetaEpTasklet;
import com.wb.domainserver.ep.tasklet.MobionEpTasklet;
import com.wb.domainserver.ep.tasklet.NaverEpTasklet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@RequiredArgsConstructor
@Slf4j
public class EpConfig extends DefaultBatchConfiguration{
private final GoogleEpTasklet googleEpTasklet;
private final MetaEpTasklet metaEpTasklet;
private final NaverEpTasklet naverEpTasklet;
private final MobionEpTasklet mobionEpTasklet;
@Bean
public Job epJob(JobRepository jobRepository
, Step googleEpStep
, Step metaEpStep
, Step naverEpStep
, Step mobionEpStep
) {
return new JobBuilder("epJob", jobRepository)
.incrementer(new RunIdIncrementer())
.start(googleEpStep)
.next(metaEpStep)
.next(naverEpStep)
.next(mobionEpStep)
.build();
}
@Bean
@JobScope
public Step googleEpStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("googleEpStep", jobRepository)
.tasklet(googleEpTasklet, platformTransactionManager)
.build();
}
@Bean
@JobScope
public Step metaEpStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("metaEpStep", jobRepository)
.tasklet(metaEpTasklet, platformTransactionManager)
.build();
}
@Bean
@JobScope
public Step naverEpStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("naverEpStep", jobRepository)
.tasklet(naverEpTasklet, platformTransactionManager)
.build();
}
@Bean
@JobScope
public Step mobionEpStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("mobionEpStep", jobRepository)
.tasklet(mobionEpTasklet, platformTransactionManager)
.build();
}
}

View File

@@ -0,0 +1,97 @@
package com.wb.domainserver.ep.tasklet;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;
@Slf4j
public abstract class AbstractEpTasklet {
/**
* EP 데이터 생성 후 파일 쓰기
* @param epData EP 데이터
* @param sopmalCd EP 대상 쇼핑몰
* @return
*/
protected void createEpFile(String epData, String sopmalCd, String epPath, String fileNm, String ext){
// 루트 경로에서 시작하는 디렉토리 경로 (OS에 따라 경로 분리)
// String uploaddirsPath = FileSystems.getDefault().getSeparator(); // root에서 시작
Path directory = Paths.get(epPath, sopmalCd, "ep").toAbsolutePath().normalize();
// 생성할 파일의 경로
Path filePath = directory.resolve(fileNm+ext);
log.debug("directory :::: {}", directory);
log.debug("filePath :: {}", filePath);
//디렉토리 생성
try {
Files.createDirectories(directory);
} catch (IOException ioe) {
log.error("create ep directory err {}", ioe.getMessage());
}
//파일생성
File epfile = new File(filePath.toString());
//파일 생성 기존에 있을경우 삭제후 빈파일 생성
try( FileOutputStream fos = new FileOutputStream(epfile, false)){
//파일 쓰기
String epFileData ="";
//xml 파일 일경우 xml 태그 추가하고 &를 &amp;로 치환
if(".xml".equals(ext)){
epFileData = "<?xml version='1.0'?> \n"+epData.replace("&", "&amp;");
}else{
epFileData = epData;
}
fos.write(epFileData.getBytes(StandardCharsets.UTF_8));
log.debug("파일 작성 완료: {}" , epfile.getAbsolutePath());
// 리눅스/유닉스 계열 OS일 경우 파일 읽기/쓰기 권한 부여
if (System.getProperty("os.name").toLowerCase().contains("nix") ||
System.getProperty("os.name").toLowerCase().contains("nux")) {
// 읽기/쓰기 권한을 설정
Set<PosixFilePermission> perms = new HashSet<>();
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
perms.add(PosixFilePermission.GROUP_READ);
perms.add(PosixFilePermission.GROUP_WRITE);
// 파일에 권한 적용
Files.setPosixFilePermissions(filePath, perms);
log.error("리눅스/유닉스 계열 OS에서 파일 권한 설정 완료.");
}
} catch (UnsupportedOperationException e) {
// 만약 OS가 Posix 파일 권한을 지원하지 않는다면
log.error("POSIX 파일 시스템이 아닌 OS입니다: " + e.getMessage());
}catch (FileNotFoundException fne){
log.error("create ep file directory notFound error {}", fne.getMessage());
}
catch (IOException ie){
log.error("create ep file error {}", ie.getMessage());
}catch (Exception e){
log.error("create ep file error", e);
}
}
}

View File

@@ -0,0 +1,130 @@
package com.wb.domainserver.ep.tasklet;
import com.wb.domainserver.ep.form.GoogleEpForm;
import com.wb.domainserver.ep.vo.GoogleEp;
import com.wb.domainserver.mapper.gcone.EpMapper;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@StepScope
@RequiredArgsConstructor
@Slf4j
public class GoogleEpTasklet extends AbstractEpTasklet implements Tasklet {
private final EpMapper epMapper;
@Value("${ep.common.fileupload.cdnurl}")
private String cdnurl;
@Value("${ep.common.fileupload.uploaddirs.path}")
private String epPath;
@Value("${ep.common.fileupload.uploaddirs.google}")
private String fileNm;
@Value("${ep.common.fileupload.extensions.xml}")
private String ext;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//EP 대상 상품 조회
List<GoogleEp> result = epMapper.selectGoogleEp();
if(CollectionUtils.isEmpty(result)){
return RepeatStatus.FINISHED;
}
//쇼핑몰별 분리
Map<String, List<GoogleEp>> sopmalList = result.stream().collect(Collectors.groupingBy(GoogleEp::getSopmalCd));
Map<String, String> epData = new HashMap<>();
// 쇼핑몰 코드 추출
for (Map.Entry<String, List<GoogleEp>> entry : sopmalList.entrySet()) {
// form 적용
epData = createEpForm(sopmalList.get(entry.getKey()), entry.getKey());
// log.debug("createEpForm : {}", epData);
if(CollectionUtils.isEmpty(epData)){
return RepeatStatus.FINISHED;
}
//file write
// 쇼핑몰별 file write
createEpFile(epData.get(entry.getKey()), entry.getKey(), epPath, fileNm, ext);
}
return RepeatStatus.FINISHED;
}
/**
* EP 데이터 조회 후 XML FORM에 바인딩
* @param sopmalList EP 대상 조회
* @param sopmalCd EP 대상 쇼핑몰
* @return
*/
private Map<String, String> createEpForm(List<GoogleEp> sopmalList, String sopmalCd){
if(CollectionUtils.isEmpty(sopmalList)){
return null;
}
String sopmalNm = sopmalList.get(0).getSopmalNm();
String sopmalLink = sopmalList.get(0).getPcDomnAdres();
Map<String, String> result = new HashMap<>();
StringBuilder xml = new StringBuilder();
String startForm = GoogleEpForm.googleEpForm();
xml.append(
startForm.replace("#TITLE#", sopmalNm)
.replace("#LINK#", sopmalLink)
.replace("#DESCRIPTION#", sopmalNm)
);
for(GoogleEp goodsInfo : sopmalList){
String itemForm = GoogleEpForm.googleEpItemForm();
xml.append(
itemForm.replace("#GOODS_INNB#", StringUtil.nullConvert(goodsInfo.getGoodsInnb()))
.replace("#GOODS_NM#", StringUtil.nullConvert(goodsInfo.getGoodsNm()))
.replace("#REPRSNT_DC#", StringUtil.nullConvert(goodsInfo.getReprsntDc()))
.replace("#PC_GOODS_LINK#", goodsInfo.getPcGoodsLink())
.replace("#IMG#", cdnurl+StringUtil.nullConvert(goodsInfo.getImg()))
.replace("#PRICE#", StringUtil.nullConvert(goodsInfo.getPrice()))
.replace("#SALE_PRICE#", StringUtil.nullConvert(goodsInfo.getSalePrice()))
.replace("#PRODUCT_TYPE#", StringUtil.nullConvert(goodsInfo.getProductType()))
.replace("#BRAND#", StringUtil.nullConvert(goodsInfo.getSopmalNm()))
.replace("#IN_STOCK#", StringUtil.nullConvert(goodsInfo.getInStock()))
);
}
String endForm = GoogleEpForm.googleEpEndForm();
xml.append(endForm);
result.put(sopmalCd, xml.toString());
return result;
}
}

View File

@@ -0,0 +1,130 @@
package com.wb.domainserver.ep.tasklet;
import com.wb.domainserver.ep.form.MetaEpForm;
import com.wb.domainserver.ep.vo.MetaEp;
import com.wb.domainserver.mapper.gcone.EpMapper;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@StepScope
@RequiredArgsConstructor
@Slf4j
public class MetaEpTasklet extends AbstractEpTasklet implements Tasklet {
private final EpMapper epMapper;
@Value("${ep.common.fileupload.cdnurl}")
private String cdnurl;
@Value("${ep.common.fileupload.uploaddirs.path}")
private String epPath;
@Value("${ep.common.fileupload.uploaddirs.meta}")
private String fileNm;
@Value("${ep.common.fileupload.extensions.xml}")
private String ext;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//EP 대상 상품 조회
List<MetaEp> result = epMapper.selectMetaEp();
if(CollectionUtils.isEmpty(result)){
return RepeatStatus.FINISHED;
}
//쇼핑몰별 분리
Map<String, List<MetaEp>> sopmalList = result.stream().collect(Collectors.groupingBy(MetaEp::getSopmalCd));
Map<String, String> epData = new HashMap<>();
// 쇼핑몰 코드 추출
for (Map.Entry<String, List<MetaEp>> entry : sopmalList.entrySet()) {
log.debug("sopmalList key : {}", entry.getKey());
// form 적용
epData = createEpForm(sopmalList.get(entry.getKey()), entry.getKey());
// log.debug("createEpForm : {}", epData);
if(CollectionUtils.isEmpty(epData)){
return RepeatStatus.FINISHED;
}
//file write
// 쇼핑몰별 file write
createEpFile(epData.get(entry.getKey()), entry.getKey(), epPath, fileNm, ext);
}
return RepeatStatus.FINISHED;
}
/**
* EP 데이터 조회 후 XML FORM에 바인딩
* @param sopmalList EP 대상 조회
* @param sopmalCd EP 대상 쇼핑몰
* @return
*/
private Map<String, String> createEpForm(List<MetaEp> sopmalList, String sopmalCd){
if(CollectionUtils.isEmpty(sopmalList)){
return null;
}
String sopmalNm = sopmalList.get(0).getSopmalNm();
String sopmalLink = sopmalList.get(0).getPcDomnAdres();
Map<String, String> result = new HashMap<>();
StringBuilder xml = new StringBuilder();
String startForm = MetaEpForm.metaEpForm();
xml.append(
startForm.replace("#TITLE#", sopmalNm)
.replace("#LINK#", sopmalLink)
.replace("#DESCRIPTION#", sopmalNm)
);
for(MetaEp goodsInfo : sopmalList){
String itemForm = MetaEpForm.metaEpItemForm();
xml.append(
itemForm.replace("#GOODS_INNB#", StringUtil.nullConvert(goodsInfo.getGoodsInnb()))
.replace("#GOODS_NM#", StringUtil.nullConvert(goodsInfo.getGoodsNm()))
.replace("#REPRSNT_DC#", StringUtil.nullConvert(goodsInfo.getReprsntDc()))
.replace("#PC_GOODS_LINK#", goodsInfo.getPcGoodsLink())
.replace("#IMG#", cdnurl+StringUtil.nullConvert(goodsInfo.getImg()))
.replace("#PRICE#", StringUtil.nullConvert(goodsInfo.getPrice()))
.replace("#SALE_PRICE#", StringUtil.nullConvert(goodsInfo.getSalePrice()))
.replace("#BRAND#", StringUtil.nullConvert(goodsInfo.getSopmalNm()))
.replace("#IN_STOCK#", StringUtil.nullConvert(goodsInfo.getInStock()))
);
}
String endForm = MetaEpForm.metaEpEndForm();
xml.append(endForm);
result.put(sopmalCd, xml.toString());
return result;
}
}

View File

@@ -0,0 +1,248 @@
package com.wb.domainserver.ep.tasklet;
import com.wb.domainserver.ep.form.MobionEpForm;
import com.wb.domainserver.ep.vo.MobionEp;
import com.wb.domainserver.mapper.gcone.EpMapper;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Component
@StepScope
@RequiredArgsConstructor
@Slf4j
public class MobionEpTasklet extends AbstractEpTasklet implements Tasklet {
private final EpMapper epMapper;
@Value("${ep.common.fileupload.cdnurl}")
private String cdnurl;
@Value("${ep.common.fileupload.uploaddirs.path}")
private String epPath;
@Value("${ep.common.fileupload.uploaddirs.mobion}")
private String fileNm;
@Value("${ep.common.fileupload.extensions.xml}")
private String ext;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//EP 대상 상품 조회
List<MobionEp> result = epMapper.selectMobionEp();
if(CollectionUtils.isEmpty(result)){
return RepeatStatus.FINISHED;
}
//쇼핑몰별 분리
Map<String, List<MobionEp>> sopmalList = result.stream().collect(Collectors.groupingBy(MobionEp::getSopmalCd));
Map<String, String> epData = new HashMap<>();
// 쇼핑몰 코드 추출
for (Map.Entry<String, List<MobionEp>> entry : sopmalList.entrySet()) {
// form 적용
epData = createEpForm(sopmalList.get(entry.getKey()), entry.getKey());
// log.debug("createEpForm : {}", epData);
if(CollectionUtils.isEmpty(epData)){
return RepeatStatus.FINISHED;
}
//file write
// 쇼핑몰별 file write
createEpFile(epData.get(entry.getKey()), entry.getKey(), epPath, fileNm, ext);
}
return RepeatStatus.FINISHED;
}
/**
* EP 데이터 조회 후 XML FORM에 바인딩
* @param sopmalList EP 대상 조회
* @param sopmalCd EP 대상 쇼핑몰
* @return
*/
private Map<String, String> createEpForm(List<MobionEp> sopmalList, String sopmalCd){
if(CollectionUtils.isEmpty(sopmalList)){
return null;
}
Map<String, String> result = new HashMap<>();
StringBuilder xml = new StringBuilder();
String startForm = MobionEpForm.mobionEpForm();
xml.append(startForm);
for(MobionEp goodsInfo : sopmalList){
String itemForm = MobionEpForm.mobionEpItemForm();
String imgLink1 = "";
String imgLink2 = "";
String imgLink3 = "";
String imgLink4 = "";
//이미지 조회
if(!StringUtil.isEmpty(goodsInfo.getImg())){
String[] imgArr = goodsInfo.getImg().split("\\|");
for(int i=0; i<imgArr.length; i++){
imgArr[i] = cdnurl+imgArr[i];
switch (i){
case 0:
imgLink1 = imgArr[i];
break;
case 1:
imgLink2 = imgArr[i];
break;
case 2:
imgLink3 = imgArr[i];
break;
case 3:
imgLink4 = imgArr[i];
default:
break;
}
}
}
String categoryNm1 = "";
String categoryNm2 = "";
String categoryNm3 = "";
String categoryNm4 = "";
//카테고리 조회
if(!StringUtil.isEmpty(goodsInfo.getCategoryName())){
String[] categoryArr = goodsInfo.getCategoryName().split("\\|");
for(int i=0; i<categoryArr.length; i++){
switch (i){
case 0:
categoryNm1 = categoryArr[i];
break;
case 1:
categoryNm2 = categoryArr[i];
break;
case 2:
categoryNm3 = categoryArr[i];
break;
case 3:
categoryNm4 = categoryArr[i];
default:
break;
}
}
}
xml.append(
itemForm.replace("#GOODS_INNB#", specialCharRemove(StringUtil.nullConvert(goodsInfo.getGoodsInnb())))
.replace("#GOODS_NM#", limitByteResizing(StringUtil.nullConvert(goodsInfo.getGoodsNm()), 100, 90))
.replace("#PRICE_PC#", StringUtil.nullConvert(goodsInfo.getSalePrice()))
.replace("#PRICE_MOBILE#", StringUtil.nullConvert(goodsInfo.getSalePrice()))
.replace("#NORMAL_PRICE#", StringUtil.nullConvert(goodsInfo.getPrice()))
.replace("#LINK#", StringUtil.nullConvert(goodsInfo.getPcGoodsLink()))
.replace("#MOBILE_LINK#", StringUtil.nullConvert(goodsInfo.getMblGoodsLink()))
.replace("#IMAGE_LINK1#", StringUtil.nullConvert(imgLink1))
.replace("#IMAGE_LINK2#", StringUtil.nullConvert(imgLink2))
.replace("#IMAGE_LINK3#", StringUtil.nullConvert(imgLink3))
.replace("#IMAGE_LINK4#", StringUtil.nullConvert(imgLink4))
.replace("#CATEGORY_NAME1#", limitByteResizing(StringUtil.nullConvert(categoryNm1), 50, 45))
.replace("#CATEGORY_NAME2#", limitByteResizing(StringUtil.nullConvert(categoryNm2), 50, 45))
.replace("#CATEGORY_NAME3#", limitByteResizing(StringUtil.nullConvert(categoryNm3), 50, 45))
.replace("#CATEGORY_NAME4#", limitByteResizing(StringUtil.nullConvert(categoryNm4), 50, 45))
);
}
String endForm = MobionEpForm.mobionEpEndForm();
xml.append(endForm);
result.put(sopmalCd, xml.toString());
return result;
}
/* 글자 바이트 수 제한을 걸고 말줄임표(...)를 붙이는 함수
* @param str : 대상 문자열
* @param byteLimit : 최대 바이트 길이
* @param limit : 임의로 잘라낼 바이트 길이
*
* */
private static String limitByteResizing(String str, int byteLimit, int limit){
// 1. 먼저 멀티바이트 길이 초과 잘라내기 처리
byte[] bytes = str.getBytes(StandardCharsets.UTF_8); // UTF-8 인코딩으로 변환
if (bytes.length > byteLimit) {
// 멀티바이트 문자 확인
while (limit > 0 && (bytes[limit] & 0xC0) == 0x80) { // UTF-8 연속 바이트 확인
limit--;
}
// 문자열 자르기
return new String(bytes, 0, limit, StandardCharsets.UTF_8) + "...";
}else{
return str;
}
}
/*
* 문자열에 포함된 특수문자 제거 후 문자열 반환
* @param 대상 문자열
* 제거할 특수문자 !#$%&'()*+,/:;<=>?@\^_`{|}~\t\r\n\v\f
*
* */
private static String specialCharRemove(String str){
Pattern p = Pattern.compile("[^!#$%&'()*+,/:;<=>?@\\^_`{|}~\\t\\r\\n\\v\\f]+");
Matcher matcher = p.matcher(str);
StringBuilder finalString = new StringBuilder();
while (matcher.find()) {
finalString.append(matcher.group());
}
return finalString.toString();
}
}

View File

@@ -0,0 +1,199 @@
package com.wb.domainserver.ep.tasklet;
import com.wb.domainserver.ep.form.NaverEpForm;
import com.wb.domainserver.ep.vo.NaverEp;
import com.wb.domainserver.mapper.gcone.EpMapper;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@StepScope
@RequiredArgsConstructor
@Slf4j
public class NaverEpTasklet extends AbstractEpTasklet implements Tasklet {
private final EpMapper epMapper;
@Value("${ep.common.fileupload.cdnurl}")
private String cdnurl;
@Value("${ep.common.fileupload.uploaddirs.path}")
private String epPath;
@Value("${ep.common.fileupload.uploaddirs.naver}")
private String fileNm;
@Value("${ep.common.fileupload.extensions.txt}")
private String ext;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//EP 대상 상품 조회
List<NaverEp> result = epMapper.selectNaverEp();
if(CollectionUtils.isEmpty(result)){
return RepeatStatus.FINISHED;
}
//쇼핑몰별 분리
Map<String, List<NaverEp>> sopmalList = result.stream().collect(Collectors.groupingBy(NaverEp::getSopmalCd));
Map<String, String> epData = new HashMap<>();
// 쇼핑몰 코드 추출
for (Map.Entry<String, List<NaverEp>> entry : sopmalList.entrySet()) {
log.debug("sopmalList key : {}", entry.getKey());
// form 적용
epData = createEpForm(sopmalList.get(entry.getKey()), entry.getKey());
if(CollectionUtils.isEmpty(epData)){
return RepeatStatus.FINISHED;
}
//file write
// 쇼핑몰별 file write
createEpFile(epData.get(entry.getKey()), entry.getKey(), epPath, fileNm, ext);
}
return RepeatStatus.FINISHED;
}
/**
* EP 데이터 조회 후 XML FORM에 바인딩
* @param sopmalList EP 대상 조회
* @param sopmalCd EP 대상 쇼핑몰
* @return
*/
private Map<String, String> createEpForm(List<NaverEp> sopmalList, String sopmalCd){
if(CollectionUtils.isEmpty(sopmalList)){
return null;
}
Map<String, String> result = new HashMap<>();
StringBuilder txt = new StringBuilder();
NaverEpForm epForm = new NaverEpForm();
String naverEpFormHeader = epForm.naverEpFormHeader();
txt.append(naverEpFormHeader.replaceAll(" ", "\t"));
for(NaverEp ep : sopmalList){
txt.append(convertTab(ep.getId()));
txt.append(convertTab(ep.getTitle()));
txt.append(convertTab(ep.getPricePc()));
txt.append(convertTab(ep.getPriceMobile()));
txt.append(convertTab(ep.getNormalPrice()));
txt.append(convertTab(ep.getLink()));
txt.append(convertTab(ep.getMobileLink()));
txt.append(convertTab(cdnurl+ep.getImageLink()));
if(!StringUtil.isEmpty(ep.getAddImageLink())){
txt.append(convertTab(cdnurl+ep.getAddImageLink()));
}else{
txt.append(convertTab(ep.getAddImageLink()));
}
if(StringUtil.isEmpty(ep.getCategoryName())){
txt.append(convertTab(ep.getCategoryName1()));
txt.append(convertTab(ep.getCategoryName2()));
txt.append(convertTab(ep.getCategoryName3()));
txt.append(convertTab(ep.getCategoryName4()));
}else{
String [] category = ep.getCategoryName().split("\\|");
log.debug("category ::: {}", ep.getCategoryName());
log.debug("category length ::: {}", category.length);
//카테고리 총 수 4개 에서 현재 있는 카테고리 수 차감
int categoryTabCnt = 4 - category.length;
//카테고리 있는 만큼 카테고리명 append
for(int i = 0; i < category.length; i++){
txt.append(convertTab(category[i]));
}
//카테고리명 없는 수만큼 tab 처리
for(int i = 0; i < categoryTabCnt; i++){
txt.append(convertTab(""));
}
}
txt.append(convertTab(ep.getNaverCategory()));
txt.append(convertTab(ep.getNaverProductId()));
txt.append(convertTab(ep.getCondition()));
txt.append(convertTab(ep.getImportFlag()));
txt.append(convertTab(ep.getParallelImport()));
txt.append(convertTab(ep.getOrderMade()));
txt.append(convertTab(ep.getProductFlag()));
txt.append(convertTab(ep.getAdult()));
txt.append(convertTab(ep.getGoodsType()));
txt.append(convertTab(ep.getBarcode()));
txt.append(convertTab(ep.getManufactureDefineNumber()));
txt.append(convertTab(ep.getModelNumber()));
txt.append(convertTab(ep.getBrand()));
txt.append(convertTab(ep.getMaker()));
txt.append(convertTab(ep.getOrigin()));
txt.append(convertTab(ep.getCardEvent()));
txt.append(convertTab(ep.getEventWords()));
txt.append(convertTab(ep.getCoupon()));
txt.append(convertTab(ep.getPartnerCouponDownload()));
txt.append(convertTab(ep.getInterestFreeEvent()));
txt.append(convertTab(ep.getPoint()));
txt.append(convertTab(ep.getInstallationCosts()));
txt.append(convertTab(ep.getPreMatchCode()));
txt.append(convertTab(ep.getSearchTag()));
txt.append(convertTab(ep.getGroupId()));
txt.append(convertTab(ep.getVendorId()));
txt.append(convertTab(ep.getCoordiId()));
txt.append(convertTab(ep.getMinimumPurchaseQuantity()));
txt.append(convertTab(ep.getReviewCount()));
txt.append(convertTab(ep.getShipping()));
txt.append(convertTab(ep.getDeliveryGrade()));
txt.append(convertTab(ep.getDeliveryDetail()));
txt.append(convertTab(ep.getAttribute()));
txt.append(convertTab(ep.getOptionDetail()));
txt.append(convertTab(ep.getSellerId()));
txt.append(convertTab(ep.getAgeGroup()));
if(!StringUtil.isEmpty(ep.getGender())){
txt.append(convertTab(ep.getGender()));
}
txt.append("\n");
}
result.put(sopmalCd, txt.toString());
return result;
}
/**
*<pre>
* 인자로 받은 String이 null일 경우 tab으로 리턴한다.
* 인자로 받은 String이 null이 아닐 경우 tab을 뒤에 붙여 리턴한다.
*</pre>
*/
public static String convertTab(String src) {
final String tab = "\t";
if (src == null || src.equals("null") || "".equals(src) || " ".equals(src)) {
return tab;
} else {
return src + tab;
}
}
}

View File

@@ -0,0 +1,34 @@
package com.wb.domainserver.ep.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class GoogleEp {
private String sopmalCd;
private String goodsInnb;
private String goodsNm;
private String reprsntDc;
private String pcGoodsLink;
private String pcDomnAdres;
private String img;
private String sopmalNm;
private String inStock;
private String productType;
private String price;
private String salePrice;
}

View File

@@ -0,0 +1,32 @@
package com.wb.domainserver.ep.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MetaEp {
private String sopmalCd;
private String goodsInnb;
private String goodsNm;
private String reprsntDc;
private String pcGoodsLink;
private String pcDomnAdres;
private String img;
private String sopmalNm;
private String inStock;
private String price;
private String salePrice;
}

View File

@@ -0,0 +1,27 @@
package com.wb.domainserver.ep.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MobionEp {
private String sopmalCd;
private String goodsInnb;
private String goodsNm;
private String pcGoodsLink;
private String mblGoodsLink;
private String img;
private String price;
private String salePrice;
private String categoryName;
}

View File

@@ -0,0 +1,62 @@
package com.wb.domainserver.ep.vo;
import lombok.Data;
@Data
public class NaverEp {
//쇼핑몰별 구분
private String sopmalCd;
private String id;
private String title;
private String pricePc;
private String priceMobile;
private String normalPrice;
private String link;
private String mobileLink;
private String imageLink;
private String addImageLink;
//categoryName :: 카테고리명 DB에서 받아와서 1~4에 다시 재분배용으로 사용
private String categoryName;
private String categoryName1;
private String categoryName2;
private String categoryName3;
private String categoryName4;
private String naverCategory;
private String naverProductId;
private String condition;
private String importFlag;
private String parallelImport;
private String orderMade;
private String productFlag;
private String adult;
private String goodsType;
private String barcode;
private String manufactureDefineNumber;
private String modelNumber;
private String brand;
private String maker;
private String origin;
private String cardEvent;
private String eventWords;
private String coupon;
private String partnerCouponDownload;
private String interestFreeEvent;
private String point;
private String installationCosts;
private String preMatchCode;
private String searchTag;
private String groupId;
private String vendorId;
private String coordiId;
private String minimumPurchaseQuantity;
private String reviewCount;
private String shipping;
private String deliveryGrade;
private String deliveryDetail;
private String attribute;
private String optionDetail;
private String sellerId;
private String ageGroup;
private String gender;
}

View File

@@ -0,0 +1,31 @@
package com.wb.domainserver.exception;
import org.springframework.http.HttpStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ErrCode {
//APPLICATION_SERVER_ERROR
PAGE_NOT_FOUND(HttpStatus.NOT_FOUND, HttpStatus.NOT_FOUND.value(), "페이지를 찾을수 없습니다"),
BAD_REQUEST(HttpStatus.BAD_REQUEST, HttpStatus.BAD_REQUEST.value(), "잘못된 요청입니다"),
NOT_AUTHENTICATED(HttpStatus.UNAUTHORIZED, HttpStatus.UNAUTHORIZED.value(), "인증이 필요한 요청입니다"),
INVALID_PERMISSION(HttpStatus.FORBIDDEN, HttpStatus.FORBIDDEN.value(), "해당 요청에 권한이 없습니다"),
METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, HttpStatus.METHOD_NOT_ALLOWED.value(), "허용되지 않는 요청 메소드입니다"),
REQUEST_TIMEOUT(HttpStatus.REQUEST_TIMEOUT, HttpStatus.REQUEST_TIMEOUT.value(), "요청 시간이 만료되었습니다."),
//DATABASE_TRANSACTION_ERROR
DUPLICATED_USER_NAME(HttpStatus.CONFLICT, HttpStatus.CONFLICT.value(), "유저명이 중복됩니다"),
//INTERNAL_SERVER_ERROR,
INTERNAL_SEVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.value(), "실행 도중 예기치 못한 오류가 발생하였습니다"),
USERNAME_NOT_FOUND(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.value(), "유저를 찾을 수 없습니다"),
DATABASE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.value(), "Database 에러가 발생하였습니다");
private HttpStatus status;
private int statusCode;
private String message;
}

View File

@@ -0,0 +1,202 @@
package com.wb.domainserver.exception;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.nimbusds.jose.shaded.gson.JsonParseException;
import com.wb.domainserver.exception.code.ErrorCode;
import com.wb.domainserver.exception.response.ErrorResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.servlet.NoHandlerFoundException;
import java.io.IOException;
/**
* Controller 내에서 발생하는 Exception 대해서 Catch 하여 응답값(Response)을 보내주는 기능을 수행함.
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
private final HttpStatus HTTP_STATUS_OK = HttpStatus.OK;
/**
* [Exception] API 호출 시 '객체' 혹은 '파라미터' 데이터 값이 유효하지 않은 경우
*
* @param ex MethodArgumentNotValidException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
log.error("handleMethodArgumentNotValidException", ex);
BindingResult bindingResult = ex.getBindingResult();
StringBuilder stringBuilder = new StringBuilder();
for (FieldError fieldError : bindingResult.getFieldErrors()) {
stringBuilder.append(fieldError.getField()).append(":");
stringBuilder.append(fieldError.getDefaultMessage());
stringBuilder.append(", ");
}
final ErrorResponse response = ErrorResponse.of(ErrorCode.NOT_VALID_ERROR, String.valueOf(stringBuilder));
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* [Exception] API 호출 시 'Header' 내에 데이터 값이 유효하지 않은 경우
*
* @param ex MissingRequestHeaderException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(MissingRequestHeaderException.class)
protected ResponseEntity<ErrorResponse> handleMissingRequestHeaderException(MissingRequestHeaderException ex) {
log.error("MissingRequestHeaderException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.REQUEST_BODY_MISSING_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* [Exception] 클라이언트에서 Body로 '객체' 데이터가 넘어오지 않았을 경우
*
* @param ex HttpMessageNotReadableException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
protected ResponseEntity<ErrorResponse> handleHttpMessageNotReadableException(
HttpMessageNotReadableException ex) {
log.error("HttpMessageNotReadableException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.REQUEST_BODY_MISSING_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
/**
* [Exception] 클라이언트에서 request로 '파라미터로' 데이터가 넘어오지 않았을 경우
*
* @param ex MissingServletRequestParameterException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
protected ResponseEntity<ErrorResponse> handleMissingRequestHeaderExceptionException(
MissingServletRequestParameterException ex) {
log.error("handleMissingServletRequestParameterException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.MISSING_REQUEST_PARAMETER_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
/**
* [Exception] 잘못된 서버 요청일 경우 발생한 경우
*
* @param e HttpClientErrorException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(HttpClientErrorException.BadRequest.class)
protected ResponseEntity<ErrorResponse> handleBadRequestException(HttpClientErrorException e) {
log.error("HttpClientErrorException.BadRequest", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.BAD_REQUEST_ERROR, e.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* [Exception] 잘못된 주소로 요청 한 경우
*
* @param e NoHandlerFoundException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(NoHandlerFoundException.class)
protected ResponseEntity<ErrorResponse> handleNoHandlerFoundExceptionException(NoHandlerFoundException e) {
log.error("handleNoHandlerFoundExceptionException", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.NOT_FOUND_ERROR, e.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* [Exception] NULL 값이 발생한 경우
*
* @param e NullPointerException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(NullPointerException.class)
protected ResponseEntity<ErrorResponse> handleNullPointerException(NullPointerException e) {
log.error("handleNullPointerException", e);
final ErrorResponse response = ErrorResponse.of(ErrorCode.NULL_POINT_ERROR, e.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* Input / Output 내에서 발생한 경우
*
* @param ex IOException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(IOException.class)
protected ResponseEntity<ErrorResponse> handleIOException(IOException ex) {
log.error("handleIOException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.IO_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* com.google.gson 내에 Exception 발생하는 경우
*
* @param ex JsonParseException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(JsonParseException.class)
protected ResponseEntity<ErrorResponse> handleJsonParseExceptionException(JsonParseException ex) {
log.error("handleJsonParseExceptionException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.JSON_PARSE_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* com.fasterxml.jackson.core 내에 Exception 발생하는 경우
*
* @param ex JsonProcessingException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(JsonProcessingException.class)
protected ResponseEntity<ErrorResponse> handleJsonProcessingException(JsonProcessingException ex) {
log.error("handleJsonProcessingException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.REQUEST_BODY_MISSING_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
// ==================================================================================================================
/**
* [CustomException] WnbtRestException 경우 발생
*
* @param ex WnbtRestException
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(WnbtRestException.class)
protected final ResponseEntity<ErrorResponse> handleAllExceptions(WnbtRestException ex) {
log.error("Exception", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
/**
* [Exception] 모든 Exception 경우 발생
*
* @param ex Exception
* @return ResponseEntity<ErrorResponse>
*/
@ExceptionHandler(Exception.class)
protected final ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
log.error("Exception", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HTTP_STATUS_OK);
}
}

View File

@@ -0,0 +1,39 @@
package com.wb.domainserver.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
@Getter
public class WnbtException extends RuntimeException {
private String code;
private String codeNumber;
private ErrCode errCode;
public WnbtException(){}
public WnbtException(String code, String message){
super(message);
this.code = code;
}
public WnbtException(ErrCode errCode) {
super(errCode.getMessage());
this.code = String.valueOf(errCode.getStatus());
this.codeNumber = String.valueOf(errCode.getStatusCode());
this.errCode = errCode;
}
public WnbtException(ErrCode errCode, String customMessage) {
super(customMessage);
this.code = String.valueOf(errCode.getStatus());
this.codeNumber = String.valueOf(errCode.getStatusCode());
this.errCode = errCode;
}
public WnbtException(String message, Throwable cause){
super(message, cause);
}
}

View File

@@ -0,0 +1,38 @@
package com.wb.domainserver.exception;
import com.wb.domainserver.exception.code.ErrorCode;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class WnbtRestException extends RuntimeException {
private String code;
private ErrorCode errCode;
public WnbtRestException(String message) {
super(message);
}
public WnbtRestException(String code, String message) {
super(message);
this.code = code;
}
public WnbtRestException(ErrorCode errCode){
super(errCode.getMessage());
this.code = String.valueOf(errCode.getStatus());
this.errCode = errCode;
}
public WnbtRestException(ErrorCode errCode, String customMessage) {
super(customMessage);
this.code = String.valueOf(errCode.getStatus());
this.errCode = errCode;
}
public WnbtRestException(String message, Throwable cause){
super(message, cause);
}
}

View File

@@ -0,0 +1,36 @@
package com.wb.domainserver.exception;
import lombok.Getter;
@Getter
public class WnbtWebClientException extends RuntimeException{
private String code;
private String codeNumber;
private ErrCode errCode;
public WnbtWebClientException(){}
public WnbtWebClientException(String code, String message){
super(message);
this.code = code;
}
public WnbtWebClientException(ErrCode errCode) {
super(errCode.getMessage());
this.code = String.valueOf(errCode.getStatus());
this.codeNumber = String.valueOf(errCode.getStatusCode());
this.errCode = errCode;
}
public WnbtWebClientException(ErrCode errCode, String customMessage) {
super(customMessage);
this.code = String.valueOf(errCode.getStatus());
this.codeNumber = String.valueOf(errCode.getStatusCode());
this.errCode = errCode;
}
public WnbtWebClientException(String message, Throwable cause){
super(message, cause);
}
}

View File

@@ -0,0 +1,98 @@
package com.wb.domainserver.exception.code;
import lombok.Getter;
/**
* [공통 코드] API 통신에 대한 '에러 코드'를 Enum 형태로 관리를 한다.
* Global Error CodeList : 전역으로 발생하는 에러코드를 관리한다.
* Custom Error CodeList : 업무 페이지에서 발생하는 에러코드를 관리한다
* Error Code Constructor : 에러코드를 직접적으로 사용하기 위한 생성자를 구성한다.
*
* @author hjin1210
*/
@Getter
public enum ErrorCode {
/**
* ******************************* Global Error CodeList ***************************************
* HTTP Status Code
* 400 : Bad Request
* 401 : Unauthorized
* 403 : Forbidden
* 404 : Not Found
* 500 : Internal Server Error
* *********************************************************************************************
*/
// 잘못된 서버 요청
BAD_REQUEST_ERROR(400, "G001", "Bad Request Exception"),
// @RequestBody 데이터 미 존재
REQUEST_BODY_MISSING_ERROR(400, "G002", "Required request body is missing"),
// 유효하지 않은 타입
INVALID_TYPE_VALUE(400, "G003", " Invalid Type Value"),
// Request Parameter 로 데이터가 전달되지 않을 경우
MISSING_REQUEST_PARAMETER_ERROR(400, "G004", "Missing Servlet RequestParameter Exception"),
// 입력/출력 값이 유효하지 않음
IO_ERROR(400, "G005", "I/O Exception"),
// com.google.gson JSON 파싱 실패
JSON_PARSE_ERROR(400, "G006", "JsonParseException"),
// com.fasterxml.jackson.core Processing Error
JACKSON_PROCESS_ERROR(400, "G007", "com.fasterxml.jackson.core Exception"),
// 권한이 없음
FORBIDDEN_ERROR(403, "G008", "Forbidden Exception"),
// 서버로 요청한 리소스가 존재하지 않음
NOT_FOUND_ERROR(404, "G009", "Not Found Exception"),
// NULL Point Exception 발생
NULL_POINT_ERROR(404, "G010", "Null Point Exception"),
// @RequestBody 및 @RequestParam, @PathVariable 값이 유효하지 않음
NOT_VALID_ERROR(404, "G011", "handle Validation Exception"),
// @RequestBody 및 @RequestParam, @PathVariable 값이 유효하지 않음
NOT_VALID_HEADER_ERROR(404, "G012", "Header에 데이터가 존재하지 않는 경우 "),
// 서버가 처리 할 방법을 모르는 경우 발생
INTERNAL_SERVER_ERROR(500, "G999", "Internal Server Error Exception"),
/**
* ******************************* Custom Error CodeList ***************************************
*/
// Transaction Insert Error
INSERT_ERROR(200, "9999", "Insert Transaction Error Exception"),
// Transaction Update Error
UPDATE_ERROR(200, "9999", "Update Transaction Error Exception"),
// Transaction Delete Error
DELETE_ERROR(200, "9999", "Delete Transaction Error Exception"),
; // End
/**
* ******************************* Error Code Constructor ***************************************
*/
// 에러 코드의 '코드 상태'을 반환한다.
private final int status;
// 에러 코드의 '코드간 구분 값'을 반환한다.
private final String divisionCode;
// 에러 코드의 '코드 메시지'을 반환한다.
private final String message;
// 생성자 구성
ErrorCode(final int status, final String divisionCode, final String message) {
this.status = status;
this.divisionCode = divisionCode;
this.message = message;
}
}

View File

@@ -0,0 +1,46 @@
package com.wb.domainserver.exception.code;
import lombok.Getter;
/**
* [공통 코드] API 통신에 대한 '에러 코드'를 Enum 형태로 관리를 한다.
* Success CodeList : 성공 코드를 관리한다.
* Success Code Constructor: 성공 코드를 사용하기 위한 생성자를 구성한다.
*
* @author hjin1210
*/
@Getter
public enum SuccessCode {
/**
* ******************************* Success CodeList ***************************************
*/
// 조회 성공 코드 (HTTP Response: 200 OK)
SELECT_SUCCESS(200, "200", "SELECT SUCCESS"),
// 삭제 성공 코드 (HTTP Response: 200 OK)
DELETE_SUCCESS(200, "200", "DELETE SUCCESS"),
// 삽입 성공 코드 (HTTP Response: 201 Created)
INSERT_SUCCESS(201, "201", "INSERT SUCCESS"),
// 수정 성공 코드 (HTTP Response: 201 Created)
UPDATE_SUCCESS(204, "204", "UPDATE SUCCESS"),
; // End
/**
* ******************************* Success Code Constructor ***************************************
*/
// 성공 코드의 '코드 상태'를 반환한다.
private final int status;
// 성공 코드의 '코드 값'을 반환한다.
private final String code;
// 성공 코드의 '코드 메시지'를 반환한다.s
private final String message;
// 생성자 구성
SuccessCode(final int status, final String code, final String message) {
this.status = status;
this.code = code;
this.message = message;
}
}

View File

@@ -0,0 +1,133 @@
package com.wb.domainserver.exception.response;
import com.wb.domainserver.exception.code.ErrorCode;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.validation.BindingResult;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Global Exception Handler에서 발생한 에러에 대한 응답 처리를 관리
*/
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ErrorResponse {
private int status; // 에러 상태 코드
private String divisionCode; // 에러 구분 코드
private String resultMsg; // 에러 메시지
private List<FieldError> errors; // 상세 에러 메시지
private String reason; // 에러 이유
/**
* ErrorResponse 생성자-1
*
* @param code ErrorCode
*/
@Builder
protected ErrorResponse(final ErrorCode code) {
this.resultMsg = code.getMessage();
this.status = code.getStatus();
this.divisionCode = code.getDivisionCode();
this.errors = new ArrayList<>();
}
/**
* ErrorResponse 생성자-2
*
* @param code ErrorCode
* @param reason String
*/
@Builder
protected ErrorResponse(final ErrorCode code, final String reason) {
this.resultMsg = code.getMessage();
this.status = code.getStatus();
this.divisionCode = code.getDivisionCode();
this.reason = reason;
}
/**
* ErrorResponse 생성자-3
*
* @param code ErrorCode
* @param errors List<FieldError>
*/
@Builder
protected ErrorResponse(final ErrorCode code, final List<FieldError> errors) {
this.resultMsg = code.getMessage();
this.status = code.getStatus();
this.errors = errors;
this.divisionCode = code.getDivisionCode();
}
/**
* Global Exception 전송 타입-1
*
* @param code ErrorCode
* @param bindingResult BindingResult
* @return ErrorResponse
*/
public static ErrorResponse of(final ErrorCode code, final BindingResult bindingResult) {
return new ErrorResponse(code, FieldError.of(bindingResult));
}
/**
* Global Exception 전송 타입-2
*
* @param code ErrorCode
* @return ErrorResponse
*/
public static ErrorResponse of(final ErrorCode code) {
return new ErrorResponse(code);
}
/**
* Global Exception 전송 타입-3
*
* @param code ErrorCode
* @param reason String
* @return ErrorResponse
*/
public static ErrorResponse of(final ErrorCode code, final String reason) {
return new ErrorResponse(code, reason);
}
/**
* 에러를 e.getBindingResult() 형태로 전달 받는 경우 해당 내용을 상세 내용으로 변경하는 기능을 수행한다.
*/
@Getter
public static class FieldError {
private final String field;
private final String value;
private final String reason;
public static List<FieldError> of(final String field, final String value, final String reason) {
List<FieldError> fieldErrors = new ArrayList<>();
fieldErrors.add(new FieldError(field, value, reason));
return fieldErrors;
}
private static List<FieldError> of(final BindingResult bindingResult) {
final List<org.springframework.validation.FieldError> fieldErrors = bindingResult.getFieldErrors();
return fieldErrors.stream()
.map(error -> new FieldError(
error.getField(),
error.getRejectedValue() == null ? "" : error.getRejectedValue().toString(),
error.getDefaultMessage()))
.collect(Collectors.toList());
}
@Builder
FieldError(String field, String value, String reason) {
this.field = field;
this.value = value;
this.reason = reason;
}
}
}

View File

@@ -0,0 +1,86 @@
package com.wb.domainserver.export.jobs;
import com.wb.domainserver.export.tasklet.UpdateTsAtmcPurchsDcsnTasklet;
import com.wb.domainserver.sweettracker.tasklet.UpdateTsDlvySttusUpdtTasklet;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.listener.ExecutionContextPromotionListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
/**
* 스윗트래커 배치
*
* @author 추지훈
* @version 1.0
* @since 2024.07.10
*/
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class AtmcPurchsDcsnCommConfig extends DefaultBatchConfiguration {
private static final Logger logger = LoggerFactory.getLogger(AtmcPurchsDcsnCommConfig.class);
private final UpdateTsAtmcPurchsDcsnTasklet updateAtmcPurchsDcsn;
/* ##############################################################################################
자동 구매확정 START
################################################################################################# */
/**
* <자동 구매확정 처리>
* @param jobRepository
* @param transactionManager
* @param promotionListener
* @return
*/
@Bean
public Job atmcPurchsDcsnJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new JobBuilder("atmcPurchsDcsnJob", jobRepository)
.start(updateAtmcPurchsDcsnStep(jobRepository, transactionManager, promotionListener)) // .on("FAILED").to(mqReqDlivySndng)
.incrementer(new RunIdIncrementer())
.build();
}
/**
*
* @param jobRepository
* @param transactionManager
* @param promotionListener
* @return
*/
@Bean
public Step updateAtmcPurchsDcsnStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener promotionListener) {
return new StepBuilder("updateAtmcPurchsDcsnStep", jobRepository)
.tasklet(updateAtmcPurchsDcsn, transactionManager)
.listener(promotionListener)
.build();
}
/* ##############################################################################################
자동 구매확정 END
################################################################################################# */
}

View File

@@ -0,0 +1,665 @@
package com.wb.domainserver.export.tasklet;
import com.wb.domainserver.exception.WnbtRestException;
import com.wb.domainserver.export.vo.TsMlgVO;
import com.wb.domainserver.export.vo.BOMlgUseDtlVO;
import com.wb.domainserver.export.vo.TsPurchsDcsnVO;
import com.wb.domainserver.mapper.gcone.AtmcPurchsDcsnMapper;
import com.wb.domainserver.mapper.gcone.SweetTrackerCommMapper;
import com.wb.domainserver.sweettracker.vo.TsOrderLogVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import com.wb.domainserver.util.string.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
/**
* 배송완료 후 7일 지난 출고건들 찾아서 구매확정 처리
*
* @author 추지훈
* @since 2024.07.11
* @version 1.0
*/
@Component
@JobScope
@Slf4j
public class UpdateTsAtmcPurchsDcsnTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(UpdateTsAtmcPurchsDcsnTasklet.class);
@Autowired
private AtmcPurchsDcsnMapper mapper;
@Autowired
private SweetTrackerCommMapper sweetTrackerMapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
Map<String, Object> message = new HashMap<String, Object>();
log.debug("==========================================");
log.debug("UpdateTsAtmcPurchsDcsnTasklet 실행");
// 주문 로그
List<TsOrderLogVO> orderLogVOList = new ArrayList<>();
String logSj = "";
String logDtlCn = "";
TsPurchsDcsnVO purchsDcsnVO = new TsPurchsDcsnVO();
try {
// 배송완료 후 7일 지난 출고 목록
TsPurchsDcsnVO dlivyVO = new TsPurchsDcsnVO();
// 주문상품옵션의 지급마일리지가 0 보다 크고 구매확정이 'N' 이면서 출고 상품의 지급예정 수량이 > 0 이면서 지급예정수량과 지급예정소멸수량이 같은
List<DataMap> orderItemList = mapper.selectTsExportOrderItemInqire(dlivyVO);
log.debug(" 자동 구매확정 대상 목록 : {}", orderItemList);
Set<String> ordrDlvyInnbSet = new HashSet<>();
String ordrInnb = "";
if (!CollectionUtils.isEmpty(orderItemList)) {
for (DataMap orderItem : orderItemList) {
TsOrderLogVO orderLogVO = new TsOrderLogVO();
ordrInnb = String.valueOf(orderItem.get("ordrInnb"));
log.debug("구매확정 수량 업데이트 파라미터 확인 : {}", orderItem);
log.debug("주문 번호 확인 ordrInnb : {}", ordrInnb);
mapper.updateTsPurchsDcsnOrdrItemUpdt(orderItem);
DataMap mlgResult = new DataMap();
Integer exportQy = 0;
exportQy = Integer.parseInt(StringUtil.isNullToString(orderItem.get("qy")));
Integer pymntPrearngeQy = 0; // 지급예정수량
pymntPrearngeQy = Integer.parseInt(StringUtil.isNullToString(orderItem.get("pymntPrearngeQy")));
Integer accmlmnyPymntQy = 0; // 적립금지급수량
accmlmnyPymntQy = Integer.parseInt(StringUtil.isNullToString(orderItem.get("accmlmnyPymntQy")));
Integer pymntPrearngeExtshQy = 0; // 지급예정소멸수량
pymntPrearngeExtshQy = Integer.parseInt(StringUtil.isNullToString(orderItem.get("pymntPrearngeExtshQy")));
String mlgValidPdAt = "N"; // 마일리지 유효기간 사용여부
mlgValidPdAt = String.valueOf(orderItem.get("mlgValidPdAt"));
Integer mlgValidPd = 0; // 마일리지 유효기간
String mlgValidPdStr = "0";
mlgValidPdStr = String.valueOf(orderItem.get("mlgValidPd"));
mlgValidPd = Integer.parseInt(mlgValidPdStr);
String mbrInnb = "0";
if (orderItem.get("mbrInnb") != null) {
mbrInnb = String.valueOf(orderItem.get("mbrInnb"));
}
Integer mlgAccmlAmt = 0;
mlgAccmlAmt = Integer.parseInt(String.valueOf(BigDecimal.valueOf(Long.valueOf(StringUtil.isNullToString(orderItem.get("mlgAccmlAmt"))))));
if (accmlmnyPymntQy > 0 && mlgAccmlAmt > 0 && !"0".equals(mbrInnb)) {
TsMlgVO mlgVO = new TsMlgVO();
mlgVO.setOrdrInnb(BigInteger.valueOf(Long.valueOf(StringUtil.isNullToString(orderItem.get("ordrInnb")))));
mlgVO.setMbrInnb(StringUtil.isNullToString(orderItem.get("mbrInnb")));
mlgVO.setMbrDvCd(StringUtil.isNullToString(orderItem.get("mbrDvCd")));
mlgVO.setSopmalCd(StringUtil.isNullToString(orderItem.get("sopmalCd")));
mlgVO.setMlgApplcDvCd("01");
mlgVO.setMlgApplcResn("[" + orderItem.get("dlivyCdNb") + "]구매확정");
mlgVO.setAccmlmnyAmt(BigDecimal.valueOf(Long.valueOf(StringUtil.isNullToString(orderItem.get("mlgAccmlAmt")))));
mlgVO.setRegusrDvCd("03");
mlgVO.setUpdusrDvCd("03");
mlgVO.setRegusr(0);
mlgVO.setUpdusr(0);
mlgVO.setMlgValidPd(mlgValidPd); // 개월 수
mlgVO.setMlgValidPdAt(mlgValidPdAt); // 여부
log.debug(" 자동 구매확정 대상 마일리지 VO mlgVO : {}", mlgVO);
insertBOMlgAdd(mlgVO);
mapper.updateTsExportItemQyAllUpdt(orderItem); // 적립금지급수량 업데이트
} else { // 마일리지 지급하지 않을 경우
mapper.updateTsExportItemQyAllUpdtNoMlg(orderItem); // 적립금지급수량 업데이트 '0' 처리
}
// 주문 배송 상태 부분배송중(70), 배송중(75) 처리
DataMap dlvyVO = new DataMap();
dlvyVO.put("ordrDlvyInnb", orderItem.get("ordrDlvyInnb"));
dlvyVO.put("sopmalCd", orderItem.get("sopmalCd"));
dlvyVO.put("ordrInnb", ordrInnb);
dlvyVO.put("dlivyInnb", orderItem.get("dlivyInnb"));
Integer dlvyResult = 0;
log.debug(" 주문 배송 상태 변경 전 VO dlvyVO : {}", dlvyVO);
dlvyResult = sweetTrackerMapper.updateOrdrDlvyStatusUpdt6575(dlvyVO);
// 주문 상태 부분배송중(70), 배송중(75) 처리
DataMap ordrVO = new DataMap();
ordrVO.put("ordrInnb", ordrInnb);
ordrVO.put("sopmalCd", orderItem.get("sopmalCd"));
log.debug("주문상태 변경 전 VO 확인 : {}", dlivyVO);
mapper.updateTsOrdrStatusUpdt6575(ordrVO);
dlivyVO.setPurchsDcsnDvCd("02"); // 시스템
dlivyVO.setSopmalCd(String.valueOf(orderItem.get("sopmalCd")));
dlivyVO.setDlivyInnb(String.valueOf(orderItem.get("dlivyInnb")));
log.debug("출고처리 전 VO 확인 : {}", dlivyVO);
mapper.updateTsPurchsDcsnSttusUpdt(dlivyVO);
logSj = "구매확정(" + orderItem.get("dlivyCdNb") + ")";
logDtlCn = "[시스템]이 " + logSj + " 처리를 하였습니다.";
orderLogVO.setLogSj(logSj);
orderLogVO.setLogDtlCn(logDtlCn);
orderLogVO.setOrdrInnb(BigInteger.valueOf(Long.valueOf(ordrInnb)));
orderLogVO.setSopmalCd(String.valueOf(orderItem.get("sopmalCd")));
orderLogVO.setDlivyInnb(String.valueOf(orderItem.get("dlivyInnb")));
orderLogVO.setLogDvCd("05"); // 출고(export)
orderLogVO.setDvCd("03"); // 시스템
orderLogVO.setOpetrNm("시스템");
orderLogVOList.add(orderLogVO);
}
}
message.put("status", "1");
message.put("message", "success");
} catch (Exception e) {
e.printStackTrace();
message.put("status", "0");
message.put("message", "fail");
} finally {
insertBOOrdrLogRegist(orderLogVOList);
}
log.debug("UpdateTsAtmcPurchsDcsnTasklet 종료");
log.debug("==========================================");
return RepeatStatus.FINISHED;
}
/**
* 배송 관련 주문 로그 등록
*/
private void insertBOOrdrLogRegist(List<TsOrderLogVO> logList) {
if (!CollectionUtils.isEmpty(logList)) {
for (TsOrderLogVO logVO : logList) {
mapper.insertOrderLog(logVO);
}
}
}
/**
* 마일리지 적립 add / 기본적립
*
* @param mlgVo
* @return DataMap
*/
@Transactional
public DataMap insertBOMlgAdd(TsMlgVO mlgVo) throws WnbtRestException {
log.debug("마일리지 적립 add1 => {}", mlgVo);
DataMap message = new DataMap();
message.put("status", "0");
message.put("message", "");
//마일리지 객체가 있을 경우
if(mlgVo != null) {
//null인 항목은 기본값 처리
mlgVo = setBasicIfNull(mlgVo);
log.debug("마일리지 적립 add2 => {}", mlgVo);
// 쇼핑몰 코드로 마일리지 정보 및 회원 등급 정보 조회
DataMap shopSetUpMap = mapper.selectBOShopInqire(mlgVo.getSopmalCd());
//회원고유번호
String mbrInnb = mlgVo.getMbrInnb();
//주문번호
BigInteger ordrInnb = objNumToBigInteger(mlgVo.getOrdrInnb());
//구매이고, 회원인 경우
//회원인 경우 설정된 만료기간 필요, 비회원이면 마일리지 지급 안함
boolean isOrdrMbrInbb =!BigInteger.ZERO.equals(ordrInnb) && !"0".equals(mbrInnb);
if (isOrdrMbrInbb && "01".equals(mlgVo.getMlgApplcDvCd())) {
//마일리지 사용 여부
String mlgPymntAt = StringUtil.isNullToString(shopSetUpMap.get("mlgPymntAt"));
//마일리지 미사용 시
if("N".equals(mlgPymntAt)) {
throw new WnbtRestException("마일리지 미사용 상태입니다.");
}
//유효기간 제한 여부
//y, 제한 일자 가져옴, n 무제한
String mlgValidPdAt = StringUtil.isNullToString(mlgVo.getMlgValidPdAt());
//vo에 유효기간 파라미터가 없는 경우 쇼핑몰 설정 따름
if("".equals(mlgValidPdAt)) {
mlgValidPdAt = StringUtil.isNullToString(shopSetUpMap.get("mlgValidPdAt"));
}
log.info("mlgValidPdAt {}", mlgValidPdAt);
// 제한 설정이 Y시 쇼핑몰 설정의 기간설정
if("Y".equals(mlgValidPdAt)) {
String mlgValidPdStr = StringUtil.isNullToString(shopSetUpMap.get("mlgValidPd"));
int mlgValidPd = "".equals(mlgValidPdStr) ? 0 : Integer.parseInt(mlgValidPdStr);
mlgVo.setMlgValidPd(mlgValidPd);
}
//최대 마일리지 제한 여부
//y 제한, n 무제한
String mlgMxmmPymntAmtAt = StringUtil.isNullToString(shopSetUpMap.get("mlgMxmmPymntAt"));
if("Y".equals(mlgMxmmPymntAmtAt)) {
String mlgMxmmAccmlmnyAmtStr = "".equals(StringUtil.isNullToString(shopSetUpMap.get("mlgMxmmAccmlmnyAmt")))
? "0" : StringUtil.isNullToString(shopSetUpMap.get("mlgMxmmAccmlmnyAmt"));
//마일리지 최대 금액
BigDecimal mlgMxmmAccmlmnyAmt = new BigDecimal(mlgMxmmAccmlmnyAmtStr);
//최대 금액이 0이 아니고, 적립 금액이 제한 이상인 경우 제한 금액으로 입력
if(mlgVo.getAccmlmnyAmt().compareTo(mlgMxmmAccmlmnyAmt) > 0) {
mlgVo.setAccmlmnyAmt(mlgMxmmAccmlmnyAmt);
}
}
} else if (isOrdrMbrInbb && ("03".equals(mlgVo.getMlgApplcDvCd()) || "04".equals(mlgVo.getMlgApplcDvCd())
|| "05".equals(mlgVo.getMlgApplcDvCd()))) {
//주문에 관해서 리뷰 작성시 마일리지 지급
//03 - 일반, 04 - 한달 리뷰, 05 - 포토리뷰
// 마일리지 만료 개월수가 있고 0보다 크고, 제한 여부 Y인경우
if(mlgVo.getMlgValidPd() != null){
mlgVo.setMlgValidPdAt("Y");
}
}
Integer result = 0;
//고정값
//01 지급
mlgVo.setMlgDvCd("01");
//add 적립구분
mlgVo.setMlgAccmlDvCd("add");
//01 온오프 구분
String onOfDvCd = StringUtil.isNullToString(mlgVo.getOnlineOflneDvCd());
if("".equals(onOfDvCd)) {
mlgVo.setOnlineOflneDvCd("01");
}
//손실 0 입력
mlgVo.setLoss(BigDecimal.ZERO);
//잔액
mlgVo.setBlce(mlgVo.getAccmlmnyAmt());
//적립 입력
result = mapper.insertBOMlgAdd(mlgVo);
//손실 목록 조회
List<DataMap> lossList = mapper.selectBOLoss(mlgVo);
//손실이 있는 경우
if(!lossList.isEmpty()) {
//적립값
BigDecimal accmlmnyAmt = mlgVo.getAccmlmnyAmt().abs();
//손실 수정 vo
TsMlgVO mlgLossUpdtVo = new TsMlgVO();
//잔액 수정 vo
TsMlgVO mlgBlceUpdtVo = new TsMlgVO();
for(DataMap map : lossList) {
//손실 내역
BigDecimal loss = objNumToBigDecimal(map.get("loss"));
//손실 마일리지 번호
BigInteger lossMlgInnb = objNumToBigInteger(map.get("mlgInnb"));
//손실 쇼핑몰 코드
String lossSopmalCd = StringUtil.isNullToString(map.get("sopmalCd"));
//손실 주문번호
BigInteger lossOrdrInnb = objNumToBigInteger(map.get("ordrInnb"));
TsMlgVO useMlgVo = new TsMlgVO();
useMlgVo.setMbrDvCd(StringUtil.isNullToString(map.get("mbrDvCd")));
useMlgVo.setMbrInnb(StringUtil.isNullToString(map.get("mbrInnb")));
useMlgVo.setOrdrInnb(lossOrdrInnb);
useMlgVo.setAccmlmnyAmt(objNumToBigDecimal(map.get("accmlmnyAmt")));
//적립으로 인한 손실 차감을 상세 정보에 입력시,
//손실원인 적립 취소의 마일리지 번호는 최초 하나만 입력
BigInteger useMlgInnb = mapper.selectBOMlgLossAddCanclMlgInnb(useMlgVo);
log.debug("useMlgInnb add {}", useMlgInnb);
//적립액이 로스보다 크거나 같은 경우
if(accmlmnyAmt.compareTo(loss) >= 0) {
//적립 요청액에서 손실 금액 차감
accmlmnyAmt = accmlmnyAmt.subtract(loss);
//손실 수정
mlgLossUpdtVo.setMlgInnb(lossMlgInnb);
mlgLossUpdtVo.setLoss(BigDecimal.ZERO);
mlgLossUpdtVo.setUpdusrDvCd(mlgVo.getRegusrDvCd());
mlgLossUpdtVo.setUpdusr(mlgVo.getRegusr());
mlgLossUpdtVo.setMbrInnb(mlgVo.getMbrInnb());
mlgLossUpdtVo.setMbrDvCd(mlgVo.getMbrDvCd());
if(accmlmnyAmt.compareTo(loss) == 0) {
mlgLossUpdtVo.setCanclAt("Y");
}
mapper.updateBOMlgLoss(mlgLossUpdtVo);
//적립 수정
mlgBlceUpdtVo.setMlgInnb(mlgVo.getMlgInnb());
mlgBlceUpdtVo.setBlce(accmlmnyAmt);
mlgBlceUpdtVo.setUpdusrDvCd(mlgVo.getRegusrDvCd());
mlgBlceUpdtVo.setUpdusr(mlgVo.getRegusr());
mlgBlceUpdtVo.setMbrInnb(mlgVo.getMbrInnb());
mlgBlceUpdtVo.setMbrDvCd(mlgVo.getMbrDvCd());
mapper.updateBOMlgBlce(mlgBlceUpdtVo);
//손실 차감 금액 기록
mlgVo.setMlgApplcResn("적립에 의한 손실 차감");
mlgVo.setManageMemo("적립의에 의한 손실 차감");
insertMlgLossDn(mlgVo, loss);
//상세 내역 등록
insertMlgUseDtlAdd(mlgVo, lossSopmalCd, useMlgInnb, lossMlgInnb, loss);
} else {
//loss가 더 큰 경우
BigDecimal subResult = loss.subtract(accmlmnyAmt);
log.debug("subResult add {}", subResult);
//손실 수정
mlgLossUpdtVo.setMlgInnb(lossMlgInnb);
mlgLossUpdtVo.setLoss(subResult);
mlgLossUpdtVo.setUpdusrDvCd(mlgVo.getRegusrDvCd());
mlgLossUpdtVo.setUpdusr(mlgVo.getRegusr());
mlgLossUpdtVo.setMbrInnb(mlgVo.getMbrInnb());
mlgLossUpdtVo.setMbrDvCd(mlgVo.getMbrDvCd());
mapper.updateBOMlgLoss(mlgLossUpdtVo);
//적립 수정
mlgBlceUpdtVo.setMlgInnb(mlgVo.getMlgInnb());
mlgBlceUpdtVo.setBlce(BigDecimal.ZERO);
mlgBlceUpdtVo.setUpdusrDvCd(mlgVo.getRegusrDvCd());
mlgBlceUpdtVo.setUpdusr(mlgVo.getRegusr());
mlgBlceUpdtVo.setMbrInnb(mlgVo.getMbrInnb());
mlgBlceUpdtVo.setMbrDvCd(mlgVo.getMbrDvCd());
mapper.updateBOMlgBlce(mlgBlceUpdtVo);
//손실 차감 금액 기록
mlgVo.setMlgApplcResn("적립에 의한 손실 차감");
mlgVo.setManageMemo("적립에 의한 손실 차감");
insertMlgLossDn(mlgVo, accmlmnyAmt);
//상세 내역 등록
insertMlgUseDtlAdd(mlgVo, lossSopmalCd, useMlgInnb, lossMlgInnb, accmlmnyAmt);
accmlmnyAmt = BigDecimal.ZERO;
}
//적립값이 0이 되면 break
if(accmlmnyAmt.compareTo(BigDecimal.ZERO) == 0) {
break;
}
}
}
if (result > 0) {
message.put("result", "success");
} else {
message.put("result", "fail");
}
}
return message;
}
/**
* 손실 차감 금액 기록
* @param mlgVo
*/
private void insertMlgLossDn(TsMlgVO mlgVo, BigDecimal dnAccmlmnyAmt) {
TsMlgVO boMlgDnVO = new TsMlgVO();
boMlgDnVO.setOrdrInnb(mlgVo.getOrdrInnb());
boMlgDnVO.setMbrInnb(mlgVo.getMbrInnb());
boMlgDnVO.setMbrDvCd(mlgVo.getMbrDvCd());
boMlgDnVO.setSopmalCd(mlgVo.getSopmalCd());
boMlgDnVO.setOrdrCd(mlgVo.getOrdrCd());
boMlgDnVO.setMlgDvCd("02");
boMlgDnVO.setMlgAccmlDvCd("dn");
boMlgDnVO.setMlgApplcDvCd("11");
boMlgDnVO.setMlgApplcResn(mlgVo.getMlgApplcResn());
boMlgDnVO.setAccmlmnyAmt(dnAccmlmnyAmt.abs().negate());
boMlgDnVO.setBlce(BigDecimal.ZERO);
boMlgDnVO.setLoss(BigDecimal.ZERO);
boMlgDnVO.setManageCd("loss recovery");
boMlgDnVO.setManageMemo(mlgVo.getManageMemo());
boMlgDnVO.setEndAt("N");
boMlgDnVO.setCanclAt("N");
boMlgDnVO.setOnlineOflneDvCd(mlgVo.getOnlineOflneDvCd());
boMlgDnVO.setStrInnb(mlgVo.getStrInnb());
boMlgDnVO.setStrCd(mlgVo.getStrCd());
boMlgDnVO.setStrnm(mlgVo.getStrnm());
boMlgDnVO.setStrDvCd(mlgVo.getStrDvCd());
boMlgDnVO.setPosCd(mlgVo.getPosCd());
boMlgDnVO.setRegusrDvCd("03");
boMlgDnVO.setRegusr(0);
mapper.insertBOMlgDn(boMlgDnVO);
}
/**
* 적립시 마일리지 상세 등록 공통
*/
public void insertMlgUseDtlAdd(TsMlgVO mlgVo, String lossSopmalCd,
BigInteger useMlgInnb, BigInteger lossMlgInnb, BigDecimal amt){
BOMlgUseDtlVO boMlgUseDtlVO = new BOMlgUseDtlVO();
boMlgUseDtlVO.setAccmlMlgInnb(mlgVo.getMlgInnb());
boMlgUseDtlVO.setUseMlgInnb(useMlgInnb);
boMlgUseDtlVO.setAccmlSopmalCd(mlgVo.getSopmalCd());
boMlgUseDtlVO.setUseSopmalCd(lossSopmalCd);
boMlgUseDtlVO.setMlgAccmlDvCd("_add");
boMlgUseDtlVO.setFrstUseAmt(amt);
boMlgUseDtlVO.setUseAmt(amt);
boMlgUseDtlVO.setCanclAmt(BigDecimal.ZERO);
boMlgUseDtlVO.setCanclAt("N");
boMlgUseDtlVO.setLossMlgInnb(lossMlgInnb);
boMlgUseDtlVO.setRegusrDvCd(mlgVo.getRegusrDvCd());
boMlgUseDtlVO.setRegusr(mlgVo.getRegusr());
mapper.insertBOMlgUseDtlAddCancl(boMlgUseDtlVO);
}
/**
* TsMlgVO 항목 중 null인 경우 기본값 입력 처리
* @param
* @return
*/
public TsMlgVO setBasicIfNull(TsMlgVO mlgVo) {
if(mlgVo.getOrdrInnb() == null) {
mlgVo.setOrdrInnb(BigInteger.ZERO);
}
if(mlgVo.getBbscttInnb() == null) {
mlgVo.setBbscttInnb(BigInteger.ZERO);
}
if(mlgVo.getOrdrCd() == null) {
mlgVo.setOrdrCd("");
}
if(mlgVo.getLoss() == null) {
mlgVo.setLoss(BigDecimal.ZERO);
}
if(mlgVo.getOrdrInfo() == null) {
mlgVo.setOrdrInfo("");
}
if(mlgVo.getManageCd() == null) {
mlgVo.setManageCd("");
}
if(mlgVo.getManageMemo() == null) {
mlgVo.setManageMemo("");
}
if(mlgVo.getExtshBatchBundle() == null) {
mlgVo.setExtshBatchBundle("");
}
if(mlgVo.getStrInnb() == null) {
mlgVo.setStrInnb(0);
}
if(mlgVo.getStrCd() == null) {
mlgVo.setStrCd("");
}
if(mlgVo.getStrnm() == null) {
mlgVo.setStrnm("");
}
if(mlgVo.getPosCd() == null) {
mlgVo.setPosCd("");
}
if(mlgVo.getBlce() == null) {
mlgVo.setBlce(BigDecimal.ZERO);
}
if(mlgVo.getMlgValidDt() == null) {
mlgVo.setMlgValidDt(0);
}
return mlgVo;
}
/**
* 적립/지급 시, 손실 존재하면 손실 계산 후 결과 리턴
* @param lossList
* @return
*/
public DataMap calculateLossList(List<DataMap> lossList, BigDecimal accmlmnyAmt) {
for(DataMap map : lossList) {
BigDecimal loss = objNumToBigDecimal(map.get("loss"));
//적립액이 로스보다 크거나 같은 경우
if(accmlmnyAmt.compareTo(loss) >= 0) {
accmlmnyAmt = accmlmnyAmt.subtract(loss);
map.put("loss", 0);
} else {
//loss가 더 큰 경우
BigDecimal subResult = loss.subtract(accmlmnyAmt);
accmlmnyAmt = BigDecimal.ZERO;
map.put("loss", subResult);
}
//적립값이 0이 되면 break
if(accmlmnyAmt.compareTo(BigDecimal.ZERO) == 0) {
break;
}
}
DataMap resultMap = new DataMap();
resultMap.put("lossList", lossList);
resultMap.put("accmlmnyAmt", accmlmnyAmt);
return resultMap;
}
/**
* 객체가 null 인지 확인하고 null 인 경우 0, 아니면 BigDecimal 숫자 리턴
* @param object
* @return
*/
public BigDecimal objNumToBigDecimal(Object object) {
BigDecimal decimal = BigDecimal.ZERO;
log.debug("object {}", object);
if (object == null) {
return decimal;
} else if (object instanceof BigDecimal bigDecimal){
return bigDecimal;
} else {
return BigDecimal.valueOf((Integer) object);
}
}
/**
* 객체가 null 인지 확인하고 null 인 경우 0, 아니면 BigDecimal 숫자 리턴
* @param object
* @return
*/
public BigInteger objNumToBigInteger(Object object) {
BigInteger bigInteger = BigInteger.ZERO;
if (object == null) {
return bigInteger;
} else if (object instanceof BigInteger bigDecimal){
return bigDecimal;
} else {
String str = object.toString().trim();
if(str.isEmpty()){
return BigInteger.ZERO;
}
return new BigInteger(str);
}
}
}

View File

@@ -0,0 +1,66 @@
package com.wb.domainserver.export.vo;
import com.wb.domainserver.common.vo.AbstractVO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
*
* 마일리지 VO
* @author 추지훈
* @since 2024-02-05
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-05-21 이운산 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class BOMlgUseDtlVO extends AbstractVO {
private static final long serialVersionUID = 1L;
/**
* 마일리지 적립 정보
*/
/** 이용취소마일리지 고유번호 */
private BigInteger useCanclMlgInnb;
/** 적립마일리지 고유번호 */
private BigInteger accmlMlgInnb;
/** 이용마일리지고유번호 */
private BigInteger useMlgInnb;
/** 적립쇼핑몰 코드 */
private String accmlSopmalCd;
/** 이용쇼핑몰 코드 */
private String useSopmalCd;
/** 마일리지 적립구분 */
private String mlgAccmlDvCd;
/** 이용금액 */
private BigDecimal useAmt;
/** 최초이용액 */
private BigDecimal frstUseAmt;
/** 취소액 */
private BigDecimal canclAmt;
/** 최소여부 */
private String canclAt;
/** 상위이용취소마일리지고유번호 */
private BigInteger upperUseCanclMlgInnb;
/** 손실 발생 마일리지 번호 */
private BigInteger lossMlgInnb;
/** 등록자 구분 */
private String regusrDvCd;
/** 수정자 구분 */
private String updusrDvCd;
}

View File

@@ -0,0 +1,132 @@
package com.wb.domainserver.export.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
/**
*
* 마일리지 VO
* @author 추지훈
* @since 2024-02-05
* @version 1.0
* @see
*
* <pre>
* == (Modification Information) == 개정이력
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2024-02-05 추지훈 최초 생성
*
* </pre>
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class TsMlgVO {
private static final long serialVersionUID = 1L;
/**
* 마일리지 정보
*/
/** 마일리지 고유번호 */
private BigInteger mlgInnb;
/** 주문고유번호 */
private BigInteger ordrInnb;
/** 회원고유번호 */
private String mbrInnb;
/** 회원구분코드 */
private String mbrDvCd;
/** 쇼핑몰 코드 */
private String sopmalCd;
/** 게시글고유번호 */
private BigInteger bbscttInnb;
/** 주문코드 */
private String ordrCd;
/** 마일리지구분 */
private String mlgDvCd;
/** 마일리지적립구분 */
private String mlgAccmlDvCd;
/** 마일리지적용구분 */
private String mlgApplcDvCd;
/** 마일리지적용사유 */
private String mlgApplcResn;
/** 적립금액 */
private BigDecimal accmlmnyAmt;
/** 잔액 */
private BigDecimal blce;
/** 손실 */
private BigDecimal loss;
/** 사용가능시작일시 */
private Date usePosblBgnDt;
/** 사용가능종료일시 */
private Date usePosblEndDt;
/** 주문정보 */
private String ordrInfo;
/** 관리코드 */
private String manageCd;
/** 관리메모 */
private String manageMemo;
/** 만료여부 */
private String endAt;
/** 취소여부 */
private String canclAt;
/** 취소일시 */
private Date canclDt;
/** 소멸 배치 묶음 */
private String extshBatchBundle;
/** 온오프 구분 */
private String onlineOflneDvCd;
/** 매장고뷰번호 */
private Integer strInnb;
/** 매장코드 */
private String strCd;
/** 매장명 */
private String strnm;
/** 매장구분 */
private String strDvCd;
/** 포스코드 */
private String posCd;
/** 등록자구분 */
private String regusrDvCd;
/** 수정자구분 */
private String updusrDvCd;
/**
* db 없는 항목
*/
/** 마일리지 유효 개월 수 */
private Integer mlgValidPd;
/** 마일리지 유효기간 - 특정일자 지정시 사용 */
private Integer mlgValidDt;
/** 마일리지 유효기간 제한 여부 */
private String mlgValidPdAt;
/** 사용쇼핑몰 코드 */
private String useSopmalCd;
/** 유효기간 수정_종료일자 */
private String usePosblEndDtStr;
/** 문자 입력 내용 */
private String mlgSmsCn;
/** 문자 발송 전화번호 */
private String mbtlnb;
/** 문자 발송 고객명 */
private String mbrNm;
/** 등록자 */
private int regusr;
/** 수정자 */
private int updusr;
}

View File

@@ -0,0 +1,33 @@
package com.wb.domainserver.export.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = false)
public class TsPurchsDcsnVO implements Serializable {
private static final long serialVersionUID = 1L;
private String sopmalCd;
private String dlivyInnb;
private String ordrGoodsOptnInnb;
private String optnTy;
private String qy;
private String ordrInnb;
private String oiopOrdrDlvyInnb;
private String purchsDcsnDvCd;
}

View File

@@ -0,0 +1,233 @@
package com.wb.domainserver.gift.jobs;
import com.wb.domainserver.ntcn.tasklet.common.InsertTsMssageSureTasklet;
import com.wb.domainserver.gift.tasklet.InsertMssageGiftDlvyAddrTasklet;
import com.wb.domainserver.gift.tasklet.SelectGiftOrderCancelTasklet;
import com.wb.domainserver.gift.tasklet.InsertGiftDlvyAddrEmailTasklet;
import com.wb.domainserver.gift.tasklet.InsertGiftDlvyAddrNtcnTalkTasklet;
import com.wb.domainserver.ntcn.tasklet.common.SelectMessageSndngInqireTasklet;
import com.wb.domainserver.ntcn.tasklet.common.SendTsEmailTasklet;
import com.wb.domainserver.ntcn.util.CustomEmailDecider;
import com.wb.domainserver.ntcn.util.CustomJobExecutionListener;
import com.wb.domainserver.ntcn.util.CustomNtcnTalkDecider;
import com.wb.domainserver.ntcn.util.CustomSmsDecider;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.listener.ExecutionContextPromotionListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@RequiredArgsConstructor
@Configuration
//@EnableBatchProcessing
public class MssageGiftDlvyAddrConfig extends DefaultBatchConfiguration{
private static final Logger logger = LoggerFactory.getLogger(MssageGiftDlvyAddrConfig.class);
//메세지발송 여부 확인
private final SelectMessageSndngInqireTasklet selectMessageSndngInqireTasklet;
//이메일 디사이더
private final CustomEmailDecider customEmailMarktAgreDecider;
//문자 디사이더
private final CustomSmsDecider customSmsMarktAgreDecider;
//알림톡 디사이더
private final CustomNtcnTalkDecider customNtcnTalkMarktAgreDecider;
//선물하기 배송주소 미입력 알림 이메일 대상 생성(미구현)
private final InsertGiftDlvyAddrEmailTasklet insertGiftDlvyAddrEmailTasklet;
//선물하기 배송주소 미입력 알림 이메일 발송
private final SendTsEmailTasklet sendTsMarktAgreEmailTasklet;
//선물하기 배송주소 미입력 알림 문자 대상 생성
private final InsertMssageGiftDlvyAddrTasklet insertSmsGiftDlvyAddrTasklet;
//선물하기 배송주소 미입력 알림 알림톡 대상 생성(미구현)
private final InsertGiftDlvyAddrNtcnTalkTasklet insertGiftDlvyAddrNtcnTalkTasklet;
//선물하기 배송주소 미입력 알림 문자 및 알림톡 발송
private final InsertTsMssageSureTasklet insertCommMssageSureTasklet;
// 선물 거절 및 주소입력 기간 초과 주문 취소
private final SelectGiftOrderCancelTasklet selectGiftOrderCancel;
/* ##############################################################################################
선물 주소입력 알림 메세지 발송 START
################################################################################################# */
/**
* <선물 주소입력 알림 메세지 발송>
*/
@Bean
public Job mssageGiftDlvyAddrJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, ExecutionContextPromotionListener mssageSttusListener) {
return new JobBuilder("mssageGiftDlvyAddrJob", jobRepository)
.incrementer(new RunIdIncrementer())
.start(selectCommMessageSndngInqireTasklet(jobRepository, transactionManager))
.next(customEmailMarktAgreDecider)
.on("EXECUTE").to(giftDlvyAddrEmailFlow(jobRepository, transactionManager))
.from(customEmailMarktAgreDecider).on("SKIP").to(customSmsMarktAgreDecider)
.from(giftDlvyAddrEmailFlow(jobRepository, transactionManager)).on("*").to(customSmsMarktAgreDecider)
.next(customSmsMarktAgreDecider)
.on("EXECUTE").to(giftDlvyAddrSmsFlow(jobRepository, transactionManager))
.from(customSmsMarktAgreDecider).on("SKIP").to(customNtcnTalkMarktAgreDecider)
.from(giftDlvyAddrSmsFlow(jobRepository, transactionManager)).on("*").to(customNtcnTalkMarktAgreDecider)
.next(customNtcnTalkMarktAgreDecider)
.on("EXECUTE").to(giftDlvyAddrNtcnTalkFlow(jobRepository, transactionManager))
.from(customNtcnTalkMarktAgreDecider).on("SKIP").end()
.from(giftDlvyAddrNtcnTalkFlow(jobRepository, transactionManager)).on("*").end()
.end()
.listener(new CustomJobExecutionListener(
"FORM_DV_REMND",
"14",
"mssageGiftDlvyAddr"))
.build();
}
/**
* (공통)메세지 대상 조회 스텝
*/
@Bean
public Step selectCommMessageSndngInqireTasklet(JobRepository jobRepository,
PlatformTransactionManager transactionManager) {
return new StepBuilder("selectCommMessageSndngInqireTasklet", jobRepository)
.tasklet(selectMessageSndngInqireTasklet, transactionManager)
.build();
}
/**
* 선물하기 배송주소 미입력 알림 이메일 플로우(미사용)
*/
@Bean
public Flow giftDlvyAddrEmailFlow(JobRepository jobRepository,
PlatformTransactionManager transactionManager){
return new FlowBuilder<Flow>("giftDlvyAddrEmailFlow")
.start(insertGiftDlvyAddrEmailStep(jobRepository, transactionManager))
.next(sendGiftDlvyAddrEmailStep(jobRepository, transactionManager))
.build();
}
/**
* 선물하기 배송주소 미입력 알림 이메일 대상 생성 스텝(미사용-내부 미구현)
*/
@Bean
public Step insertGiftDlvyAddrEmailStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager){
return new StepBuilder("insertGiftDlvyAddrEmailStep", jobRepository)
.tasklet(insertGiftDlvyAddrEmailTasklet, transactionManager)
.build();
}
/**
* 선물하기 배송주소 미입력 알림 이메일 발송 스텝(미사용)
*/
@Bean
public Step sendGiftDlvyAddrEmailStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager){
return new StepBuilder("sendGiftDlvyAddrEmailStep", jobRepository)
.tasklet(sendTsMarktAgreEmailTasklet, transactionManager)
.build();
}
/**
* 선물하기 배송주소 미입력 알림 문자 플로우(사용)
*/
@Bean
public Flow giftDlvyAddrSmsFlow(JobRepository jobRepository,
PlatformTransactionManager transactionManager){
return new FlowBuilder<Flow>("giftDlvyAddrSmsFlow")
.start(insertSmsGiftDlvyAddrStep(jobRepository, transactionManager))
.next(insertCommMssageSureStep(jobRepository, transactionManager))
.build();
}
/**
* 선물하기 배송주소 미입력 알림 문자 대상 생성 스텝(사용)
*/
@Bean
public Step insertSmsGiftDlvyAddrStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager) {
return new StepBuilder("insertSmsGiftDlvyAddrStep", jobRepository)
.tasklet(insertSmsGiftDlvyAddrTasklet, transactionManager)
.build();
}
/**
* 선물하기 배송주소 미입력 알림 문자 발송 스텝(사용)
*/
@Bean
public Step insertCommMssageSureStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager) {
return new StepBuilder("insertCommMssageSureStep", jobRepository)
.tasklet(insertCommMssageSureTasklet, transactionManager)
.build();
}
/**
* 선물하기 배송주소 미입력 알림 알림톡 플로우(미사용)
*/
@Bean
public Flow giftDlvyAddrNtcnTalkFlow(JobRepository jobRepository,
PlatformTransactionManager transactionManager){
return new FlowBuilder<Flow>("giftDlvyAddrNtcnTalkFlow")
.start(insertGiftDlvyAddrNtcnTalkStep(jobRepository, transactionManager))
.next(insertCommMssageSureStep(jobRepository, transactionManager))
.build();
}
/**
* 선물하기 배송주소 미입력 알림 알림톡 대상 생성 스텝(미사용-내부 미구현)
*/
@Bean
public Step insertGiftDlvyAddrNtcnTalkStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager) {
return new StepBuilder("insertGiftDlvyAddrNtcnTalkStep", jobRepository)
.tasklet(insertGiftDlvyAddrNtcnTalkTasklet, transactionManager)
.build();
}
/* ##############################################################################################
선물 주소입력 알림 메세지 발송 END
################################################################################################# */
/* ##############################################################################################
선물 거절 및 주소입력 기간 초과 주문 취소 START
################################################################################################# */
/**
* 선물주문무효
*/
@Bean
public Job giftOrderCancelJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new JobBuilder("giftOrderCancelJob", jobRepository)
.start(selectGiftOrderCancel(jobRepository, transactionManager))
.incrementer(new RunIdIncrementer())
.build();
}
/**
* 선물주문무효
*/
@Bean
public Step selectGiftOrderCancel(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("selectGiftOrderCancel", jobRepository)
.tasklet(selectGiftOrderCancel, transactionManager)
.build();
}
/* ##############################################################################################
선물 거절 및 주소입력 기간 초과 주문 취소 END
################################################################################################# */
}

View File

@@ -0,0 +1,67 @@
package com.wb.domainserver.gift.tasklet;
import com.wb.domainserver.common.CommonService;
import com.wb.domainserver.mapper.gcone.EmailMapper;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.dataaccess.DataMap;
import com.wb.domainserver.util.ntcn.DataShareBean;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RequiredArgsConstructor
public class InsertGiftDlvyAddrEmailTasklet implements Tasklet {
@Autowired
private EmailMapper emailMapper;
private final DataShareBean dataShareBean;
private final CommonService commonService;
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
//조회 양식 코드 세팅
DataMap paramMap = new DataMap();
paramMap.put("formDtlDvCd", "01");
paramMap.put("formDvCd", "FORM_DV_CMMN");
paramMap.put("sttus", "3");
paramMap.put("secretKey", commonService.selectSecretkey());
emailMapper.insertMbrMarktAgreEmail(paramMap);
emailMapper.insertMbrMarktAgreEmailTo(paramMap);
emailMapper.updateMbrMarktAgreEmailSttus();
//상태 삭제
emailMapper.deleteMbrMarktAgreEmail();
StepContext stepContext= StepSynchronizationManager.getContext();
ExecutionContext executionContext = stepContext.getStepExecution().getJobExecution().getExecutionContext();
executionContext.put("sttus", "3");
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,234 @@
package com.wb.domainserver.gift.tasklet;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.mapper.gcone.MssageMapper;
import com.wb.domainserver.ntcn.vo.TsMssageVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import com.wb.domainserver.util.ntcn.DataShareBean;
import com.wb.domainserver.util.ntcn.NtcnUtil;
import com.wb.domainserver.util.string.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
@JobScope
public class InsertGiftDlvyAddrNtcnTalkTasklet implements Tasklet {
private static final Logger logger = LoggerFactory.getLogger(InsertGiftDlvyAddrNtcnTalkTasklet.class);
@Autowired
private MssageMapper mapper;
private final DataShareBean dataShareBean;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
Map<String, Object> message = dataShareBean.getData("message");
ExecutionContext jobContext = chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext();
// Set<String> result = (Set<String>) jobContext.get("result");
// log.debug("result {}", result);
// if(!result.contains("ntcnTalkY")){
// return RepeatStatus.FINISHED;
// }
//조회 양식 코드 세팅
DataMap paramMap = new DataMap();
paramMap.put("formDtlDvCd", StringUtil.isNullToString(message.get("formDtlDvCd")));
paramMap.put("formDvCd", StringUtil.isNullToString(message.get("formDvCd")));
paramMap.put("batchNm", StringUtil.isNullToString(message.get("batchNm")));
List<DataMap> selectNtcnTalkTrgtList = (List<DataMap>) message.get("selectNtcnTalkTrgtList");
// 발송 대상 목록을 쇼핑몰 별로 그룹화하여 새로운 리스트로 분리 생성
//알림톡
if(selectNtcnTalkTrgtList != null) {
String dv = "AT";
log.debug("first selectNtcnTalkTrgtList {}", selectNtcnTalkTrgtList);
//양식 조회
Map<String, List<TsMssageVO>> makeGroupeSmsData
= makeGroupedMssageData(selectNtcnTalkTrgtList, dv);
DataMap resultMap = processGroupedMssageData(makeGroupeSmsData);
List<BigInteger> smsInnbNtcnList = (List<BigInteger>) resultMap.get("smsInnbNtcnList");
List<String> sopmalCdList = (List<String>) resultMap.get("sopmalCdList");
List<DataMap> dataList = (List<DataMap>) resultMap.get("dataList");
log.debug("before selectNtcnTalkTrgtList {}", selectNtcnTalkTrgtList);
selectNtcnTalkTrgtList = mergeListsOnKeyValue(selectNtcnTalkTrgtList, dataList);
log.debug("after selectNtcnTalkTrgtList {}", selectNtcnTalkTrgtList);
message.put("dataNtcnTalkList", dataList);
message.put("smsInnbNtcnList", smsInnbNtcnList);
message.put("selectNtcnTalkTrgtList", selectNtcnTalkTrgtList);
dataShareBean.putData("message", message);
}
log.debug("message {}", message);
return RepeatStatus.FINISHED;
}
/**
* 발송 대상 그룹 처리
* 발송 대상 목록을 쇼핑몰 별로 그룹화하여 새로운 리스트로 분리 생성
* @param groupedData
*/
public Map<String, List<TsMssageVO>> makeGroupedMssageData(List<DataMap> selectedList, String dv){
return selectedList.stream()
.map(map -> {
TsMssageVO tsMssageVO = new TsMssageVO();
tsMssageVO.setSopmalCd(StringUtil.isNullToString(map.get("sopmalCd")));
tsMssageVO.setRegusrDv("03");//시스템
tsMssageVO.setStrInnb(BigInteger.ZERO);
tsMssageVO.setStrNm("");
tsMssageVO.setStrDv("");
//예약 날짜
// String resveDtStr = StringUtil.isNullToString(map.get("resveDt"));
//예약 날짜
String resveDtStr = StringUtil.isNullToString(map.get("sndngDt"));
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date parseDate = formatter.parse(resveDtStr);
tsMssageVO.setResveDt(parseDate);
} catch (ParseException e) {
throw new RuntimeException(e);
}
tsMssageVO.setChrSttus("REG");
tsMssageVO.setHead("");
String cn = StringUtil.isNullToString("AT".equals(dv) ? map.get("msg") : map.get("smsCn"));
tsMssageVO.setCn(NtcnUtil.fixStr(cn));
tsMssageVO.setTail("");
//dv가 AT면 AT설정, 아니면 길이 계산 dv (sms, lms)
tsMssageVO.setDv("AT".equals(dv) ? dv : NtcnUtil.msgType(cn));
tsMssageVO.setSmsNm("surem");
tsMssageVO.setSndngNb(StringUtil.isNullToString(map.get("sndngNb")));
tsMssageVO.setRegusr(BigInteger.ZERO);
tsMssageVO.setUpdusr(BigInteger.ZERO);
//GC_SMS_TO 등록 정보
tsMssageVO.setSttus("REG");
log.debug("recptn ntcn nb {}", StringUtil.isNullToString(map.get("recptnNb")));
tsMssageVO.setRecptnNb(StringUtil.isNullToString(map.get("recptnNb")));
//tsMssageVO.setRecptnNb(StringUtil.isNullToString(map.get("mbtlnb")));
tsMssageVO.setCstmrIdnb(NtcnUtil.objNumToBigInteger(map.get("mbrInnb")));
tsMssageVO.setCstmrNm(StringUtil.isNullToString(map.get("mbrNm")));
tsMssageVO.setSubstWrd1(StringUtil.isNullToString(map.get("substWrd1")));
tsMssageVO.setSubstWrd2(StringUtil.isNullToString(map.get("substWrd2")));
tsMssageVO.setSubstWrd3(StringUtil.isNullToString(map.get("substWrd3")));
tsMssageVO.setSubstWrd4(StringUtil.isNullToString(map.get("substWrd4")));
tsMssageVO.setSubstWrd5(StringUtil.isNullToString(map.get("substWrd5")));
ObjectMapper objectMapper = new ObjectMapper();
String substDataStr = StringUtil.isNullToString(map.get("sndngData"));
//치환데이터 입력
tsMssageVO.setSubstData(substDataStr);
return tsMssageVO;
})
.collect(Collectors.groupingBy(TsMssageVO::getSopmalCd));
}
private static String getMbrInnb() {
return "mbrInnb";
}
/**
* 쇼핑몰별 그룹화된 데이터 메시지 처리
* @param map
* @return
*/
public DataMap processGroupedMssageData(Map<String, List<TsMssageVO>> groupedData) {
//그룹 처리 목록 FM_SMS 입력, FM_SMS에는 쇼핑몰코드별 입력
List<BigInteger> smsInnbList = new ArrayList<>();
List<String> sopmalCdList = new ArrayList<>();
List<TsMssageVO> list = new ArrayList<>();
List<DataMap> dataList = new ArrayList<>();
log.debug("groupedData {}", groupedData);
for (Map.Entry<String, List<TsMssageVO>> entry : groupedData.entrySet()) {
if(!entry.getValue().isEmpty()) {
list = entry.getValue();
TsMssageVO tsMsgVO = list.get(0);
//FM_SMS 등록
mapper.insertMssageRegist(tsMsgVO);
log.debug("tsMsgVO {}", tsMsgVO);
smsInnbList.add(tsMsgVO.getSmsInnb());
sopmalCdList.add(tsMsgVO.getSopmalCd());
DataMap smsMap = mapper.selectSmsInqire(tsMsgVO);
dataList.add(smsMap);
//SMS_INNB 입력
list.forEach(tsMssageToVO ->
tsMssageToVO.setSmsInnb(tsMsgVO.getSmsInnb())
);
mapper.insertMssageToListRegist(list);
}
}
DataMap resultMap = new DataMap();
if(!dataList.isEmpty()) {
mapper.updateMssageCntUpdtMap(dataList);
//문자 상태 수정
mapper.updateMssageCntSttusUpdtMap(dataList);
;
resultMap.put("smsInnbNtcnList", smsInnbList);
resultMap.put("sopmalCdList", sopmalCdList);
resultMap.put("dataList", dataList);
}
return resultMap;
}
public List<DataMap> mergeListsOnKeyValue(List<DataMap> list1, List<DataMap> list2) {
return list1.stream()
.map(map1 -> {
DataMap mergedMap = new DataMap();
mergedMap.putAll(map1);
list2.forEach(map2 -> {
if (map2.entrySet().stream().anyMatch(entry ->
map1.containsKey(entry.getKey()) && map1.get(entry.getKey()).equals(entry.getValue()))) {
mergedMap.putAll(map2);
}
});
return mergedMap;
})
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,149 @@
package com.wb.domainserver.gift.tasklet;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wb.domainserver.common.CommonService;
import com.wb.domainserver.mapper.gcone.MssageMapper;
import com.wb.domainserver.ntcn.vo.TsSendVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
/**
* 2024-11-03
* 쿠폰 발급 및 메세지 발송 처리
*
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class InsertMssageGiftDlvyAddrTasklet implements Tasklet {
private final MssageMapper mssageMapper;
private final Environment env;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.info("InsertMssageGiftDlvyAddrTasklet execute Step1 - StepContext 설정");
StepContext stepContext= StepSynchronizationManager.getContext();
ExecutionContext executionContext = stepContext.getStepExecution().getJobExecution().getExecutionContext();
executionContext.put("sttus", "28");
executionContext.put("sttusTo", "280");
String formDvCd = (String) executionContext.get("formDvCd");
String formDtlDvCd = (String) executionContext.get("formDtlDvCd");
log.info("formDvCd : {}", formDvCd);
log.info("formDtlDvCd : {}", formDtlDvCd);
DataMap paramMap = new DataMap();
// paramMap.put("secretKey", commonService.selectSecretkey());
paramMap.put("sttus", "28");
paramMap.put("formDvCd", formDvCd); // FORM_DV_REMND
paramMap.put("formDtlDvCd", formDtlDvCd); // 14
paramMap.put("subDay", "3"); // 선물하기 배송지 미입력 알림 발송 날짜 : 만료일 3일전
log.info("InsertMssageGiftDlvyAddrTasklet execute Step2 - 선물하기 배송주소 미입력 알림 SMS INSERT");
//GC_SMS 메세지 등록
mssageMapper.insertGiftDlvyAddrSms(paramMap);
log.info("InsertMssageGiftDlvyAddrTasklet execute Step3 - 선물하기 배송주소 미입력 대상자 조회");
//선물하기 배송주소 미입력 대상자 추출
List<DataMap> trgtList = mssageMapper.selectGiftDlvyAddrTrgtList(paramMap);
log.info("trgtList1 : {}", trgtList);
if(!trgtList.isEmpty()) {
// 주문식별코드 생성
trgtList = trgtList.stream()
.map(smsTo -> {
// 코드생성
String codeOrdrInnb = seq2code((BigInteger) smsTo.get("ordrInnb"));
smsTo.put("codeOrdrInnb",codeOrdrInnb);
log.info("ordrInnb : codeOrdrInnb : {}", smsTo.get("ordrInnb")+" : "+codeOrdrInnb);
String codeOrdrDlvyInnb = seq2code((BigInteger) smsTo.get("ordrDlvyInnb"));
smsTo.put("codeOrdrDlvyInnb",codeOrdrDlvyInnb);
log.info("ordrDlvyInnb : codeOrdrDlvyInnb : {}", smsTo.get("ordrDlvyInnb")+" : "+codeOrdrDlvyInnb);
smsTo.put("sttus","28");
// DataMap dataMap = new DataMap();
try {
String linkUrl = getProperty("presenturl") + "/" + smsTo.get("sopmalCd") +
"/gift/selectGiftOrdrForm?ordrInnb=" + codeOrdrInnb +
"&ordrDlvyInnb=" + codeOrdrDlvyInnb;
log.info("linkUrl", linkUrl);
smsTo.put("linkUrl",linkUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
return smsTo;
})
.toList();
log.info("trgtList2 : {}", trgtList);
log.info("InsertMssageGiftDlvyAddrTasklet execute Step3-1 - SMS_TO INSERT");
//GC_SMS_TO 메세지 대상자 등록
mssageMapper.insertGiftDlvyAddrSmsTo(trgtList);
log.info("InsertMssageGiftDlvyAddrTasklet execute Step3-2 - 선물하기 배송 상태값 UPDATE");
// OrderShipping GiftSttusCd 업데이트 (01:선물수락대기 -> 05:선물수락 알림발송)
mssageMapper.updateOrderShippingGiftSttus(trgtList);
} else {
log.info("InsertMssageGiftDlvyAddrTasklet execute Step3-3 - 대상자 없음");
}
log.info("InsertMssageGiftDlvyAddrTasklet execute Step4 - 대상없는 SMS DELETE");
// 대상 없는 경우(타겟카운트=0) 삭제 : GC_SMS
mssageMapper.deleteGiftDlvyAddrSms();
log.info("InsertMssageGiftDlvyAddrTasklet execute Step5 - FINISH!");
return RepeatStatus.FINISHED;
}
public String seq2code(BigInteger seq) {
// HEX 제외 문자 배열
List<Character> noHex = new ArrayList<>();
for (char ch = 'g'; ch <= 'z'; ch++) {
noHex.add(ch);
}
// DEC -> HEX 변환
String code = seq.toString(16).toUpperCase();
// 랜덤 위치에 HEX 제외 문자 끼워넣기 (n번)
int n = 3;
Random random = new Random();
int len = code.length();
for (int i = 0; i < n; i++) {
int pos = random.nextInt(len + 1); // 랜덤 위치 (0부터 len까지)
char ch = noHex.get(random.nextInt(noHex.size()));
code = code.substring(0, pos) + ch + code.substring(pos);
len++; // 길이가 증가하므로 업데이트
}
return code;
}
public String getProperty(String basePath) {
return env.getProperty(basePath);
}
}

View File

@@ -0,0 +1,49 @@
package com.wb.domainserver.gift.tasklet;
import com.wb.domainserver.mapper.gcone.AtmcrcpmnyMapper;
import com.wb.domainserver.response.WnbtWebClientResponseHandler;
import com.wb.domainserver.util.communicate.RESRC;
import com.wb.domainserver.util.communicate.SendToResrc;
import com.wb.domainserver.util.dataaccess.DataMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
public class SelectGiftOrderCancelTasklet implements Tasklet {
@Autowired
private AtmcrcpmnyMapper mapper;
@Autowired
WnbtWebClientResponseHandler responseHandler;
@Autowired
private SendToResrc sendToResrc;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
log.debug("execute()");
List<DataMap> list = mapper.selectGiftOrderCancel();
if(!list.isEmpty()) {
Map<String, Object> result = responseHandler.handleResponseAsMap(
sendToResrc.ofPost(RESRC.GCONEBO, "/gcone/ordr/ordr/insertBOSetleCanclRefndList", list)
);
log.debug("result = {}", result);
}
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,46 @@
package com.wb.domainserver.log.jobs;
import com.wb.domainserver.log.tasklet.DeleteSopmalAccessLog;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@RequiredArgsConstructor
@Slf4j
public class LogConfig extends DefaultBatchConfiguration{
private final DeleteSopmalAccessLog deleteSopmalAccessLog;
@Bean
public Job logJob(JobRepository jobRepository
, Step deleteSopmalAccessLogStep
) {
return new JobBuilder("logJob", jobRepository)
.incrementer(new RunIdIncrementer())
.start(deleteSopmalAccessLogStep)
.build();
}
@Bean
@JobScope
public Step deleteSopmalAccessLogStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {
return new StepBuilder("deleteSopmalAccessLogStep", jobRepository)
.tasklet(deleteSopmalAccessLog, platformTransactionManager)
.build();
}
}

View File

@@ -0,0 +1,38 @@
package com.wb.domainserver.log.tasklet;
import com.wb.domainserver.log.vo.AccessLogVO;
import com.wb.domainserver.mapper.gcone.LogMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;
@Component
@StepScope
@RequiredArgsConstructor
@Slf4j
public class DeleteSopmalAccessLog implements Tasklet {
private final LogMapper mapper;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//사용자 로그 삭제대상 기준 고유번호 조회
AccessLogVO vo = mapper.selectSopmalAccessLogStdr();
//조회한 고유번호를 기준으로 사용자 로그 백업
mapper.insertSopmalAccessLogBak(vo);
//조회한 고유번호를 기준으로 사용자 로그 삭제
mapper.deleteSopmalAccessLog(vo);
return RepeatStatus.FINISHED;
}
}

View File

@@ -0,0 +1,15 @@
package com.wb.domainserver.log.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AccessLogVO {
private static final long serialVersionUID = 1L;
/*로그 고유번호*/
private String accessLogInnb;
}

View File

@@ -0,0 +1,13 @@
package com.wb.domainserver.mapper.crm;
import com.wb.domainserver.sample.vo.BbsmngrVO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository("SampleCrmMapper")
public interface SampleCrmMapper {
public int insertCrmCheck(BbsmngrVO vo);
}

View File

@@ -0,0 +1,83 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.analysis.vo.TsAnalysisErpGoodsVO;
import com.wb.domainserver.analysis.vo.TsAnalysisErpSetGoodsVO;
import com.wb.domainserver.analysis.vo.TsAnalysisErpTotalStatisticsVO;
import com.wb.domainserver.analysis.vo.TsAnalysisOrderListVO;
import com.wb.domainserver.export.vo.TsPurchsDcsnVO;
import com.wb.domainserver.sweettracker.vo.TsOrderLogVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Mapper
@Repository
@Qualifier("statDataSource")
public interface AnalysisMapper {
/**
* ERP 제상품 현황 INSERT
* @param TsAnalysisErpGoodsVOList
*/
public void insertErpGoods(List<TsAnalysisErpGoodsVO> TsAnalysisErpGoodsVOList);
/**
* ERP 세트상품 INSERT
* @param TsAnalysisErpSetGoodsVOList
*/
public void insertErpSetGoods(List<TsAnalysisErpSetGoodsVO> TsAnalysisErpSetGoodsVOList);
/**
* 자사몰 주문 리스트
*
*/
public List<TsAnalysisOrderListVO> selectShoppingMallOrderList(DataMap params);
/**
* ERP 주문 리스트
*
*/
public List<TsAnalysisOrderListVO> selectErpOrderList();
/**
* 주문리스트 -> barcode 상품정보
*
*/
public List<DataMap> selectbarcodeGoodsInfo(String goodsCode);
/**
* 주문리스트 -> setcode 상품정보
*
*/
public List<DataMap> selectsetCodeGoodsInfo(DataMap param);
/**
* 주문리스트 -> barcode 상품정보
*
*/
public void deleteErpGoods();
/**
* 주문리스트 -> setcode 상품정보
*
*/
public void deleteErpSetGoods();
public void insertOrderList(List<TsAnalysisOrderListVO> TsAnalysisOrderListVO);
public void insertTotalList(List<TsAnalysisErpTotalStatisticsVO> TsAnalysisErpTotalStatisticsVO);
}

View File

@@ -0,0 +1,41 @@
package com.wb.domainserver.mapper.gcone;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import com.wb.domainserver.app.vo.AppPushVO;
import com.wb.domainserver.util.dataaccess.DataMap;
@Mapper
@Repository
public interface AppPushMapper {
/* 푸시 대상 혜택 조회 */
public List<DataMap> selectBOBnftPushTrgetList(AppPushVO vo);
/* 라이브쇼핑 푸시발송건 조회 */
public DataMap selectBOBnftPushLvshopInfo(AppPushVO vo);
/* 섭취챌린지 푸시발송건 & 발송대상 푸시키 조회 */
public List<DataMap> selectBOBnftPushNtakchlMbrList(AppPushVO vo);
/* 푸시 예약 발송건 조회 */
public List<DataMap> selectBOBnftPushResveList(AppPushVO vo);
/* 혜택별 발송대상 푸시키 조회 */
public List<DataMap> selectBOBnftPushMbrList(AppPushVO vo);
/* 섭취챌린지 마지막 푸시발송시간 수정 */
public int updateBOBnftPushNtakchlSendDt(AppPushVO vo);
/* 푸시발송내역 등록 */
public int insertBOBnftPushSndngDtls(AppPushVO vo);
/* 푸시발송내역 수정 */
public int updateBOBnftPushSndngDtls(AppPushVO vo);
/* 푸시발송 에러내역 등록 */
public int insertBOBnftPushSndngErrlog(AppPushVO vo);
}

View File

@@ -0,0 +1,150 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.export.vo.TsMlgVO;
import com.wb.domainserver.export.vo.BOMlgUseDtlVO;
import com.wb.domainserver.export.vo.TsPurchsDcsnVO;
import com.wb.domainserver.sweettracker.vo.TsOrderLogVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import java.math.BigInteger;
import java.util.List;
@Mapper
@Repository
@Qualifier("statDataSource")
public interface AtmcPurchsDcsnMapper {
/**
* 대상 출고 상품 목록 조회
* @param dlivyVO
* @return
*/
public List<DataMap> selectTsExportOrderItemInqire(TsPurchsDcsnVO dlivyVO);
/**
* 주문 상품 옵션 자동 구매 확정
* @param orderItem
*/
public void updateTsPurchsDcsnOrdrItemUpdt(DataMap orderItem);
/**
* 주문 배송 자동 구매 확정
* @param dlvyVO
* @return
*/
public Integer updateTsPurchsDcsnOrdrDlvyUpdt(DataMap dlvyVO);
/**
* 주문 자동 구매 확정
* @param ordrVO
*/
public void updateTsOrdrStatusUpdt6575(DataMap ordrVO);
/**
* 구매 확정 상태 수정
* @param dlivyVO
*/
public void updateTsPurchsDcsnSttusUpdt(TsPurchsDcsnVO dlivyVO);
/**
* 출고 상품 마일리지 적립 관련 수량 수정
* @param orderItem
*/
public void updateTsExportItemQyAllUpdt(DataMap orderItem);
/**
* 출고 상품 마일리지 적립 관련 수량 수정 _ 마일리지 적립 실패했을 경우
* @param orderItem
*/
public void updateTsExportItemQyAllUpdtFail(DataMap orderItem);
/**
* 마일리지 지급하지 않는경우
* @param orderItem
*/
public void updateTsExportItemQyAllUpdtNoMlg(DataMap orderItem);
/**
* 주문 로그 등록
* @param logVO
*/
public void insertOrderLog(TsOrderLogVO logVO);
/**
* 브랜드별 마일리지 설정
* @param sopmalCd
* @return
*/
public DataMap selectBOShopInqire(String sopmalCd);
/**
* 손실 조회
* @param mlgVO
* @return
*/
public List<DataMap> selectBOLoss(TsMlgVO mlgVO);
BigInteger selectBOMlgLossAddCanclMlgInnb(TsMlgVO useMlgVo);
/**
* 마일리지 적립 등록
* USE_POSBLE_END_DT mlgValidDt
* @param vo
* @return
*/
public Integer insertBOMlgAdd(TsMlgVO vo);
/**
* 마일리지 손실 수정
* @param vo
* @return
*/
public Integer updateBOMlgLoss(TsMlgVO vo);
/**
* 마일리지 손실 수정
* @param vo
* @return
*/
public Integer updateBOMlgLossList(List<DataMap> lossList);
/**
* 마일리지 잔액 수정
* @param vo
* @return
*/
public Integer updateBOMlgBlce(TsMlgVO vo);
/**
* 손실 차감 금액 기록
* @param boMlgDnVO
*/
void insertBOMlgDn(TsMlgVO boMlgDnVO);
/**
* 마일리지 상세 등록
* @param boMlgUseDtlVO
*/
void insertBOMlgUseDtlAddCancl(BOMlgUseDtlVO boMlgUseDtlVO);
/**
* 출고목록 > 출고 상세 > 구매확정 > 주문상품옵션 구매확정 수량 및 여부 업데이트
* @param orderItem
*/
public void updateBOPurchsDcsnOrdrItemUpdt(DataMap orderItem);
}

View File

@@ -0,0 +1,59 @@
package com.wb.domainserver.mapper.gcone;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import com.wb.domainserver.atmcrcpmny.vo.TsUpdateClearPersonalInfoShopVO;
import com.wb.domainserver.util.dataaccess.DataMap;
@Mapper
@Repository
public interface AtmcrcpmnyMapper {
/** 현금영수증 신청할 데이터 조회 */
public List<DataMap> selectCshRciptRegist();
/** 미입금 내역 조회 */
public List<DataMap> selectDepositRequest();
/** 자동주문취소 조회 */
public List<DataMap> selectOrderCancel();
/** 선물하기주문취소 조회 */
public List<DataMap> selectGiftOrderCancel();
/** 문자 발송 삭제 대상 조회 */
public List<DataMap> selectGcSms(TsUpdateClearPersonalInfoShopVO vo);
/** 문자 발송 대상 삭제 */
public void deleteGcSmsTo(TsUpdateClearPersonalInfoShopVO vo);
/** 이메일 발송로그 삭제 */
public void deleteGcEmailLog(TsUpdateClearPersonalInfoShopVO vo);
/** 이메일 대상관리 삭제 */
public void deleteGcEmailTo(TsUpdateClearPersonalInfoShopVO vo);
/** 배송 */
public void updateGcOrderShipping(TsUpdateClearPersonalInfoShopVO vo);
/** 반품 */
public void updateGcOrderRefund(TsUpdateClearPersonalInfoShopVO vo);
/** 매출증빙 */
public void updateGcSales(TsUpdateClearPersonalInfoShopVO vo);
/** 주문 */
public void updateGcOrder(TsUpdateClearPersonalInfoShopVO vo);
/** 주문결제 */
public void updateGcOrderSetle(TsUpdateClearPersonalInfoShopVO vo);
/** update할 주문 고유번호 조회 */
public List<TsUpdateClearPersonalInfoShopVO> selectUpdateTrget(TsUpdateClearPersonalInfoShopVO vo);
}

View File

@@ -0,0 +1,113 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.coupon.vo.TsCouponPkSndngVO;
import com.wb.domainserver.coupon.vo.TsCouponVO;
import com.wb.domainserver.coupon.vo.TsDwldCouponVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface CouponMapper {
/** 쿠폰(팩) 발송 등록 */
public Integer insertBOCouponPkSndngRegist(TsCouponPkSndngVO couponPkSndngVO);
/** 쿠폰(팩) 발송 대상쿠폰 등록 */
public void insertBOSndngTrgetCouponRegist(TsCouponPkSndngVO couponPkSndngVO);
/** 쿠폰(팩) 발송 등급대상 등록 */
public void insertBOSndngCouponGroupRegist(TsCouponPkSndngVO couponPkSndngVO);
/**
* 쿠폰발송 상세 조회
* @param dwldCouponVO
*/
public TsCouponPkSndngVO selectBOCouponPkSndngDtlInqire(TsDwldCouponVO tsldCouponVO);
/**
* 발송 대상 쿠폰 조회
* @param dwldCouponVO
* @return
*/
public List<TsCouponVO> selectBOTrgetCouponInqire(TsDwldCouponVO dwldCouponVO);
/** 쿠폰 적용 상품 */
public List<DataMap> selectBOCouponIssueGoods(TsCouponVO couponVO);
/**
* 쿠폰 상세 적용상품 정보 조회
* @param couponVO
* @return
*/
public List<DataMap> selectBOCouponIssueGoodsInfoInqire(TsCouponVO couponVO);
/**
* 다운로드 쿠폰 발급 정보 등록(쿠폰 발급, 다운로드)
* @param dwldCouponVO
*/
public int insertBOCouponPkIssuRegist(TsDwldCouponVO dwldCouponVO);
/**
* 다운로드 쿠폰 발급 적용 상품 등록 ( 쿠폰 발급, 다운로드)
* @param dwldCouponVO
*/
public void insertBOCouponPkIssuGoodsRegist(TsDwldCouponVO dwldCouponVO);
/**
* 인증번호 생성
* @param couponVO
*/
public void insertBOMkCouponOflneCouponCrtnb(TsCouponVO couponVO);
public String selectBOSopmalCouponNbInqire(TsCouponVO couponVO);
List<TsCouponPkSndngVO> selectTsCouponPkSndngDtlInqire(DataMap paramMap);
List<TsCouponVO> selectTsCouponTrgetListInqire(List<TsDwldCouponVO> dwldCouponVOList);
/**
* 생일자 추출(전 쇼핑몰: 생일 쿠폰 운영중인) 쿠폰발급
*/
void insertCouponBirthdayDwld(DataMap paramMap);
/**
* 오프라인 쿠폰발급
*/
void insertOffCouponBirthdayDwld(DataMap paramMap);
/**
* 생일자 추출(전 쇼핑몰: 생일 인증쿠폰 운영중인) 인증쿠폰발급
*/
void insertCertCouponBirthdayDwld(DataMap paramMap);
/**
* 쿠폰혜택적용상품 스냅샷
*/
void insertCouponBirthdayDwldIssueGoods(DataMap paramMap);
/**
* 생일쿠폰 상태값 업데이트
*/
void updateOffCouponBirthdayDwldSttus(DataMap paramMap);
void updateCouponBirthdayDwldSttus(DataMap paramMap);
/**
* 등급변경자 추출 쿠폰발급
*/
void insertCouponMbrGradDwld(DataMap paramMap);
/**
* 등급변경 - 쿠폰혜택적용상품 스냅샷
*/
void insertCouponMbrGradDwldIssueGoods();
}

View File

@@ -0,0 +1,82 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.ntcn.vo.TsEmailLogVO;
import com.wb.domainserver.ntcn.vo.TsEmailVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface EmailMapper {
List<Integer> selectBOEmailSndngTrgetSnb(List<DataMap> emailSndngList);
/**
* 회원 2년 동의 메일
*/
void insertMbrMarktAgreEmail(DataMap paramMap);
/**
* 회원 2년 대상자 입력
* @param smsToList
*/
void insertMbrMarktAgreEmailTo(DataMap smsToList);
List<DataMap> selectMarktAgreTrgtList(DataMap paramMap);
void updateMbrMarktAgreEmailSttus();
void deleteMbrMarktAgreEmail();
List<TsEmailVO> selectEmailVoList(DataMap paramMap);
void updateBOEmailSndng(List<TsEmailVO> voListNew);
void updateMbrMarktAgreEmailToSttus(DataMap paramMap);
void updateEmailSttus(DataMap paramMap);
/**
* 장바구니 이메일
*/
void insertCartEmail();
/**
* 이메일 대상자 입력
* @param emailToList
*/
void insertEmailTo(List<TsEmailVO> emailToList);
void insertEmailLog(List<TsEmailLogVO> emailLogList);
void deleteEmailNonTrgt(DataMap paramMap);
void insertCouponEndEmail();
void updateEmailToSttus(DataMap paramMap);
void insertCartSaleEmail();
void insertMlgExpEmail();
List<DataMap> selectMlgTrgtListEmailInqire(DataMap paramMap);
List<DataMap> selectEmailLogOkList(DataMap paramMap);
void updateMarktAgreTrnsmisDt(DataMap emailOkList);
void updateEmailSendSttus(TsEmailVO updtEmailVO);
void insertEmailSendLog(TsEmailLogVO tsEmailLogVO);
/* ##############################################################################################
발송내역 가져오기 START
################################################################################################# */
}

View File

@@ -0,0 +1,46 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.ep.vo.GoogleEp;
import com.wb.domainserver.ep.vo.MetaEp;
import com.wb.domainserver.ep.vo.MobionEp;
import com.wb.domainserver.ep.vo.NaverEp;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface EpMapper {
/**
* 네이버 EP 조회
* @return
*/
public List<NaverEp> selectNaverEp();
/**
* 구글 EP 조회
* @return
*/
public List<GoogleEp> selectGoogleEp();
/**
* 메타 EP 조회
* @return
*/
public List<MetaEp> selectMetaEp();
/**
* 모비온 EP 조회
* @return
*/
public List<MobionEp> selectMobionEp();
}

View File

@@ -0,0 +1,19 @@
package com.wb.domainserver.mapper.gcone;
import com.wb.domainserver.crm.vo.TsExtOrdrVO;
import com.wb.domainserver.crm.vo.TsMemberAppnVO;
import com.wb.domainserver.util.dataaccess.DataMap;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.math.BigInteger;
@Mapper
@Repository
public interface ExtOrdrMapper {
/*외부주문 max값 조회*/
public DataMap selectExtOrdrMaxInnb();
/*외부주문 주문정보 가져오기*/
public int insertExtOrdr(TsExtOrdrVO vo);
}

Some files were not shown because too many files have changed in this diff Show More