feat: 카카오톡 반영
parent
ca60c92bf2
commit
38fa24fb04
@ -0,0 +1,75 @@
|
||||
create table ENS_SND_DTL_KKO_TALK
|
||||
(
|
||||
SEND_DETAIL_ID NUMBER(19) not null
|
||||
primary key,
|
||||
TITLE VARCHAR2(40),
|
||||
LINK VARCHAR2(500),
|
||||
HASH VARCHAR2(99),
|
||||
GUIDE VARCHAR2(2000),
|
||||
PAYLOAD VARCHAR2(500),
|
||||
READ_EXPIRES_AT VARCHAR2(20),
|
||||
REVIEW_EXPIRES_AT VARCHAR2(20),
|
||||
USE_NON_PERSONALIZED_NOTI VARCHAR2(10),
|
||||
CI VARCHAR2(88),
|
||||
PHONE_NUMBER VARCHAR2(30),
|
||||
NAME VARCHAR2(50),
|
||||
BIRTHDAY VARCHAR2(8),
|
||||
EXTERNAL_ID VARCHAR2(40),
|
||||
ENVELOPE_ID VARCHAR2(34),
|
||||
ERROR_CODE VARCHAR2(40),
|
||||
ERROR_MESSAGE CLOB,
|
||||
LAST_UPDT_DT TIMESTAMP(6),
|
||||
REGIST_DT TIMESTAMP(6),
|
||||
BILL_UID VARCHAR2(45 char)
|
||||
constraint FK_BILL_UID
|
||||
references ENS_BILL (BILL_UID),
|
||||
SEND_MAST_ID NUMBER(19)
|
||||
constraint FK_SEND_MAST_ID
|
||||
references ENS_SND_MAST(SEND_MAST_ID)
|
||||
);
|
||||
comment on table ENS_SND_DTL_KKO_TALK is '카카오톡 상세';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.SEND_DETAIL_ID is '발송 상세 ID';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.SEND_MAST_ID is '발송 마스터 ID';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.TITLE is '제목';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.LINK is '웹링크';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.HASH is '해시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.GUIDE is '메시지';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.PAYLOAD is 'PAYLOAD';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.READ_EXPIRES_AT is '최초 열람 만료 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.REVIEW_EXPIRES_AT is '재열람 만료 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.USE_NON_PERSONALIZED_NOTI is '알림톡 개인정보 제거 여부';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.CI is 'CI';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.PHONE_NUMBER is '수신인 전화번호';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.NAME is '수신인 이름';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.BIRTHDAY is '수신인 생년월일';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.EXTERNAL_ID is '문서 매핑 식별 ID';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.ENVELOPE_ID is '문서 고유 ID';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.STATUS is '문서 상태';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.SENT_AT is '문서 송신 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.RECEIVED_AT is '문서 수신 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.READ_AT is '문서 열람 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.AUTHENTICATED_AT is '문서 열람 인증 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.OTT_VERIFIED_AT is '토큰 검증 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.IS_NOTIFICATION_UNAVAILABLE is '알림톡 수신 가능 여부';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.USER_NOTIFIED_AT is '알림톡 수신 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.DISTRIBUTION_RECEIVED_AT is '유통정보 수신 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.ERROR_CODE is '에러 코드';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.ERROR_MESSAGE is '에러 메시지';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.REGIST_DT is '등록 일시';
|
||||
comment on column ENS_SND_DTL_KKO_TALK.LAST_UPDT_DT is '수정 일시';
|
||||
|
||||
/* FIXME: 카카오톡에 맞게 변경 필요 */
|
||||
create table ENS_TMPLT_MNG_KKO_TALK
|
||||
(
|
||||
CI_TRANS_USE_YN VARCHAR2(1 char) not null,
|
||||
CS_NAME VARCHAR2(10 char) not null,
|
||||
CS_NUMBER VARCHAR2(20 char) not null,
|
||||
PRY_MESSAGE VARCHAR2(2000 char),
|
||||
TMPLT_CS_INFO_USE_YN VARCHAR2(1 char) not null,
|
||||
TMPLT_MSG_USE_YN VARCHAR2(1 char) not null,
|
||||
ORG_CD VARCHAR2(255 char) not null,
|
||||
TMPLT_CD VARCHAR2(30 char) not null,
|
||||
primary key (ORG_CD, TMPLT_CD),
|
||||
constraint FK_TMPLT_MNG_KKO_TALK
|
||||
foreign key (ORG_CD, TMPLT_CD) references ENS_TMPLT_MNG
|
||||
);
|
@ -0,0 +1,120 @@
|
||||
package cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.kkotalk;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.monitor.slack.event.MonitorEvent;
|
||||
import cokr.xit.ens.modules.common.code.PostSeCd;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendDetail;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository.IntgrnSendDetailRepository;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.AcceptDataEventListener;
|
||||
import cokr.xit.ens.modules.common.monitor.MessageByPhase;
|
||||
import cokr.xit.ens.modules.kkomydoc.service.event.KkoMydocSendRealtimeEvent;
|
||||
import cokr.xit.ens.modules.kkomydoc.service.event.KkoMydocSendReserveEvent;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.service.KkoTalkService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AcceptByKkoTalkEventListener implements AcceptDataEventListener<AcceptDataByKkoTalk, KkotalkDTO.SendDetailKkoTalkDTO> {
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
private final KkoTalkService kkoTalkService;
|
||||
private final IntgrnSendDetailRepository intgrnSendDetailRepository;
|
||||
|
||||
|
||||
@Override
|
||||
public void accept(AcceptDataByKkoTalk ev) {
|
||||
final PostSeCd POST_SE_CD = PostSeCd.kkoMydoc;
|
||||
EnsResponseVO responseVO = null;
|
||||
try {
|
||||
|
||||
responseVO = kkoTalkService.accept(ev.createReqDto());
|
||||
|
||||
|
||||
Map<String, Object> resultInfo = (Map<String, Object>) responseVO.getResultInfo();
|
||||
Long sendMastId = (Long) resultInfo.get("sendMastId");
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> sendDetails = (List<KkotalkDTO.SendDetailKkoTalkDTO>) resultInfo.get("sendDetails");
|
||||
if (EnsErrCd.OK.equals(responseVO.getErrCode())) {
|
||||
Map<String, Long> sendDetailIdMap = convertSendDetailIdMap(sendDetails);
|
||||
this.acceptSuccess(ev.getIntgrnSendDetails(), POST_SE_CD, sendDetailIdMap);
|
||||
intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
|
||||
} else {
|
||||
this.acceptFail(ev.getIntgrnSendDetails(), POST_SE_CD, responseVO.getErrCode(), String.format("%s %s", responseVO.getErrMsg(), responseVO.getResultInfo().toString()));
|
||||
intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ev.IsReserveSend()) {
|
||||
KkoMydocSendReserveEvent event = KkoMydocSendReserveEvent.builder()
|
||||
.sendMastIds(Arrays.asList(sendMastId))
|
||||
.build();
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
|
||||
} else {
|
||||
KkoMydocSendRealtimeEvent event = KkoMydocSendRealtimeEvent.builder()
|
||||
.sendMastIds(Arrays.asList(sendMastId))
|
||||
// .callback(() -> this.fetch(sendMastId, ev.getSendDetails()))
|
||||
.build();
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.acceptFail(ev.getIntgrnSendDetails(), POST_SE_CD, EnsErrCd.ACPT999, e.getMessage());
|
||||
intgrnSendDetailRepository.saveAll(ev.getIntgrnSendDetails());
|
||||
responseVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.ERR999).errMsg(e.getMessage()).build();
|
||||
} finally {
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode())) {
|
||||
String message = createFailMessage(ev.getIntgrnSendDetails().get(0).getIntgrnSendMast().getIntSendMastId(), POST_SE_CD, responseVO);
|
||||
applicationEventPublisher.publishEvent(MonitorEvent.builder()
|
||||
.message(MessageByPhase.builder()
|
||||
.oClass(getClass().getSimpleName() + "." + new Throwable().getStackTrace()[0].getMethodName())
|
||||
.postSeCd(PostSeCd.intgrnNoti)
|
||||
.statCd(StatCd.sendfail)
|
||||
.errCd(responseVO.getErrCode())
|
||||
.message(message)
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Long> convertSendDetailIdMap(List<KkotalkDTO.SendDetailKkoTalkDTO> sendDetails) {
|
||||
|
||||
Map<String, Long> sendDetailIdMap = sendDetails.stream()
|
||||
.map(row -> {
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("key", row.getExternalId());
|
||||
m.put("value", row.getSendDetailId());
|
||||
return m;
|
||||
})
|
||||
// .map(row -> {
|
||||
// Map<String, Object> m = new HashMap<>();
|
||||
// m.put("key", row.getPropExternalDocumentUuid());
|
||||
// m.put("value", row.getSendDetailId());
|
||||
// return m;
|
||||
// })
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (Long) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
return sendDetailIdMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSendDetailId(IntgrnSendDetail intgrnSendDetail, Long sendDetailId) {
|
||||
intgrnSendDetail.setSendDetailIdKkoTalk(sendDetailId);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.kkotalk;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cokr.xit.ens.core.model.EnsBillAcptReqDTO;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.core.utils.crypto.AES256;
|
||||
import cokr.xit.ens.core.utils.crypto.Crypto;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendDetail;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.IntgrnSendMast;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.service.support.AcceptData;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.config.XitProperty;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkApiDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.config.Document;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
public class AcceptDataByKkoTalk extends AcceptData<KkotalkDTO.KkoTalkAcceptReqDTO> {
|
||||
|
||||
private AES256 aes256 = new AES256(Crypto.AES256.getKey());
|
||||
|
||||
public AcceptDataByKkoTalk(IntgrnSendMast intgrnSendMast, List<IntgrnSendDetail> intgrnSendDetails, Boolean isReserveSend) {
|
||||
super(intgrnSendMast, intgrnSendDetails, isReserveSend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KkotalkDTO.KkoTalkAcceptReqDTO createReqDto() {
|
||||
return KkotalkDTO.KkoTalkAcceptReqDTO.builder()
|
||||
.vender(intgrnSendMast.getVender().getCode())
|
||||
.org_cd(intgrnSendMast.getOrgCd())
|
||||
.tmplt_cd(intgrnSendMast.getTmpltCd())
|
||||
.post_bundle_title(intgrnSendMast.getPostBundleTitle())
|
||||
.send_dt(intgrnSendMast.getSendDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
|
||||
.close_dt(intgrnSendMast.getCloseDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
|
||||
.documents(intgrnSendDetails.stream().map(this::createDocument).collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
|
||||
protected Document createDocument(IntgrnSendDetail intgrnSendDetail) {
|
||||
|
||||
KkotalkApiDTO.Envelope envelope = gson.fromJson(intgrnSendDetail.getJAcptDocKkoTalk(), KkotalkApiDTO.Envelope.class);
|
||||
|
||||
return Document.builder()
|
||||
.title(envelope.getTitle())
|
||||
.content(envelope.getContent())
|
||||
.hash(envelope.getHash())
|
||||
.guide(envelope.getGuide())
|
||||
.payload(envelope.getPayload())
|
||||
.readExpiresAt(envelope.getReadExpiresAt())
|
||||
.reviewExpiresAt(envelope.getReviewExpiresAt())
|
||||
.useNonPersonalizedNotification(envelope.getUseNonPersonalizedNotification())
|
||||
.ci(envelope.getCi())
|
||||
.phoneNumber(envelope.getPhoneNumber())
|
||||
.name(envelope.getName())
|
||||
.birthday(envelope.getBirthday())
|
||||
.externalId(intgrnSendDetail.getLinkedUuid())
|
||||
.xit_property(this.createXitProperty(intgrnSendDetail))
|
||||
.build();
|
||||
}
|
||||
|
||||
protected XitProperty createXitProperty(IntgrnSendDetail intgrnSendDetail) {
|
||||
return XitProperty.builder()
|
||||
.mbl_page_data(CmmnUtil.isEmpty(intgrnSendDetail.getJMblPageData()) ? null : gson.fromJson(intgrnSendDetail.getJMblPageData(), Map.class))
|
||||
// .bill_link_info(this.createBillLinkInfo(intgrnSendDetail))
|
||||
.bill_acpt_data(this.createBillAcptData(intgrnSendDetail))
|
||||
// .jid(intgrnSendDetail.getJids())
|
||||
.jid(aes256.decrypt(intgrnSendDetail.getJid()))
|
||||
.tmplt_msg_data(this.createTmpltMsgData(intgrnSendDetail))
|
||||
.build();
|
||||
}
|
||||
|
||||
protected EnsBillAcptReqDTO createBillAcptData(IntgrnSendDetail intgrnSendDetail) {
|
||||
if (CmmnUtil.isEmpty(intgrnSendDetail.getBill()))
|
||||
return null;
|
||||
return EnsBillAcptReqDTO.builder()
|
||||
.billUid(intgrnSendDetail.getBill().getBillUid())
|
||||
.billerUserKey(intgrnSendDetail.getBill().getBillerUserKey())
|
||||
.billSe(intgrnSendDetail.getBill().getBillSeCd())
|
||||
.build();
|
||||
}
|
||||
|
||||
protected Map<String, String> createTmpltMsgData(IntgrnSendDetail intgrnSendDetail) {
|
||||
if (CmmnUtil.isEmpty(intgrnSendDetail.getJTmpltMsgData()))
|
||||
return null;
|
||||
else
|
||||
return gson.fromJson(intgrnSendDetail.getJTmpltMsgData(), Map.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cokr.xit.ens.modules.common.ctgy.sys.mng.mapper;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
* packageName : cokr.xit.ens.modules.common.ctgy.sys.mng.mapper
|
||||
* fileName : IOrgMngMapper
|
||||
* author : limju
|
||||
* date : 2024 9월 03
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2024 9월 03 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface IOrgMngMapper {
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package cokr.xit.ens.modules.kkotalk.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.TableGenerator;
|
||||
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.Bill;
|
||||
import cokr.xit.ens.modules.common.domain.BaseEntity;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.support.FieldError;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Entity
|
||||
@Getter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "ens_snd_dtl_kko_talk", schema = "", catalog = "", indexes = {
|
||||
@Index(name = "idx_snd_dtl_kko_talk_uk_id", columnList = "envelope_id"),
|
||||
@Index(name = "idx_snd_dtl_kko_talk_uk", columnList = "envelope_id, external_id"),
|
||||
// @Index(name = "idx_kkomd_bill_uid", columnList = "mk_bill_uid"),
|
||||
})
|
||||
public class SendDetailKkoTalk extends BaseEntity {
|
||||
|
||||
@Id
|
||||
// @GeneratedValue(strategy=GenerationType.AUTO)
|
||||
@GeneratedValue(strategy = GenerationType.TABLE, generator = "SendDetailKkoTalk_Generator")
|
||||
@TableGenerator(table = "ens_seq_generator", name = "SendDetailKkoTalk_Generator"
|
||||
, pkColumnName = "seq_name", pkColumnValue = "SendDetailKkoTalk_id"
|
||||
, initialValue = 0, allocationSize = 200)
|
||||
private Long sendDetailId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "send_mast_id")
|
||||
private SendMast sendMast;
|
||||
|
||||
@Column(name = "title", nullable = true, length = 40)
|
||||
@Setter
|
||||
private String title;
|
||||
|
||||
@Column(name = "link", nullable = true, length = 99)
|
||||
@Setter
|
||||
private String link;
|
||||
|
||||
@Column(name = "hash", nullable = true, length = 99)
|
||||
@Setter
|
||||
private String hash;
|
||||
|
||||
@Column(name = "read_expires_at", nullable = true)
|
||||
private String readExpiresAt;
|
||||
|
||||
|
||||
@Column(name = "review_expires_at", nullable = true)
|
||||
private String reviewExpiresAt;
|
||||
|
||||
@Column(name = "guide", nullable = true)
|
||||
private String guide;
|
||||
|
||||
/**
|
||||
* payload
|
||||
*/
|
||||
@Column(name = "payload", nullable = true)
|
||||
private String payload;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 알림톡 내용에 개인정보 제거 여부
|
||||
* default: false
|
||||
* </pre>
|
||||
*/
|
||||
@Column(name = "is_notification_unavailable", nullable = true)
|
||||
private Boolean useNonPersonalizedNotification = false;
|
||||
|
||||
/**
|
||||
* 수신자 CI
|
||||
*/
|
||||
@Column(name = "ci", nullable = true)
|
||||
private String ci;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 수신자 전화번호
|
||||
* ci 미전송시 필수
|
||||
* </pre>
|
||||
*/
|
||||
@Column(name = "phone_number", nullable = true)
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 수신자 이름
|
||||
* ci 미전송시 필수
|
||||
* </pre>
|
||||
*/
|
||||
@Column(name = "name", nullable = true)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 수신자 생년월일 (YYYY-MM-DD 형식)
|
||||
* ci 미전송시 필수
|
||||
* </pre>
|
||||
*/
|
||||
@Column(name = "birthday", nullable = true)
|
||||
private String birthday;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 문서매핑용 식별자 - 최대 40자
|
||||
* </pre>
|
||||
*/
|
||||
@Column(name = "external_id", nullable = true)
|
||||
private String externalId;
|
||||
|
||||
@Column(name = "envelope_id", nullable = true)
|
||||
private String envelopeId;
|
||||
|
||||
|
||||
@Embedded
|
||||
@Setter
|
||||
private FieldError error;
|
||||
|
||||
|
||||
@Column(name = "mk_bill_use_yn", nullable = true, length = 1)
|
||||
private String mkBillUseYn;
|
||||
|
||||
// @Column(name = "mk_bill_uid", nullable = true, length = 45)
|
||||
// private String mkBillUid;
|
||||
|
||||
@JoinColumn(name = "bill_uid", referencedColumnName = "bill_uid")
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
private Bill bill;
|
||||
|
||||
@Column(name = "mk_jid", nullable = true, length = 24)
|
||||
private String mkJid;
|
||||
|
||||
@Column(name = "mk_tmplt_msg_json_data", nullable = true, length = 4000)
|
||||
private String mkTmpltMsgJsonData;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package cokr.xit.ens.modules.kkotalk.domain;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.TmpltMng;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Entity
|
||||
@Getter
|
||||
@ToString
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Table(name = "ens_tmplt_mng_kko_talk", schema = "", catalog = "")
|
||||
@DiscriminatorValue("kkotalk")
|
||||
public class TmpltMngKkoTalk extends TmpltMng {
|
||||
|
||||
|
||||
@Column(name = "pryMessage", nullable = true, length = 2000)
|
||||
@Setter
|
||||
private String pryMessage;
|
||||
|
||||
|
||||
@Column(name = "cs_number", nullable = false, length = 20)
|
||||
@Setter
|
||||
private String csNumber;
|
||||
|
||||
|
||||
@Column(name = "cs_name", nullable = false, length = 10)
|
||||
@Setter
|
||||
private String csName;
|
||||
|
||||
|
||||
@Column(name = "ci_trans_use_yn", nullable = false, length = 1)
|
||||
private String ciTransUseYn;
|
||||
|
||||
|
||||
@Column(name = "tmplt_msg_use_yn", nullable = false, length = 1)
|
||||
private String tmpltMsgUseYn;
|
||||
|
||||
|
||||
@Column(name = "tmplt_cs_info_use_yn", nullable = false, length = 1)
|
||||
private String tmpltCsInfoUseYn;
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null)
|
||||
return false;
|
||||
Class<?> oEffectiveClass = o instanceof HibernateProxy ?
|
||||
((HibernateProxy)o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||
Class<?> thisEffectiveClass = this instanceof HibernateProxy ?
|
||||
((HibernateProxy)this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||
if (thisEffectiveClass != oEffectiveClass)
|
||||
return false;
|
||||
TmpltMngKkoTalk that = (TmpltMngKkoTalk)o;
|
||||
return getOrgMng() != null && Objects.equals(getOrgMng(), that.getOrgMng());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this instanceof HibernateProxy ?
|
||||
((HibernateProxy)this).getHibernateLazyInitializer().getPersistentClass().hashCode() :
|
||||
getClass().hashCode();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
//
|
||||
// import java.util.List;
|
||||
// import java.util.Optional;
|
||||
//
|
||||
// import org.springframework.data.jpa.repository.JpaRepository;
|
||||
//
|
||||
// import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
// import cokr.xit.ens.modules.kkotalk.domain.SendDetailKkoTalk;
|
||||
//
|
||||
// public interface SendDetailKkoTalkRepository
|
||||
// extends JpaRepository<SendDetailKkoTalk, Long>, SendDetailKkoTalkRepositoryCustom {
|
||||
//
|
||||
// List<SendDetailKkoTalk> findAllBySendMast(SendMast sendMast);
|
||||
//
|
||||
// List<SendDetailKkoTalk> findAllBySendMastAndDocumentBinderUuidIsNotNull(SendMast sendMast);
|
||||
//
|
||||
// Optional<SendDetailKkoTalk> findByPropExternalDocumentUuidAndDocumentBinderUuid(String propExternalDocumentUuid, String documentBinderUuid);
|
||||
//
|
||||
// Optional<SendDetailKkoTalk> findByPropExternalDocumentUuid(String propExternalDocumentUuid);
|
||||
//
|
||||
// }
|
@ -0,0 +1,13 @@
|
||||
// package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
//
|
||||
// import java.util.List;
|
||||
// import java.util.Optional;
|
||||
//
|
||||
// import cokr.xit.ens.modules.common.biztmplt.SendDetailRepositorySupport;
|
||||
// import cokr.xit.ens.modules.kkotalk.domain.SendDetailKkoTalk;
|
||||
//
|
||||
// public interface SendDetailKkoTalkRepositoryCustom extends SendDetailRepositorySupport<SendDetailKkoTalk> {
|
||||
//
|
||||
// List<SendDetailKkoTalk> findAllFetchBySendMastId(Long sendMastId);
|
||||
// Optional<SendDetailKkoTalk> findFetchByPropExternalDocumentUuidAndDocumentBinderUuid(String propExternalDocumentUuid, String documentBinderUuid);
|
||||
// }
|
@ -0,0 +1,57 @@
|
||||
// package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
//
|
||||
// import static cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.QBill.*;
|
||||
// import static cokr.xit.ens.modules.common.domain.QSendMast.*;
|
||||
// import static cokr.xit.ens.modules.kkomydoc.domain.QSendDetailKkoMydoc.*;
|
||||
//
|
||||
// import java.util.List;
|
||||
// import java.util.Optional;
|
||||
//
|
||||
// import com.querydsl.core.BooleanBuilder;
|
||||
// import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
//
|
||||
// import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
// import cokr.xit.ens.modules.kkotalk.domain.SendDetailKkoTalk;
|
||||
// import lombok.RequiredArgsConstructor;
|
||||
//
|
||||
// @RequiredArgsConstructor
|
||||
// public class SendDetailKkoTalkRepositoryImpl implements SendDetailKkoTalkRepositoryCustom {
|
||||
// private final JPAQueryFactory query;
|
||||
//
|
||||
// // @Override
|
||||
// // public List<SendDetailKkoMydoc> findAllFetchBySendMastIdAndMkBillUseYAndUrlIsNull(Long sendMastId, boolean urlIsNull) {
|
||||
// // return query.selectFrom(sendDetailKkoMydoc)
|
||||
// // .innerJoin(sendDetailKkoMydoc.sendMast, sendMast)
|
||||
// // .fetchJoin()
|
||||
// // .leftJoin(sendDetailKkoMydoc.kkoBillMast, kkoBillMast)
|
||||
// // .fetchJoin()
|
||||
// // .where(sendDetailKkoMydoc.sendMast.sendMastId.eq(sendMastId)
|
||||
// // .and(sendDetailKkoMydoc.mkBillUseYn.eq("Y"))
|
||||
// // .and(urlIsNull ? sendDetailKkoMydoc.kkoBillMast.url.isNull() : sendDetailKkoMydoc.kkoBillMast.url.isNotNull())
|
||||
// // )
|
||||
// // .fetch();
|
||||
// // }
|
||||
//
|
||||
// @Override
|
||||
// public List<SendDetailKkoTalk> findAllFetchBySendMastId(Long sendMastId) {
|
||||
// return query.selectFrom(sendDetailKkoTalk)
|
||||
// .innerJoin(sendDetailKkoTalk.sendMast, sendMast).fetchJoin()
|
||||
// // .leftJoin(sendDetailKkoMydoc.kkoBillMast, kkoBillMast)
|
||||
// .leftJoin(sendDetailKkTalk.bill, bill).fetchJoin()
|
||||
// .where(sendDetailKkoTalk.sendMast.sendMastId.eq(sendMastId))
|
||||
// .fetch();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Optional<SendDetailKkoTalk> findFetchByPropExternalDocumentUuidAndDocumentBinderUuid(String propExternalDocumentUuid, String documentBinderUuid) {
|
||||
// BooleanBuilder builder = new BooleanBuilder();
|
||||
// builder.and(sendDetailKkoMydoc.documentBinderUuid.eq(documentBinderUuid));
|
||||
// if (!CmmnUtil.isEmpty(propExternalDocumentUuid))
|
||||
// builder.and(sendDetailKkoTalk.propExternalDocumentUuid.eq(propExternalDocumentUuid));
|
||||
//
|
||||
// return Optional.ofNullable(query.selectFrom(sendDetailKkoTalk)
|
||||
// .innerJoin(sendDetailKkoTalk.sendMast, sendMast).fetchJoin()
|
||||
// .where(builder)
|
||||
// .fetchOne());
|
||||
// }
|
||||
// }
|
@ -0,0 +1,10 @@
|
||||
package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import cokr.xit.ens.modules.kkotalk.domain.TmpltMngKkoTalk;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
public interface TmpltMngKkoTalkRepository extends JpaRepository<TmpltMngKkoTalk, Long>,
|
||||
TmpltMngKkoTalkRepositoryCustom {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.TmpltMngRepositorySupport;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngSearchDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.domain.TmpltMngKkoTalk;
|
||||
import cokr.xit.ens.modules.kkotalk.model.TmpltMngKkoTalkDTO;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
public interface TmpltMngKkoTalkRepositoryCustom extends TmpltMngRepositorySupport<TmpltMngKkoTalk, TmpltMngSearchDTO, TmpltMngKkoTalkDTO> {
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package cokr.xit.ens.modules.kkotalk.domain.repository;
|
||||
|
||||
import static cokr.xit.ens.modules.common.ctgy.sys.mng.domain.QOrgMng.*;
|
||||
import static cokr.xit.ens.modules.kkotalk.domain.QTmpltMngKkoTalk.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.QBean;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngSearchDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.domain.TmpltMngKkoTalk;
|
||||
import cokr.xit.ens.modules.kkotalk.model.TmpltMngKkoTalkDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@RequiredArgsConstructor
|
||||
public class TmpltMngKkoTalkRepositoryImpl implements TmpltMngKkoTalkRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory query;
|
||||
|
||||
@Override
|
||||
public Optional<TmpltMngKkoTalk> findFetchByOrgCdAndTmpltCd(String orgCd, String tmpltCd) {
|
||||
return Optional.ofNullable(query.selectFrom(tmpltMngKkoTalk)
|
||||
.where(tmpltMngKkoTalk.orgMng.orgCd.eq(orgCd)
|
||||
.and(tmpltMngKkoTalk.tmpltCd.eq(tmpltCd)))
|
||||
.fetchOne());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TmpltMngKkoTalk> findAllFetchBySearchDTO(TmpltMngSearchDTO searchDTO) {
|
||||
return query.selectFrom(tmpltMngKkoTalk)
|
||||
.innerJoin(tmpltMngKkoTalk.orgMng, orgMng)
|
||||
.fetchJoin()
|
||||
.where(eqSearchDTO(searchDTO))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TmpltMngKkoTalkDTO> findDtoByOrgCdAndTmpltCd(String orgCd, String tmpltCd) {
|
||||
return Optional.ofNullable(query.select(mappedDto())
|
||||
.from(tmpltMngKkoTalk)
|
||||
.where(tmpltMngKkoTalk.orgMng.orgCd.eq(orgCd)
|
||||
.and(tmpltMngKkoTalk.tmpltCd.eq(tmpltCd)))
|
||||
.fetchOne());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<TmpltMngKkoTalkDTO> findAllDtoBySearchDTO(TmpltMngSearchDTO searchDTO) {
|
||||
return query.select(mappedDto())
|
||||
.from(tmpltMngKkoTalk)
|
||||
.innerJoin(tmpltMngKkoTalk.orgMng, orgMng)
|
||||
.where(eqSearchDTO(searchDTO))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
private QBean<TmpltMngKkoTalkDTO> mappedDto() {
|
||||
return Projections.fields(TmpltMngKkoTalkDTO.class
|
||||
, tmpltMngKkoTalk.dtype
|
||||
, tmpltMngKkoTalk.orgMng.orgCd
|
||||
, tmpltMngKkoTalk.orgMng.orgNm
|
||||
, tmpltMngKkoTalk.tmpltCd
|
||||
, tmpltMngKkoTalk.title
|
||||
, tmpltMngKkoTalk.message
|
||||
, tmpltMngKkoTalk.useYn
|
||||
, tmpltMngKkoTalk.csNumber
|
||||
, tmpltMngKkoTalk.csName
|
||||
, tmpltMngKkoTalk.ciTransUseYn
|
||||
, tmpltMngKkoTalk.tmpltMsgUseYn
|
||||
, tmpltMngKkoTalk.tmpltCsInfoUseYn
|
||||
, tmpltMngKkoTalk.pryMessage
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TmpltMngKkoTalk> findFetchByOrgCdAndTmpltCdAndUseYn(String orgCd, String tmpltCd, String useYn) {
|
||||
return Optional.ofNullable(
|
||||
query.selectFrom(tmpltMngKkoTalk)
|
||||
.innerJoin(tmpltMngKkoTalk.orgMng, orgMng)
|
||||
.fetchJoin()
|
||||
.where(
|
||||
tmpltMngKkoTalk.orgMng.orgCd.eq(orgCd)
|
||||
.and(tmpltMngKkoTalk.tmpltCd.eq(tmpltCd))
|
||||
.and(tmpltMngKkoTalk.useYn.eq(useYn))
|
||||
)
|
||||
.fetchOne());
|
||||
}
|
||||
|
||||
private BooleanBuilder eqSearchDTO(TmpltMngSearchDTO searchDTO) {
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
if (!CmmnUtil.isEmpty(searchDTO.getSchOrgCd()))
|
||||
builder.and(tmpltMngKkoTalk.orgMng.orgCd.eq(searchDTO.getSchOrgCd()));
|
||||
|
||||
if (!CmmnUtil.isEmpty(searchDTO.getSchTmpltCd()))
|
||||
builder.and(tmpltMngKkoTalk.tmpltCd.eq(searchDTO.getSchTmpltCd()));
|
||||
|
||||
if (!CmmnUtil.isEmpty(searchDTO.getSchTitle()))
|
||||
builder.and(tmpltMngKkoTalk.title.like(searchDTO.getSchTitle() + "%"));
|
||||
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cokr.xit.ens.modules.kkotalk.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description :
|
||||
* packageName : cokr.xit.ens.modules.kkotalk.mapper
|
||||
* fileName : IKkoTalkMapper
|
||||
* author : limju
|
||||
* date : 2024 9월 03
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2024 9월 03 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Mapper
|
||||
public interface IKkoTalkMapper {
|
||||
void saveSndDtlKkoTalk(KkotalkDTO.SendDetailKkoTalkDTO sendDetailKkoTalk);
|
||||
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> findAllBySendMastId(Long sendMastId);
|
||||
|
||||
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> findAllFetchBySendMastId(Long sendMastId);
|
||||
Optional<KkotalkDTO.SendDetailKkoTalkDTO> findFetchByExternalIdAndEnvelopeId(String externalId, String envelopeId);
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package cokr.xit.ens.modules.kkotalk.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngByTypeDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Schema(name = "TmpltMngKkoTalkDTO")
|
||||
public class TmpltMngKkoTalkDTO extends TmpltMngByTypeDTO implements Serializable {
|
||||
|
||||
@NotEmpty(message = "고객센터 전화번호는 필수 입력값 입니다.")
|
||||
@Length(max = 20, message = "고객센터 전화번호의 최대 길이를 초과 했습니다.")
|
||||
@Schema(required = true, title = "고객센터 전화번호", example = "02-123-4567")
|
||||
private String csNumber;
|
||||
|
||||
@NotEmpty(message = "고객센터 명은 필수 입력값 입니다.")
|
||||
@Length(max = 10, message = "고객센터 명의 최대 길이를 초과 했습니다.")
|
||||
@Schema(required = true, title = "고객센터 명", example = "콜센터")
|
||||
private String csName;
|
||||
|
||||
@NotEmpty(message = "CI변환사용여부는 필수 입력값 입니다.")
|
||||
@Length(max = 1, message = "CI변환사용여부의 최대 길이를 초과 했습니다.")
|
||||
@Pattern(regexp = "(Y|N)", message = "CI변환사용여부는 Y 또는 N 만 입력 할 수 있습니다.")
|
||||
@Schema(required = true, title = "CI변환사용여부", example = "Y")
|
||||
private String ciTransUseYn;
|
||||
|
||||
@NotEmpty(message = "템플릿 메시지 사용여부는 필수 입력값 입니다.")
|
||||
@Length(max = 1, message = "템플릿 메시지 사용여부의 최대 길이를 초과 했습니다.")
|
||||
@Pattern(regexp = "(Y|N)", message = "템플릿 메시지 사용여부는 Y 또는 N 만 입력 할 수 있습니다.")
|
||||
@Schema(required = true, title = "템플릿 메시지 사용여부", example = "Y")
|
||||
private String tmpltMsgUseYn;
|
||||
|
||||
@NotEmpty(message = "템플릿 CS 정보 사용여부는 필수 입력값 입니다.")
|
||||
@Length(max = 1, message = "템플릿 CS 정보 사용여부의 최대 길이를 초과 했습니다.")
|
||||
@Pattern(regexp = "(Y|N)", message = "템플릿 CS 정보 사용여부는 Y 또는 N 만 입력 할 수 있습니다.")
|
||||
@Schema(required = true, title = "템플릿 CS 정보 사용여부", example = "Y")
|
||||
private String tmpltCsInfoUseYn;
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cokr.xit.ens.modules.kkotalk.model.config;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import cokr.xit.ens.modules.kkomydoc.model.config.XitProperty;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkApiDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Getter
|
||||
@ToString
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "Document")
|
||||
public class Document extends KkotalkApiDTO.Envelope {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 상품 코드 - 필수
|
||||
* D10_1|D10_2|D11_1|D11_2
|
||||
* </pre>
|
||||
*/
|
||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "상품코드", example = "D10_2", allowableValues = {"D10_1","D10_2","D11_1","D11_2"})
|
||||
@Size(min = 3, max = 5, message = "상품 코드는 필수 입니다(\"D10_1\",\"D10_2\",\"D11_1\",\"D11_2\"")
|
||||
private String productCode = "D10_2";
|
||||
|
||||
@Valid
|
||||
private XitProperty xit_property;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cokr.xit.ens.modules.kkotalk.model.struct;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
import cokr.xit.ens.core.mapstruct.GenericMapper;
|
||||
import cokr.xit.ens.core.mapstruct.StructMapperConfig;
|
||||
import cokr.xit.ens.modules.kkotalk.domain.TmpltMngKkoTalk;
|
||||
import cokr.xit.ens.modules.kkotalk.model.TmpltMngKkoTalkDTO;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Mapper(config = StructMapperConfig.class)
|
||||
public interface TmpltMngKkoTalkMapper extends GenericMapper<TmpltMngKkoTalkDTO, TmpltMngKkoTalk> {
|
||||
|
||||
|
||||
@Override
|
||||
@Mapping(target = "orgMng.orgCd", source = "orgCd")
|
||||
TmpltMngKkoTalk toEntity(TmpltMngKkoTalkDTO tmpltMngKkoTalkDTO);
|
||||
|
||||
@Override
|
||||
@Mapping(target = "orgCd", expression = "java(tmpltMngKkoTalk.getOrgMng().getOrgCd())")
|
||||
TmpltMngKkoTalkDTO toDto(TmpltMngKkoTalk tmpltMngKkoTalk);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,497 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.modules.common.code.PostSeCd;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.OrgMngService;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.common.domain.support.FieldError;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydocTokenHist;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocTokenHistRepository;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkApiDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.IKkoTalkApiService;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.KkoTalkAcceptor;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.KkoTalkMaker;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.KkoTalkRsltFetcher;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.KkoTalkRsltProvider;
|
||||
import cokr.xit.ens.modules.kkotalk.service.support.KkoTalkSender;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkService {
|
||||
private final KkoTalkAcceptor kkoTalkAcceptor;
|
||||
|
||||
private final KkoTalkMaker kkoTalkMaker;
|
||||
private final KkoTalkSender kkoTalkSender;
|
||||
private final KkoTalkRsltFetcher kkoTalkRsltFetcher;
|
||||
private final KkoTalkRsltProvider kkoTalkRsltProvider;
|
||||
|
||||
private final IKkoTalkApiService kkoTalkApi;
|
||||
|
||||
private final SendMastRepository sendMastRepository;
|
||||
private final SendDetailKkoMydocTokenHistRepository sendDetailKkoMydocTokenHistRepository;
|
||||
private final OrgMngService orgMngService;
|
||||
|
||||
|
||||
/**
|
||||
* 접수 서비스
|
||||
*
|
||||
* @param reqDTO
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO<?> accept(KkotalkDTO.KkoTalkAcceptReqDTO reqDTO) {
|
||||
EnsResponseVO responseVO = null;
|
||||
try {
|
||||
responseVO = kkoTalkAcceptor.statBegin(reqDTO);
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
return responseVO;
|
||||
|
||||
responseVO = kkoTalkAcceptor.execute(reqDTO);
|
||||
} catch (EnsException e) {
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 제작 서비스
|
||||
*
|
||||
* @param sendMastId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO<?> remake(Long sendMastId) {
|
||||
try {
|
||||
SendMast sendMast = sendMastRepository.findById(sendMastId)
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.SEND404, "일치하는 자료가 없습니다."));
|
||||
if (!PostSeCd.kkoMydoc.equals(sendMast.getPostSe()))
|
||||
throw new EnsException(EnsErrCd.SEND404, String.format("%s 자료가 아닙니다.", PostSeCd.kkoMydoc.getCodeNm()));
|
||||
if (!(StatCd.accept.equals(sendMast.getStatCd())
|
||||
|| StatCd.makefail.equals(sendMast.getStatCd())))
|
||||
throw new EnsException(EnsErrCd.SEND404, "접수/제작실패(accept/makefail) 단계가 아닙니다.");
|
||||
} catch (EnsException e) {
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
kkoTalkMaker.statReady(Collections.singletonList(sendMastId));
|
||||
|
||||
|
||||
return this.make(sendMastId);
|
||||
}
|
||||
|
||||
/**
|
||||
* (일괄)제작 서비스
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO<?> makeAll() {
|
||||
List<Long> sendMastIds = sendMastRepository.findAllByPostSeAndStatCdIn(PostSeCd.kkoMydoc, Arrays.asList(StatCd.accept))
|
||||
.stream()
|
||||
.map(row -> row.getSendMastId())
|
||||
.collect(Collectors.toList());
|
||||
if (sendMastIds.isEmpty())
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.MAKE404)
|
||||
.errMsg("\"접수(accept)\" 상태인 자료가 없습니다")
|
||||
.build();
|
||||
|
||||
kkoTalkMaker.statReady(sendMastIds);
|
||||
|
||||
List<EnsResponseVO> resultInfo = sendMastIds.stream()
|
||||
.map(sendMastId -> this.make(sendMastId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
|
||||
}
|
||||
|
||||
private EnsResponseVO<?> make(Long sendMastId) {
|
||||
EnsResponseVO responseVO = kkoTalkMaker.statBegin(sendMastId);
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
return responseVO;
|
||||
|
||||
Optional<SendMast> sendMast = sendMastRepository.findById(sendMastId);
|
||||
try {
|
||||
//
|
||||
// responseVO = this.makeBillLink(sendMastId);
|
||||
// if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
// throw new EnsException(responseVO.getErrCode(), responseVO.getErrMsg());
|
||||
|
||||
responseVO = kkoTalkMaker.execute(sendMastId);
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
throw new EnsException(responseVO.getErrCode(), responseVO.getErrMsg());
|
||||
} catch (EnsException e) {
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 제작(청구서링크) 서비스
|
||||
*
|
||||
* @param sendMastId
|
||||
* @return
|
||||
*/
|
||||
// @Transactional(propagation = Propagation.SUPPORTS)
|
||||
// public EnsResponseVO makeBillLink(Long sendMastId) {
|
||||
// EnsResponseVO responseVO = kkoMydocMakerOfBillLink.execute(sendMastId);
|
||||
//
|
||||
// return responseVO;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* (대량)전송 서비스
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO<?> sendBulk(Long sendMastId) {
|
||||
|
||||
try {
|
||||
SendMast sendMast = sendMastRepository.findById(sendMastId)
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.SEND404, "일치하는 자료가 없습니다."));
|
||||
if (!PostSeCd.kkoMydoc.equals(sendMast.getPostSe()))
|
||||
throw new EnsException(EnsErrCd.SEND404, String.format("%s 자료가 아닙니다.", PostSeCd.kkoMydoc.getCodeNm()));
|
||||
if (!StatCd.makeok.equals(sendMast.getStatCd()))
|
||||
throw new EnsException(EnsErrCd.SEND404, "제작성공(makeok) 단계가 아닙니다.");
|
||||
} catch (EnsException e) {
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
List<Long> sendMastIds = Arrays.asList(sendMastId);
|
||||
EnsResponseVO responseVO = kkoTalkSender.statReady(sendMastIds);
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
return responseVO;
|
||||
|
||||
return this.send(sendMastIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* (대량)전송 서비스-일괄
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO<?> sendBulkAll() {
|
||||
List<Long> sendMastIds = sendMastRepository.findAllByPostSeAndStatCdInAndSendDtBefore(PostSeCd.kkoMydoc, Arrays.asList(StatCd.makeok), LocalDateTime.now())
|
||||
.stream()
|
||||
.map(row -> row.getSendMastId())
|
||||
.collect(Collectors.toList());
|
||||
if (sendMastIds.size() < 1)
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.SEND404)
|
||||
.errMsg("발송시간이 경과한 자료 중 \"제작성공(makeok)\" 상태인 자료가 없습니다")
|
||||
.build();
|
||||
|
||||
EnsResponseVO responseVO = kkoTalkSender.statReady(sendMastIds);
|
||||
if (!EnsErrCd.OK.equals(responseVO.getErrCode()))
|
||||
return responseVO;
|
||||
|
||||
return this.send(sendMastIds);
|
||||
}
|
||||
|
||||
private EnsResponseVO<?> send(List<Long> sendMastIds) {
|
||||
List<EnsResponseVO> resultInfo = sendMastIds.stream()
|
||||
.map(sendMastId -> {
|
||||
kkoTalkSender.statBegin(sendMastId);
|
||||
return sendMastId;
|
||||
})
|
||||
.map(sendMastId -> kkoTalkSender.execute(sendMastId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (대량)문서상태조회 서비스
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO statBulk(Long sendMastId) {
|
||||
try {
|
||||
SendMast sendMast = sendMastRepository.findById(sendMastId)
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.RSLT404, "일치하는 자료가 없습니다."));
|
||||
if (!PostSeCd.kkoMydoc.equals(sendMast.getPostSe()))
|
||||
throw new EnsException(EnsErrCd.RSLT404, String.format("%s 자료가 아닙니다.", PostSeCd.kkoMydoc.getCodeNm()));
|
||||
if (!Arrays.asList(StatCd.sendok, StatCd.sendcmplt, StatCd.open).stream()
|
||||
.anyMatch(statCd -> statCd.equals(sendMast.getStatCd())))
|
||||
throw new EnsException(EnsErrCd.RSLT404, "전송성공/전송완료/열람중(sendok/sendcmplt/open) 단계가 아닙니다.");
|
||||
} catch (EnsException e) {
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
List<EnsResponseVO> responseVOS = (List<EnsResponseVO>) this.stat(Arrays.asList(sendMastId)).getResultInfo();
|
||||
return responseVOS.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* (대량)문서상태조회 서비스-일괄
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO<?> statBulkAll() {
|
||||
List<Long> sendMastIds = sendMastRepository.findAllByPostSeAndStatCdIn(PostSeCd.kkoMydoc, Arrays.asList(StatCd.sendok, StatCd.sendcmplt, StatCd.open))
|
||||
.stream()
|
||||
.map(row -> row.getSendMastId())
|
||||
.collect(Collectors.toList());
|
||||
if (sendMastIds.size() < 1)
|
||||
return EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.RSLT404)
|
||||
.errMsg("\"전송성공/전송완료/열람중(sendok/sendcmplt/open)\" 상태인 자료가 없습니다")
|
||||
.build();
|
||||
|
||||
return this.stat(sendMastIds);
|
||||
}
|
||||
|
||||
private EnsResponseVO<?> stat(List<Long> sendMastIds) {
|
||||
List<EnsResponseVO> resultInfo = sendMastIds.stream()
|
||||
.map(sendMastId -> kkoTalkRsltFetcher.execute(sendMastId))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 토큰검증 서비스
|
||||
*
|
||||
* @param externalDocumentUuid
|
||||
* @param token
|
||||
* @param externalDocumentUuid
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
public EnsResponseVO<?> tokenVerify(String orgCd, String envelopId, String token, String externalDocumentUuid) {
|
||||
EnsResponseVO responseVO = null;
|
||||
|
||||
try {
|
||||
if (CmmnUtil.isEmpty(envelopId))
|
||||
throw new EnsException(EnsErrCd.ERR401, "문서식별번호(은)는 필수조건 입니다.");
|
||||
if (CmmnUtil.isEmpty(token))
|
||||
throw new EnsException(EnsErrCd.ERR401, "토큰(은)는 필수조건 입니다.");
|
||||
OrgMng orgMng = orgMngService.find(orgCd).getResultInfo();
|
||||
|
||||
KkotalkApiDTO.ValidTokenResponse resp = kkoTalkApi.validToken(
|
||||
KkotalkApiDTO.ValidTokenRequest.builder()
|
||||
.signguCode(orgMng.getOrgCd())
|
||||
.ffnlgCode("11")
|
||||
.envelopeId(envelopId)
|
||||
.token(token)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (!StringUtils.isEmpty(resp.getErrorCode())){
|
||||
responseVO = EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ERR600)
|
||||
.errMsg(String.format("%s %s", resp.getErrorCode(), resp.getErrorMessage()))
|
||||
.resultInfo(resp)
|
||||
.build();
|
||||
}else {
|
||||
|
||||
responseVO = EnsResponseVO.okBuilder()
|
||||
.resultInfo(resp)
|
||||
.build();
|
||||
}
|
||||
|
||||
// ResponseEntity<String> resp = kkoMydocApi.token(orgMng.getKkoMdAccessToken(), documentBinderUuid, token);
|
||||
// if (resp.getStatusCode() != HttpStatus.OK)
|
||||
// throw new EnsException(EnsErrCd.ERR620, String.format("토큰검증 실패. 실패사유: %s %s", resp.getStatusCode().toString(), resp.getBody()));
|
||||
|
||||
// Map<String, Object> mResponse = null;
|
||||
// try {
|
||||
// Gson gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
|
||||
// mResponse = gson.fromJson(resp.getBody(), Map.class);
|
||||
// } catch (Exception e) {
|
||||
// throw new EnsException(EnsErrCd.ERR505, String.format("토큰검증 응답데이터 파싱 실패. %s", resp.getBody()));
|
||||
// }
|
||||
|
||||
// String tokenUsedAt = (String) mResponse.get("token_status");
|
||||
// if ("USED".equals(tokenUsedAt)) {
|
||||
// responseVO = EnsResponseVO.okBuilder()
|
||||
// .resultInfo(mResponse)
|
||||
// .build();
|
||||
// } else {
|
||||
// String errorCode = (String) mResponse.get("error_code");
|
||||
// String errorMessage = (String) mResponse.get("error_message");
|
||||
// responseVO = EnsResponseVO.errRsltBuilder()
|
||||
// .errCode(EnsErrCd.ERR600)
|
||||
// .errMsg(String.format("%s %s", errorCode, errorMessage))
|
||||
// .resultInfo(mResponse)
|
||||
// .build();
|
||||
// }
|
||||
|
||||
|
||||
} catch (EnsException e) {
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.ERR999)
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
} finally {
|
||||
if (EnsErrCd.OK.equals(responseVO.getErrCode())) {
|
||||
Map<String, Object> resultInfo = (Map<String, Object>) responseVO.getResultInfo();
|
||||
sendDetailKkoMydocTokenHistRepository.save(SendDetailKkoMydocTokenHist.builder()
|
||||
.externalDocumentUuid(externalDocumentUuid)
|
||||
.documentBinderUuid(envelopId)
|
||||
.token(token)
|
||||
.tokenStatus((String) resultInfo.get("token_status"))
|
||||
.tokenUsedAt((Long) resultInfo.get("token_used_at"))
|
||||
.docBoxSentAt((Long) resultInfo.get("doc_box_sent_at"))
|
||||
.docBoxReceivedAt((Long) resultInfo.get("doc_box_received_at"))
|
||||
.authenticatedAt((Long) resultInfo.get("authenticated_at"))
|
||||
.userNotifiedAt((Long) resultInfo.get("user_notified_at"))
|
||||
.payload((String) resultInfo.get("payload"))
|
||||
.signedAt((String) resultInfo.get("signed_at"))
|
||||
.build());
|
||||
} else {
|
||||
sendDetailKkoMydocTokenHistRepository.save(SendDetailKkoMydocTokenHist.builder()
|
||||
.externalDocumentUuid(externalDocumentUuid)
|
||||
.documentBinderUuid(envelopId)
|
||||
.token(token)
|
||||
.error(FieldError.initBuilder()
|
||||
.errorCode(responseVO.getErrCode().getCode())
|
||||
.errorMessage(responseVO.getErrMsg())
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 문서상태변경 서비스
|
||||
* -.문서열람 시 본 서비스를 호출하지 않으면 "최초열람시간(doc_box_read_at)"은 제공되지 않는다.
|
||||
*
|
||||
* @param envelopeId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO readCmplt(String orgCd, String envelopeId) {
|
||||
EnsResponseVO responseVO = null;
|
||||
|
||||
try {
|
||||
if (CmmnUtil.isEmpty(orgCd))
|
||||
throw new EnsException(EnsErrCd.ERR401, "기관코드(은)는 필수조건 입니다.");
|
||||
if (CmmnUtil.isEmpty(envelopeId))
|
||||
throw new EnsException(EnsErrCd.ERR401, "문서식별번호(은)는 필수조건 입니다.");
|
||||
OrgMng orgMng = orgMngService.find(orgCd).getResultInfo();
|
||||
|
||||
KkotalkApiDTO.KkotalkErrorDTO resp = kkoTalkApi.modifyStatus(
|
||||
KkotalkDTO.EnvelopeId.builder()
|
||||
.envelopeId(envelopeId)
|
||||
.signguCode(orgMng.getOrgCd())
|
||||
.ffnlgCode("11")
|
||||
|
||||
.build()
|
||||
);
|
||||
|
||||
if (StringUtils.isEmpty(resp.getErrorCode())){
|
||||
responseVO = EnsResponseVO.okBuilder().build();
|
||||
}else{
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.ERR600)
|
||||
.errMsg(String.format("%s %s", resp.getErrorCode(), resp.getErrorMessage()))
|
||||
.build();
|
||||
}
|
||||
// ResponseEntity<String> resp = kkoTalkApi.readCompleted(orgMng.getKkoMdAccessToken(), documentBinderUuid);
|
||||
//
|
||||
//
|
||||
// if (resp.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
|
||||
// responseVO = EnsResponseVO.okBuilder().build();
|
||||
// } else {
|
||||
// Map<String, Object> mResponse = null;
|
||||
// try {
|
||||
// Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
// mResponse = gson.fromJson(resp.getBody(), Map.class);
|
||||
// } catch (Exception e) {
|
||||
// throw new EnsException(EnsErrCd.ERR505, String.format("문서상태변경 응답데이터 파싱 실패. %s", resp.getBody()));
|
||||
// }
|
||||
// String errorCode = (String) mResponse.get("error_code");
|
||||
// String errorMessage = (String) mResponse.get("error_message");
|
||||
// responseVO = EnsResponseVO.errBuilder()
|
||||
// .errCode(EnsErrCd.ERR600)
|
||||
// .errMsg(String.format("%s %s", errorCode, errorMessage))
|
||||
// .build();
|
||||
// }
|
||||
|
||||
} catch (EnsException e) {
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
responseVO = EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.ERR999)
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 전송결과 제공
|
||||
*
|
||||
* @param sendMastId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public EnsResponseVO sendResultProvide(Long sendMastId) {
|
||||
|
||||
return kkoTalkRsltProvider.execute(sendMastId);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.strategy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.OrgMngRepository;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.TmpltMngRepository;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngDTO;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngSearchDTO;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.strategy.TmpltMngStrategyTemplate;
|
||||
import cokr.xit.ens.modules.kkotalk.domain.TmpltMngKkoTalk;
|
||||
import cokr.xit.ens.modules.kkotalk.domain.repository.TmpltMngKkoTalkRepository;
|
||||
import cokr.xit.ens.modules.kkotalk.model.TmpltMngKkoTalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.struct.TmpltMngKkoTalkMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Component("tmpltMngStrategy_kkotalk")
|
||||
@RequiredArgsConstructor
|
||||
public class TmpltMngStrategyKkoTalk extends TmpltMngStrategyTemplate<Map<String, Object>, TmpltMngKkoTalkDTO> {
|
||||
|
||||
private final OrgMngRepository orgMngRepository;
|
||||
private final TmpltMngRepository tmpltMngRepository;
|
||||
private final TmpltMngKkoTalkRepository tmpltMngKkoTalkRepository;
|
||||
private final TmpltMngKkoTalkMapper kkoTalkMapper = Mappers.getMapper(TmpltMngKkoTalkMapper.class);
|
||||
// private final RedisTemplate redisTemplate;
|
||||
|
||||
@Override
|
||||
public List<TmpltMngKkoTalkDTO> findAll(TmpltMngSearchDTO tmpltMngSearchDTO) {
|
||||
return tmpltMngKkoTalkRepository.findAllDtoBySearchDTO(tmpltMngSearchDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TmpltMngKkoTalkDTO> find(String orgCd, String tmpltCd) {
|
||||
return tmpltMngKkoTalkRepository.findDtoByOrgCdAndTmpltCd(orgCd, tmpltCd);
|
||||
|
||||
// String key = super.pushCache(redisTemplate, orgCd, tmpltCd, tmpltMngKkoMydocRepository);
|
||||
// HashOperations<String, String, TmpltMngKkoMydocDTO> hashOperations = redisTemplate.opsForHash();
|
||||
// return Optional.ofNullable(hashOperations.entries(KEY).get(key));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected TmpltMngKkoTalkDTO validate(Map<String, Object> params) {
|
||||
try {
|
||||
TmpltMngKkoTalkDTO dto = mapper.convertValue(params, TmpltMngKkoTalkDTO.class);
|
||||
|
||||
final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
Set<ConstraintViolation<TmpltMngKkoTalkDTO>> list = validator.validate(dto);
|
||||
if (!list.isEmpty()) {
|
||||
throw new EnsException(EnsErrCd.ERR410, "유효하지 않은 요청 값 입니다.", list.stream()
|
||||
.map(row -> String.format("%s [ %s ]", row.getMessageTemplate(), row.getPropertyPath()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
return dto;
|
||||
}catch (IllegalArgumentException e){
|
||||
List<String> fields = Arrays.stream(TmpltMngDTO.class.getDeclaredFields()).map(row->row.getName()).collect(Collectors.toList());
|
||||
fields.addAll(Arrays.stream(TmpltMngKkoTalkDTO.class.getDeclaredFields()).map(row->row.getName()).collect(Collectors.toList()));
|
||||
throw new EnsException(EnsErrCd.ERR403, "유효하지 않은 파라미터 입니다. 사용가능한 파라미터는 resultInfo 를 참고하시기 바랍니다.", fields);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addProc(TmpltMngKkoTalkDTO dto) {
|
||||
OrgMng orgMng = orgMngRepository.findById(dto.getOrgCd()).orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("기관코드(%s)가 일치하는 자료가 없습니다.", dto.getOrgCd())));
|
||||
tmpltMngRepository.findFetchByOrgCdAndTmpltCd(dto.getOrgCd(), dto.getTmpltCd())
|
||||
.ifPresent(tmpltMng -> {
|
||||
throw new EnsException(EnsErrCd.ERR540, String.format("이미 등록된 템플릿코드[기관코드 %s 템플릿코드 %s] 입니다.", tmpltMng.getOrgMng().getOrgCd(), tmpltMng.getTmpltCd()));
|
||||
});
|
||||
|
||||
TmpltMngKkoTalk tmpltMng = kkoTalkMapper.toEntity(dto);
|
||||
tmpltMng.setOrgMng(orgMng);
|
||||
tmpltMng.setRegistId("ENS_SYS");
|
||||
tmpltMngKkoTalkRepository.save(tmpltMng);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void modifyProc(TmpltMngKkoTalkDTO dto) {
|
||||
TmpltMngKkoTalk tmpltMng = tmpltMngKkoTalkRepository.findFetchByOrgCdAndTmpltCd((dto).getOrgCd(), (dto).getTmpltCd())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("기관코드(%s) 및 템플릿코드(%s)가 일치하는 자료가 없습니다.", dto.getOrgCd(), dto.getTmpltCd())));
|
||||
if(!"Y".equals(tmpltMng.getUseYn()))
|
||||
throw new EnsException(EnsErrCd.ERR402, "\"미사용\" 상태의 템플릿은 수정 할 수 없습니다.");
|
||||
kkoTalkMapper.updateFromDto(dto, tmpltMng);
|
||||
tmpltMng.setUpdId("ENS_SYS");
|
||||
|
||||
// super.deleteCache(redisTemplate, dto.getOrgCd(), dto.getTmpltCd());
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.core.utils.DateUtil;
|
||||
import cokr.xit.ens.core.utils.IdGenerator;
|
||||
import cokr.xit.ens.core.utils.MapDeserailizer;
|
||||
import cokr.xit.ens.core.utils.crypto.AES256;
|
||||
import cokr.xit.ens.core.utils.crypto.Crypto;
|
||||
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
|
||||
import cokr.xit.ens.modules.common.code.PostSeCd;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.code.VenderCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.Bill;
|
||||
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.repository.BillRepository;
|
||||
import cokr.xit.ens.modules.common.ctgy.mblpage.domain.SendDetailMblPage;
|
||||
import cokr.xit.ens.modules.common.ctgy.mblpage.domain.repository.SendDetailMblPageRepository;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.OrgMngService;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.TmpltMngService;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.config.XitProperty;
|
||||
import cokr.xit.ens.modules.kkotalk.mapper.IKkoTalkMapper;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkAcceptor implements EnsPhaseProcSupport<EnsResponseVO<?>, KkotalkDTO.KkoTalkAcceptReqDTO> {
|
||||
|
||||
private final SendMastRepository sendMastRepository;
|
||||
private final IKkoTalkMapper kkoTalkMapper;
|
||||
private final SendDetailMblPageRepository sendDetailMblPageRepository;
|
||||
private final BillRepository billRepository;
|
||||
private final OrgMngService orgMngService;
|
||||
private final TmpltMngService tmpltMngService;
|
||||
|
||||
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).disableHtmlEscaping().create();
|
||||
|
||||
@Override
|
||||
public EnsResponseVO<?> statReady(List<KkotalkDTO.KkoTalkAcceptReqDTO> reqDTOs) {
|
||||
log.info("no process");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnsResponseVO<?> statBegin(KkotalkDTO.KkoTalkAcceptReqDTO reqDTO) {
|
||||
final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
Set<ConstraintViolation<KkotalkDTO.KkoTalkAcceptReqDTO>> list = validator.validate(reqDTO);
|
||||
if (!list.isEmpty()) {
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ACPT402)
|
||||
.errMsg("유효하지 않은 요청값 입니다.")
|
||||
.resultInfo(list.stream()
|
||||
.map(row -> String.format("%s [ %s ]", row.getMessageTemplate(), row.getPropertyPath()))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
List<String> expiredDateValidateList = expiredDateVaildate(reqDTO);
|
||||
if (!expiredDateValidateList.isEmpty()) {
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ACPT402)
|
||||
.errMsg("유효하지 않은 유효기한 입니다. 자료의 유효기한은 마감일시 이내이어야 합니다.")
|
||||
.resultInfo(expiredDateValidateList)
|
||||
.build();
|
||||
}
|
||||
EnsResponseVO<OrgMng> orgMng = orgMngService.find(reqDTO.getOrg_cd());
|
||||
if (!EnsErrCd.OK.equals(orgMng.getErrCode()))
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ACPT404)
|
||||
.errMsg("일치하는 기관정보가 없습니다.")
|
||||
.resultInfo(orgMng.getErrMsg())
|
||||
.build();
|
||||
EnsResponseVO<?> tmpltMng = tmpltMngService.find(reqDTO.getOrg_cd(), reqDTO.getTmplt_cd(), "kkotalk");
|
||||
if (!EnsErrCd.OK.equals(tmpltMng.getErrCode()))
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ACPT404)
|
||||
.errMsg("일치하는 템플릿정보가 없습니다.")
|
||||
.resultInfo(tmpltMng.getErrMsg())
|
||||
.build();
|
||||
|
||||
return EnsResponseVO.okBuilder().build();
|
||||
}
|
||||
|
||||
private List<String> expiredDateVaildate(KkotalkDTO.KkoTalkAcceptReqDTO reqDTO) {
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
reqDTO.getDocuments().forEach(document -> {
|
||||
if (!CmmnUtil.isEmpty(document)) {
|
||||
if (!CmmnUtil.isEmpty(document.getReadExpiresAt())) {
|
||||
String expDate = DateUtil.getTimeOfTimeT(document.getReadExpiresAt(), "yyyyMMddHHmmss");
|
||||
int sec = DateUtil.secByFromBetweenTo(DateUtil.toLocalDateTime(expDate), DateUtil.toLocalDateTime(reqDTO.getClose_dt()));
|
||||
if (sec < 0)
|
||||
result.add(String.format("마감일시보다 \"처리마감시간\"이 느립니다. [ document[%d].acpt_data.kko_talk.read_expires_at ]", i.get()));
|
||||
}
|
||||
if (!CmmnUtil.isEmpty(document.getReviewExpiresAt())) {
|
||||
String expDate = DateUtil.getTimeOfTimeT(document.getReviewExpiresAt(), "yyyyMMddHHmmss");
|
||||
int sec = DateUtil.secByFromBetweenTo(DateUtil.toLocalDateTime(expDate), DateUtil.toLocalDateTime(reqDTO.getClose_dt()));
|
||||
if (sec < 0)
|
||||
result.add(String.format("마감일시보다 \"처리마감시간\"이 느립니다. [ document[%d].acpt_data.kko_talk.read_expires_at ]", i.get()));
|
||||
}
|
||||
}
|
||||
i.getAndIncrement();
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO<?> execute(KkotalkDTO.KkoTalkAcceptReqDTO reqDTO) throws EnsException {
|
||||
AES256 aes256 = new AES256(Crypto.AES256.getKey());
|
||||
EnsResponseVO<?> responseVO = null;
|
||||
try {
|
||||
SendMast sendMast = SendMast.builder()
|
||||
.vender(VenderCd.valueOfEnum(reqDTO.getVender()))
|
||||
.postSe(PostSeCd.kkoTalk)
|
||||
.orgCd(reqDTO.getOrg_cd())
|
||||
.tmpltCd(reqDTO.getTmplt_cd())
|
||||
.postBundleTitle(reqDTO.getPost_bundle_title())
|
||||
.statCd(StatCd.accept)
|
||||
.sendDt(DateUtil.toLocalDateTime(reqDTO.getSend_dt()))
|
||||
.sendCnt(reqDTO.getDocuments().size())
|
||||
.closeDt(DateUtil.toLocalDateTime(reqDTO.getClose_dt()))
|
||||
.build();
|
||||
sendMastRepository.save(sendMast);
|
||||
|
||||
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> sendDetails = new ArrayList<>();
|
||||
List<Map<String, Object>> sendDetailMblPages = new ArrayList<>();
|
||||
List<Bill> bills = new ArrayList<>();
|
||||
final String prefixBillUid = sendMast.getPostSe().getCode() + "-" + IdGenerator.getCurrentTimeSec();
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
reqDTO.getDocuments().forEach(document -> {
|
||||
i.getAndIncrement();
|
||||
try {
|
||||
|
||||
Bill bill = null;
|
||||
if (!CmmnUtil.isEmpty(document.getXit_property())
|
||||
&& !CmmnUtil.isEmpty(document.getXit_property().getBill_acpt_data())) {
|
||||
// if (document.getXit_property().getBill_acpt_data().getUse_bill_uid()) {
|
||||
if (!CmmnUtil.isEmpty(document.getXit_property().getBill_acpt_data().getBillUid())) {
|
||||
bill = billRepository.findByBillUid(document.getXit_property().getBill_acpt_data().getBillUid())
|
||||
.orElseThrow(() -> new RuntimeException("등록된 청구서가 없습니다."));
|
||||
} else {
|
||||
bill = Bill.builder()
|
||||
// .billId(document.getXit_property().getBill_acpt_data().getBill_id())
|
||||
.billId(null)
|
||||
.billUid(IdGenerator.getShortUUID(prefixBillUid))
|
||||
.billerUserKey(document.getXit_property().getBill_acpt_data().getBillerUserKey())
|
||||
.billSeCd(document.getXit_property().getBill_acpt_data().getBillSe())
|
||||
.orgMng(OrgMng.builder().orgCd(reqDTO.getOrg_cd()).build())
|
||||
// .docBillKko(CmmnUtil.isEmpty(document.getXit_property().getBill_acpt_data().getBill_kko()) ? null : gson.toJson(document.getXit_property().getBill_acpt_data().getBill_kko()))
|
||||
// .docBillNv(CmmnUtil.isEmpty(document.getXit_property().getBill_acpt_data().getBill_nv()) ? null : gson.toJson(document.getXit_property().getBill_acpt_data().getBill_nv()))
|
||||
.build();
|
||||
}
|
||||
bills.add(bill);
|
||||
}
|
||||
|
||||
|
||||
XitProperty xitProperty = Optional.ofNullable(document.getXit_property()).orElse(XitProperty.builder().build());
|
||||
|
||||
|
||||
KkotalkDTO.SendDetailKkoTalkDTO sendDetail = KkotalkDTO.SendDetailKkoTalkDTO.builder()
|
||||
.sendMastId(sendMast.getSendMastId())
|
||||
.title(document.getTitle())
|
||||
.link(document.getContent().getLink())
|
||||
.hash(document.getHash())
|
||||
.guide(document.getGuide())
|
||||
.payload(document.getPayload())
|
||||
.readExpiresAt(document.getReadExpiresAt())
|
||||
.reviewExpiresAt(document.getReviewExpiresAt())
|
||||
.useNonPersonalizedNotification(document.getUseNonPersonalizedNotification())
|
||||
.ci(document.getCi())
|
||||
.phoneNumber(document.getPhoneNumber())
|
||||
.name(document.getName())
|
||||
.birthday(document.getBirthday())
|
||||
.externalId(document.getExternalId())
|
||||
.mkBillUseYn(CmmnUtil.isEmpty(bill) ? "N" : "Y")
|
||||
// .mkBillUid(bill == null ? null : bill.getBillUid())
|
||||
.billUid(Objects.requireNonNull(bill).getBillUid())
|
||||
// .mkJid(xitProperty.getJid())
|
||||
.mkJid(aes256.encrypt(xitProperty.getJid()))
|
||||
.mkTmpltMsgJsonData(CmmnUtil.isEmpty(xitProperty.getTmplt_msg_data()) ? null : gson.toJson(xitProperty.getTmplt_msg_data()))
|
||||
.build();
|
||||
sendDetails.add(sendDetail);
|
||||
|
||||
if (!(CmmnUtil.isEmpty(document.getXit_property()) || CmmnUtil.isEmpty(document.getXit_property().getMbl_page_data()))) {
|
||||
Map<String, Object> mMblPage = new HashMap<>();
|
||||
mMblPage.put("sendDetail", sendDetail);
|
||||
mMblPage.put("details", gson.toJson(document.getXit_property().getMbl_page_data()));
|
||||
sendDetailMblPages.add(mMblPage);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new EnsException(EnsErrCd.ACPT500, String.format("%d번째 데이터 접수처리 중 오류 발생. 실패사유: %s", i.get(), e.getMessage()));
|
||||
}
|
||||
});
|
||||
if (CmmnUtil.isEmpty(sendDetails))
|
||||
throw new EnsException(EnsErrCd.ACPT410, "발송상세 자료가 없습니다.");
|
||||
|
||||
|
||||
billRepository.saveAll(bills.stream()
|
||||
.filter(row -> CmmnUtil.isEmpty(row.getBillId()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
// kkotalk 발송상세 저장
|
||||
sendDetails.forEach(kkoTalkMapper::saveSndDtlKkoTalk);
|
||||
|
||||
if (!sendDetailMblPages.isEmpty())
|
||||
|
||||
sendDetailMblPageRepository.saveAll(
|
||||
sendDetailMblPages.stream()
|
||||
.map(data -> {
|
||||
KkotalkDTO.SendDetailKkoTalkDTO sendDetail = (KkotalkDTO.SendDetailKkoTalkDTO) data.get("sendDetail");
|
||||
return SendDetailMblPage.builder()
|
||||
.postSe(PostSeCd.kkoTalk.getCode())
|
||||
.sendDetailId(sendDetail.getSendDetailId())
|
||||
.details((String) data.get("details"))
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
|
||||
Map<String, Object> resultInfo = new HashMap<>();
|
||||
resultInfo.put("sendMastId", sendMast.getSendMastId());
|
||||
resultInfo.put("sendDetails", sendDetails);
|
||||
responseVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
|
||||
} catch (EnsException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new EnsException(EnsErrCd.ACPT500, String.format("오류가 발생하여 접수에 실패 했습니다. 실패사유: %s", e.getMessage()));
|
||||
}
|
||||
|
||||
return responseVO;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,259 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.monitor.slack.event.MonitorEvent;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.core.utils.IdGenerator;
|
||||
import cokr.xit.ens.core.utils.MapDeserailizer;
|
||||
import cokr.xit.ens.core.utils.crypto.AES256;
|
||||
import cokr.xit.ens.core.utils.crypto.Crypto;
|
||||
import cokr.xit.ens.core.utils.crypto.SHA256;
|
||||
import cokr.xit.ens.modules.common.biztmplt.MakeProcTemplate;
|
||||
import cokr.xit.ens.modules.common.code.PostSeCd;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.nicedici.service.NiceDiCiService;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.OrgMngService;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.common.domain.support.FieldError;
|
||||
import cokr.xit.ens.modules.common.event.SendMastStatUpdateEvent;
|
||||
import cokr.xit.ens.modules.common.monitor.MessageByPhase;
|
||||
import cokr.xit.ens.modules.kkotalk.mapper.IKkoTalkMapper;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.TmpltMngKkoTalkDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.service.strategy.TmpltMngStrategyKkoTalk;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.val;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkMaker extends MakeProcTemplate {
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
private final SendMastRepository sendMastRepository;
|
||||
//private final SendDetailKkoMydocRepository sendDetailKkoMydocRepository;
|
||||
private final IKkoTalkMapper kkoTalkMapper;
|
||||
private final OrgMngService orgMngService;
|
||||
private final TmpltMngStrategyKkoTalk tmpltMngService;
|
||||
private final NiceDiCiService niceDiCiService;
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO<?> execute(Long sendMastId) {
|
||||
AES256 aes256 = new AES256(Crypto.AES256.getKey());
|
||||
SendMast sendMast = null;
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> sendDetails = null;
|
||||
EnsResponseVO respVO = null;
|
||||
try {
|
||||
if (CmmnUtil.isEmpty(sendMastId))
|
||||
throw new EnsException(EnsErrCd.MAKE410, "발송마스터ID(은)는 필수조건 입니다.");
|
||||
|
||||
sendMast = sendMastRepository.findById(sendMastId)
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE404, String.format("일치하는 발송마스터 자료가 없습니다. [ sendMastId %s ]", sendMastId)));
|
||||
// kkotalk 발송상세 조회
|
||||
sendDetails = kkoTalkMapper.findAllBySendMastId(sendMastId);
|
||||
SendMast finalSendMast = sendMast;
|
||||
OrgMng orgMng = orgMngService.find(sendMast.getOrgCd()).getResultInfo();
|
||||
// TmpltMngKkoMydoc tmpltMngDTO = tmpltMngRepository.findFetchByOrgCdAndTmpltCdAndUseYn(sendMast.getOrgCd(), sendMast.getTmpltCd(), "Y")
|
||||
// .orElseThrow(() -> new EnsException(EnsErrCd.MAKE404, String.format("일치하는 템플릿 자료가 없거나 미사용 상태의 템플릿 입니다. [ sendMastId %s orgCd %s TmpltCd %s ]", sendMastId, finalSendMast.getOrgCd(), finalSendMast.getTmpltCd())));
|
||||
TmpltMngKkoTalkDTO tmpltMngDTO = tmpltMngService.find(sendMast.getOrgCd(), sendMast.getTmpltCd())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE404, String.format("일치하는 템플릿 자료가 없습니다. [ sendMastId %s orgCd %s TmpltCd %s ]", sendMastId, finalSendMast.getOrgCd(), finalSendMast.getTmpltCd())));
|
||||
if (!"Y".equals(tmpltMngDTO.getUseYn()))
|
||||
throw new EnsException(EnsErrCd.MAKE521, String.format("미사용 상태의 템플릿 입니다. [ sendMastId %s orgCd %s TmpltCd %s ]", sendMastId, finalSendMast.getOrgCd(), finalSendMast.getTmpltCd()));
|
||||
|
||||
|
||||
Map<String, String> mCi = new HashMap<>();
|
||||
if ("Y".equals(tmpltMngDTO.getCiTransUseYn())) {
|
||||
List<String> jids = sendDetails.stream()
|
||||
// .filter(row -> "Y".equals(row.getMkCiTransUseYn()))
|
||||
.filter(row -> !CmmnUtil.isEmpty(row.getMkJid()))
|
||||
// .map(row -> row.getMkJid())
|
||||
.map(row -> aes256.decrypt(row.getMkJid()))
|
||||
.collect(Collectors.toList());
|
||||
if (!CmmnUtil.isEmpty(jids)) {
|
||||
val ciResponseVO = niceDiCiService.ci(orgMng.getNiceCdSiteCode(), orgMng.getNiceCdSitePw(), orgMng.getNiceCdClientId(), orgMng.getNiceCdClientSercet(), jids);
|
||||
if (!EnsErrCd.OK.equals(ciResponseVO.getErrCode()))
|
||||
throw new EnsException(EnsErrCd.MAKE513, String.format("%s %s", ciResponseVO.getErrCode(), ciResponseVO.getErrMsg()));
|
||||
|
||||
final List<EnsResponseVO> responseVOList = (List<EnsResponseVO>)ciResponseVO.getResultInfo();
|
||||
mCi = responseVOList.stream()
|
||||
.map(vo -> {
|
||||
Map<String, String> resultInfo = (Map<String, String>) vo.getResultInfo();
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("key", resultInfo.get("jid"));
|
||||
m.put("value", CmmnUtil.isEmpty(resultInfo.get("ci")) ? "" : resultInfo.get("ci"));
|
||||
return m;
|
||||
})
|
||||
.collect(Collectors.toMap(m -> m.get("key"), m -> m.get("value"), (k1, k2) -> k1));
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> finalMCi = mCi;
|
||||
Optional<Integer> cntSuccess = sendDetails.stream()
|
||||
.map(row -> {
|
||||
try {
|
||||
|
||||
row.setTitle(Optional.ofNullable(tmpltMngDTO.getTitle())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE521, String.format("title 생성에 실패 했습니다. [ orgCd %s tmpltCd %s]", tmpltMngDTO.getOrgCd(), tmpltMngDTO.getTmpltCd()))));
|
||||
|
||||
if ("Y".equals(tmpltMngDTO.getTmpltCsInfoUseYn())) {
|
||||
row.setPhoneNumber(Optional.ofNullable(tmpltMngDTO.getCsNumber())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE521,
|
||||
String.format("phoneNumber 생성에 실패 했습니다. [ orgCd %s tmpltCd %s]",
|
||||
tmpltMngDTO.getOrgCd(), tmpltMngDTO.getTmpltCd()))));
|
||||
|
||||
|
||||
row.setName(Optional.ofNullable(tmpltMngDTO.getCsName())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE521,
|
||||
String.format("name 생성에 실패 했습니다. [ orgCd %s tmpltCd %s]",
|
||||
tmpltMngDTO.getOrgCd(), tmpltMngDTO.getTmpltCd()))));
|
||||
}
|
||||
//if ("Y".equals(tmpltMngDTO.getTmpltMsgUseYn())) {
|
||||
// boolean usePryMsg = CmmnUtil.isEmpty(tmpltMngDTO.getPryMessage()) ? false : true;
|
||||
// row.setPropMessage(Optional.ofNullable(this.msgTmplateToMessage(usePryMsg, tmpltMngDTO, row.getMkTmpltMsgJsonData()))
|
||||
// .orElseThrow(() -> new EnsException(EnsErrCd.MAKE521, String.format("propMessage 생성에 실패 했습니다. [ orgCd %s tmpltCd %s tmpltMsgJsonData %s ]", tmpltMngDTO.getOrgCd(), tmpltMngDTO.getTmpltCd(), row.getMkTmpltMsgJsonData()))));
|
||||
//}
|
||||
|
||||
if (CmmnUtil.isEmpty(row.getExternalId()))
|
||||
row.setExternalId(Optional.ofNullable(IdGenerator.getUUID())
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE521, String.format("propExternalDocumentUuid 생성에 실패 했습니다"))));
|
||||
//if (CmmnUtil.isEmpty(row.getPropExternalDocumentUuid()))
|
||||
// row.setPropExternalDocumentUuid(Optional.ofNullable(IdGenerator.getUUID())
|
||||
// .orElseThrow(() -> new EnsException(EnsErrCd.MAKE521, String.format("propExternalDocumentUuid 생성에 실패 했습니다"))));
|
||||
|
||||
if (CmmnUtil.isEmpty(row.getHash()))
|
||||
row.setHash(Optional.ofNullable(this.createHash(row))
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.MAKE521, String.format("hash 생성에 실패 했습니다."))));
|
||||
|
||||
//if ("Y".equals(tmpltMngDTO.getCiTransUseYn()) && !CmmnUtil.isEmpty(row.getMkJid()))
|
||||
// row.setRecvCi(Optional.ofNullable(finalMCi.get(aes256.decrypt(row.getMkJid()).replaceAll("[^0-9]", "")))
|
||||
// .map(ci -> CmmnUtil.isEmpty(ci) ? null : ci)
|
||||
// .orElseThrow(() -> new EnsException(EnsErrCd.MAKE610, String.format("recvCi 생성에 실패 했습니다. 주민번호에 대한 CI 값이 없습니다. [ jid %s ]", aes256.decrypt(row.getMkJid())))));
|
||||
|
||||
//row.setError(FieldError.initBuilder().build());
|
||||
return 1;
|
||||
} catch (EnsException e) {
|
||||
row.setErrorCode(e.getErrCd().getCode());
|
||||
row.setErrorMessage(e.getMessage());
|
||||
//row.setError(FieldError.initBuilder()
|
||||
// .errorCode(e.getErrCd().getCode())
|
||||
// .errorMessage(e.getMessage())
|
||||
// .build());
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
.reduce(Integer::sum);
|
||||
|
||||
|
||||
|
||||
if (cntSuccess.get() > 0)
|
||||
respVO = EnsResponseVO.okBuilder().resultInfo(String.format("총 %d건 중 %d건 제작 성공. [ sendMastId %s ]", sendDetails.size(), cntSuccess.get(), sendMastId)).build();
|
||||
else
|
||||
throw new EnsException(EnsErrCd.MAKE500, String.format("총 %d 건 제작 실패", sendDetails.size()));
|
||||
} catch (EnsException e) {
|
||||
|
||||
respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
|
||||
} catch (Exception e) {
|
||||
|
||||
respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.MAKE500).errMsg(e.getMessage()).build();
|
||||
} finally {
|
||||
if (!CmmnUtil.isEmpty(sendMast))
|
||||
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
sendMast.setStatCd(StatCd.makeok);
|
||||
sendMast.setError(FieldError.initBuilder().build());
|
||||
} else {
|
||||
sendMast.setStatCd(StatCd.makefail);
|
||||
sendMast.setError(FieldError.initBuilder()
|
||||
.errorCode(respVO.getErrCode().getCode())
|
||||
.errorMessage(respVO.getErrMsg())
|
||||
.build());
|
||||
|
||||
applicationEventPublisher.publishEvent(MonitorEvent.builder()
|
||||
.message(MessageByPhase.builder()
|
||||
.oClass(getClass().getSimpleName() + "." + new Throwable().getStackTrace()[0].getMethodName())
|
||||
.postSeCd(PostSeCd.kkoMydoc)
|
||||
.statCd(StatCd.makefail)
|
||||
.errCd(respVO.getErrCode())
|
||||
.message("-.SendMastId: " + sendMastId + "\n" + respVO.getErrMsg())
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
applicationEventPublisher.publishEvent(SendMastStatUpdateEvent.builder().sendMastId(sendMastId).build());
|
||||
}
|
||||
|
||||
|
||||
return respVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash값을 생성 한다.
|
||||
*
|
||||
* @param vo
|
||||
* @return
|
||||
*/
|
||||
private String createHash(KkotalkDTO.SendDetailKkoTalkDTO vo) {
|
||||
String hash = null;
|
||||
try {
|
||||
String text = vo.getExternalId()
|
||||
+ vo.getLink();
|
||||
// String text = new StringBuilder()
|
||||
// .append(vo.getPropExternalDocumentUuid())
|
||||
// .append(vo.getPropLink())
|
||||
// .append(vo.getPropMessage())
|
||||
// .toString();
|
||||
hash = SHA256.encrypt(text);
|
||||
} catch (Exception e) {
|
||||
log.error("hash 값 생성 실패. [ sendDetailId {} ]", vo.getSendDetailId());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 메시지템플릿을 메시지로 변환 후 반환 한다.
|
||||
*
|
||||
* @param usePryMsg
|
||||
* @param tmpltMngDTO
|
||||
* @param tmplateMsgData
|
||||
* @return
|
||||
*/
|
||||
private String msgTmplateToMessage(boolean usePryMsg, TmpltMngKkoTalkDTO tmpltMngDTO, String tmplateMsgData) {
|
||||
String message = usePryMsg ? tmpltMngDTO.getPryMessage() : tmpltMngDTO.getMessage();
|
||||
if (CmmnUtil.isEmpty(tmplateMsgData))
|
||||
return message;
|
||||
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
|
||||
try {
|
||||
Map<String, Object> mMsgData = gson.fromJson(tmplateMsgData, Map.class);
|
||||
for (String key : mMsgData.keySet()) {
|
||||
message = message.replace(key, String.valueOf(mMsgData.get(key)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("template Message 변환 실패. [ orgCd {} tmpltCd {} msgData {} ]", tmpltMngDTO.getOrgCd(), tmpltMngDTO.getTmpltCd(), tmplateMsgData, e);
|
||||
return null;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
@ -0,0 +1,380 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.core.utils.DateUtil;
|
||||
import cokr.xit.ens.core.utils.MapDeserailizer;
|
||||
import cokr.xit.ens.modules.common.biztmplt.ResultProcTemplate;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.OrgMngService;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.common.domain.support.FieldError;
|
||||
import cokr.xit.ens.modules.common.event.SendMastStatUpdateEvent;
|
||||
import cokr.xit.ens.modules.kkomydoc.code.KkoMydocStatusCd;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydoc;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydocStatHist;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocStatHistRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.KkoMydocApiRespVO;
|
||||
import cokr.xit.ens.modules.kkomydoc.service.support.KkoMydocApiSpec;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkRsltFetcher extends ResultProcTemplate {
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
private final SendMastRepository sendMastRepository;
|
||||
private final SendDetailKkoMydocRepository sendDetailKkoMydocRepository;
|
||||
private final SendDetailKkoMydocStatHistRepository sendDetailKkoMydocStatHistRepository;
|
||||
private final OrgMngService orgMngService;
|
||||
private final KkoMydocApiSpec kkoMydocApi;
|
||||
@Value("${contract.kakao.pay.mydoc.api.bulksend-batch-unit}")
|
||||
private int SEND_BATCH_UNIT;
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO execute(Long sendMastId) {
|
||||
|
||||
|
||||
SendMast sendMast = null;
|
||||
List<SendDetailKkoMydoc> sendDetails = null;
|
||||
EnsResponseVO respVO = null;
|
||||
Map<String, Long> resultInfo = new HashMap<>();
|
||||
resultInfo.put("sendMastId", sendMastId);
|
||||
try {
|
||||
if (CmmnUtil.isEmpty(sendMastId))
|
||||
throw new EnsException(EnsErrCd.RSLT410, "발송마스터ID(은)는 필수조건 입니다.");
|
||||
|
||||
sendMast = sendMastRepository.findById(sendMastId).orElseThrow(() -> new EnsException(EnsErrCd.RSLT404, String.format("일치하는 발송마스터 자료가 없습니다. [ sendMastId %s ]", sendMastId)));
|
||||
sendDetails = sendDetailKkoMydocRepository.findAllBySendMastAndDocumentBinderUuidIsNotNull(sendMast);
|
||||
OrgMng orgMng = orgMngService.find(sendMast.getOrgCd()).getResultInfo();
|
||||
|
||||
Lists.partition(sendDetails, SEND_BATCH_UNIT).stream()
|
||||
.forEach(list -> {
|
||||
|
||||
String sendRespBody = null;
|
||||
String jsonStr = null;
|
||||
try {
|
||||
|
||||
EnsResponseVO message = this.makeMessage(list);
|
||||
if (!(EnsErrCd.OK.equals(message.getErrCode()) || null == message.getErrCode()))
|
||||
throw new EnsException(message.getErrCode(), message.getErrMsg());
|
||||
jsonStr = String.valueOf(message.getResultInfo());
|
||||
|
||||
|
||||
|
||||
ResponseEntity<String> resp = kkoMydocApi.bulkStatus(orgMng.getKkoMdAccessToken(), orgMng.getKkoMdContractUuid(), jsonStr);
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("\n==============================================================================")
|
||||
.append("\n[ Kakao Mydoc - StatFetch ]")
|
||||
.append("\n### Request Info...")
|
||||
.append("\n" + jsonStr)
|
||||
.append("\n### Response Info...")
|
||||
.append("\n" + resp.getBody())
|
||||
.append("\n==============================================================================");
|
||||
log.debug(sb.toString());
|
||||
}
|
||||
|
||||
sendRespBody = resp.getBody();
|
||||
if (resp.getStatusCode() != HttpStatus.OK)
|
||||
throw new EnsException(EnsErrCd.RSLT620, String.format("문서상태조회 중.. %s %s", resp.getStatusCode().toString(), resp.getBody()));
|
||||
EnsResponseVO mResponse = this.respMsgToMap(resp.getBody());
|
||||
if (!EnsErrCd.OK.equals(mResponse.getErrCode()))
|
||||
throw new EnsException(mResponse.getErrCode(), mResponse.getErrMsg());
|
||||
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) mResponse.getResultInfo()).get("documents");
|
||||
|
||||
|
||||
|
||||
Map<String, KkoMydocApiRespVO> mApiRespVOByDocumentBinderUuid = documents.stream()
|
||||
.map(row -> this.toApiRespVOMap(row))
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoMydocApiRespVO) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
list.stream().forEach(row -> this.modifyStatInfoByDocumentBinderUuid(row, mApiRespVOByDocumentBinderUuid));
|
||||
|
||||
} catch (EnsException e) {
|
||||
|
||||
list.stream()
|
||||
.forEach(row -> row.setError(FieldError.initBuilder()
|
||||
.errorCode(e.getErrCd().getCode())
|
||||
.errorMessage(e.getMessage())
|
||||
.build())
|
||||
);
|
||||
} catch (Exception e) {
|
||||
|
||||
list.stream()
|
||||
.forEach(row -> row.setError(FieldError.initBuilder()
|
||||
.errorCode(EnsErrCd.RSLT500.getCode())
|
||||
.errorMessage(e.getMessage())
|
||||
.build())
|
||||
);
|
||||
} finally {
|
||||
if (!CmmnUtil.isEmpty(jsonStr))
|
||||
sendDetailKkoMydocStatHistRepository.saveAll(this.toSendDetailStatHist(list, sendRespBody));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
respVO = EnsResponseVO.okBuilder().resultInfo(resultInfo).build();
|
||||
} catch (EnsException e) {
|
||||
|
||||
respVO = EnsResponseVO.errRsltBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).resultInfo(resultInfo).build();
|
||||
} catch (Exception e) {
|
||||
|
||||
respVO = EnsResponseVO.errRsltBuilder().errCode(EnsErrCd.RSLT500).errMsg(e.getMessage()).resultInfo(resultInfo).build();
|
||||
} finally {
|
||||
if (!CmmnUtil.isEmpty(sendMast))
|
||||
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
sendMast.setError(FieldError.initBuilder().build());
|
||||
|
||||
|
||||
Integer readCnt = sendDetails.stream()
|
||||
.map(row -> KkoMydocStatusCd.READ.equals(row.getKkoDocStat()) ? 1 : 0)
|
||||
.reduce(Integer::sum)
|
||||
.orElseGet(() -> 0);
|
||||
sendMast.setReadCnt(readCnt);
|
||||
|
||||
if (StatCd.sendok.equals(sendMast.getStatCd())) {
|
||||
if (readCnt > 0)
|
||||
sendMast.setStatCd(StatCd.open);
|
||||
else
|
||||
sendMast.setStatCd(StatCd.sendcmplt);
|
||||
} else if (StatCd.sendcmplt.equals(sendMast.getStatCd())) {
|
||||
if (readCnt > 0)
|
||||
sendMast.setStatCd(StatCd.open);
|
||||
}
|
||||
} else {
|
||||
sendMast.setError(FieldError.initBuilder()
|
||||
.errorCode(respVO.getErrCode().getCode())
|
||||
.errorMessage(respVO.getErrMsg())
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
applicationEventPublisher.publishEvent(SendMastStatUpdateEvent.builder().sendMastId(sendMastId).build());
|
||||
}
|
||||
|
||||
|
||||
return respVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 문서상태조회API body Message로 변환하여 반환 한다.
|
||||
*
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
private EnsResponseVO makeMessage(List<SendDetailKkoMydoc> list) {
|
||||
String result = null;
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
EnsResponseVO resp = null;
|
||||
try {
|
||||
|
||||
List<String> documentBinderUuids = list.stream()
|
||||
.map(row -> row.getDocumentBinderUuid())
|
||||
.collect(Collectors.toList());
|
||||
Map<String, Object> mJson = new HashMap<>();
|
||||
mJson.put("document_binder_uuids", documentBinderUuids);
|
||||
|
||||
|
||||
result = gson.toJson(mJson);
|
||||
|
||||
resp = EnsResponseVO.okBuilder()
|
||||
.resultInfo(result)
|
||||
.build();
|
||||
} catch (EnsException e) {
|
||||
resp = EnsResponseVO.errBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
resp = EnsResponseVO.errBuilder()
|
||||
.errCode(EnsErrCd.RSLT502)
|
||||
.errMsg(String.format("요청 메시지 생성 중 오류 발생. %s", e.getMessage()))
|
||||
.build();
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 문서상태조회 응답결과를 API응답VO 객체에 매핑하여 반환
|
||||
*
|
||||
* @param row
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> toApiRespVOMap(Map<String, Object> row) {
|
||||
KkoMydocApiRespVO kkoMydocApiRespVO = KkoMydocApiRespVO.builder()
|
||||
.error_code(row.containsKey("error_code") ? String.valueOf(row.get("error_code")) : null)
|
||||
.error_message(row.containsKey("error_message") ? String.valueOf(row.get("error_message")) : null)
|
||||
.data(row.containsKey("status_data") ? row.get("status_data") : new HashMap<>())
|
||||
.build();
|
||||
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("key", row.get("document_binder_uuid"));
|
||||
m.put("value", kkoMydocApiRespVO);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 문서상태조회결과 갱신(update)
|
||||
* -. 성공/실패 여부에 따라 상태정보 및 Error 필드 갱신
|
||||
*
|
||||
* @param row
|
||||
* @param mMydocApiRespVOByDocumentBinderUuid
|
||||
*/
|
||||
private void modifyStatInfoByDocumentBinderUuid(SendDetailKkoMydoc row, Map<String, KkoMydocApiRespVO> mMydocApiRespVOByDocumentBinderUuid) {
|
||||
KkoMydocApiRespVO apiRespVO = mMydocApiRespVOByDocumentBinderUuid.get(row.getDocumentBinderUuid());
|
||||
if (CmmnUtil.isEmpty(apiRespVO.getError_code())) {
|
||||
Map<String, Object> statusData = (Map<String, Object>) apiRespVO.getData();
|
||||
|
||||
String docBoxStatus = statusData.containsKey("doc_box_status") ? (String) statusData.get("doc_box_status") : null;
|
||||
Long docBoxSentAt = statusData.containsKey("doc_box_sent_at") ? (Long) statusData.get("doc_box_sent_at") : null;
|
||||
Long docBoxReceivedAt = statusData.containsKey("doc_box_received_at") ? (Long) statusData.get("doc_box_received_at") : null;
|
||||
Long authenticatedAt = statusData.containsKey("authenticated_at") ? (Long) statusData.get("authenticated_at") : null;
|
||||
Long tokenUsedAt = statusData.containsKey("token_used_at") ? (Long) statusData.get("token_used_at") : null;
|
||||
Long docBoxReadAt = statusData.containsKey("doc_box_read_at") ? (Long) statusData.get("doc_box_read_at") : null;
|
||||
Long userNotifiedAt = statusData.containsKey("user_notified_at") ? (Long) statusData.get("user_notified_at") : null;
|
||||
|
||||
row.setKkoDocStat(CmmnUtil.isEmpty(docBoxStatus) ? row.getKkoDocStat() : KkoMydocStatusCd.valueOfEnum(docBoxStatus));
|
||||
row.setKkoDocSentDt(CmmnUtil.isEmpty(row.getKkoDocSentDt()) ? DateUtil.absTimeSecToDate(docBoxSentAt, "yyyyMMddHHmmss") : row.getKkoDocSentDt());
|
||||
row.setKkoDocReceivedDt(CmmnUtil.isEmpty(row.getKkoDocReceivedDt()) ? DateUtil.absTimeSecToDate(docBoxReceivedAt, "yyyyMMddHHmmss") : row.getKkoDocReceivedDt());
|
||||
row.setKkoDocAuthFrstDt(CmmnUtil.isEmpty(row.getKkoDocAuthFrstDt()) ? DateUtil.absTimeSecToDate(authenticatedAt, "yyyyMMddHHmmss") : row.getKkoDocAuthFrstDt());
|
||||
row.setKkoDocTokenVrfyFrstDt(CmmnUtil.isEmpty(row.getKkoDocTokenVrfyFrstDt()) ? DateUtil.absTimeSecToDate(tokenUsedAt, "yyyyMMddHHmmss") : row.getKkoDocTokenVrfyFrstDt());
|
||||
row.setKkoDocReadFrstDt(CmmnUtil.isEmpty(row.getKkoDocReadFrstDt()) ? DateUtil.absTimeSecToDate(docBoxReadAt, "yyyyMMddHHmmss") : row.getKkoDocReadFrstDt());
|
||||
row.setKkoDocUserNotiedDt(CmmnUtil.isEmpty(row.getKkoDocUserNotiedDt()) ? DateUtil.absTimeSecToDate(userNotifiedAt, "yyyyMMddHHmmss") : row.getKkoDocUserNotiedDt());
|
||||
|
||||
row.setError(FieldError.initBuilder().build());
|
||||
} else {
|
||||
if ("NOT_FOUND".equals(apiRespVO.getError_code()) && "documentBinder를 찾을 수 없습니다.".equals(apiRespVO.getError_message()))
|
||||
row.setKkoDocStat(KkoMydocStatusCd.INTERNAL_SENT_ERR);
|
||||
|
||||
row.setError(FieldError.initBuilder()
|
||||
.errorCode(EnsErrCd.RSLT630.getCode())
|
||||
.errorMessage(String.format("%s %s", apiRespVO.getError_code(), apiRespVO.getError_message()))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 문서상태조회 응답을 전송요청이력 Entity 데이터로 변환하여 반환 한다.
|
||||
*
|
||||
* @param list
|
||||
* @param respMsg
|
||||
* @return
|
||||
*/
|
||||
private List<SendDetailKkoMydocStatHist> toSendDetailStatHist(List<SendDetailKkoMydoc> list, String respMsg) {
|
||||
|
||||
// Map<String, KkoMydocApiRespVO> mMydocApiRespVOByExtDocUuid =
|
||||
|
||||
EnsResponseVO respVO = this.respMsgToMap(respMsg);
|
||||
|
||||
|
||||
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
|
||||
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) respVO.getResultInfo()).get("documents");
|
||||
Map<String, KkoMydocApiRespVO> mRespVOByExtDocUuid = documents.stream()
|
||||
.map(row -> this.toApiRespVOMap(row))
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoMydocApiRespVO) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
|
||||
return list.stream()
|
||||
.map(row -> {
|
||||
KkoMydocApiRespVO apiRespVO = mRespVOByExtDocUuid.get(row.getDocumentBinderUuid());
|
||||
Map<String, Object> statusData = (Map<String, Object>) apiRespVO.getData();
|
||||
return SendDetailKkoMydocStatHist.builder()
|
||||
.sendDetailId(row.getSendDetailId())
|
||||
.documentBinderUuid(row.getDocumentBinderUuid())
|
||||
.externalDocumentUuid(row.getPropExternalDocumentUuid())
|
||||
// .respRawMsg(gson.toJson(statusData))
|
||||
.docBoxStatus(statusData.containsKey("doc_box_status") ? (String) statusData.get("doc_box_status") : null)
|
||||
.docBoxSentAt(statusData.containsKey("doc_box_sent_at") ? (Long) statusData.get("doc_box_sent_at") : null)
|
||||
.docBoxReceivedAt(statusData.containsKey("doc_box_received_at") ? (Long) statusData.get("doc_box_received_at") : null)
|
||||
.authenticatedAt(statusData.containsKey("authenticated_at") ? (Long) statusData.get("authenticated_at") : null)
|
||||
.tokenUsedAt(statusData.containsKey("token_used_at") ? (Long) statusData.get("token_used_at") : null)
|
||||
.docBoxReadAt(statusData.containsKey("doc_box_read_at") ? (Long) statusData.get("doc_box_read_at") : null)
|
||||
.userNotifiedAt(statusData.containsKey("user_notified_at") ? (Long) statusData.get("user_notified_at") : null)
|
||||
.docDistributionReceivedAt(statusData.containsKey("doc_distribution_received_at") ? (Long) statusData.get("doc_distribution_received_at") : null)
|
||||
.payload(statusData.containsKey("payload") ? (String) statusData.get("payload") : null)
|
||||
.error(FieldError.initBuilder()
|
||||
.errorCode(apiRespVO.getError_code())
|
||||
.errorMessage(apiRespVO.getError_message())
|
||||
.build())
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} else {
|
||||
return list.stream()
|
||||
.map(row -> {
|
||||
return SendDetailKkoMydocStatHist.builder()
|
||||
.sendDetailId(row.getSendDetailId())
|
||||
.documentBinderUuid(row.getDocumentBinderUuid())
|
||||
.externalDocumentUuid(row.getPropExternalDocumentUuid())
|
||||
.error(FieldError.initBuilder()
|
||||
.errorCode(respVO.getErrCode().getCode())
|
||||
.errorMessage(respVO.getErrMsg())
|
||||
.build())
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private EnsResponseVO respMsgToMap(String respMsg) {
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).serializeNulls().create();
|
||||
EnsErrCd errCode = EnsErrCd.OK;
|
||||
String errMsg = EnsErrCd.OK.getCodeNm();
|
||||
Map<String, Object> mResp = null;
|
||||
try {
|
||||
mResp = gson.fromJson(respMsg, Map.class);
|
||||
if (CmmnUtil.isEmpty(mResp.get("documents")))
|
||||
throw new EnsException(EnsErrCd.RSLT620, String.format("문서상태조회API 오류. documents 키값이 없습니다. %s", respMsg));
|
||||
} catch (EnsException e) {
|
||||
errCode = e.getErrCd();
|
||||
errMsg = e.getMessage();
|
||||
} catch (Exception e) {
|
||||
errCode = EnsErrCd.RSLT511;
|
||||
errMsg = String.format("문서상태조회API 응답 데이터 JSON 객체 변환 실패. %s", respMsg);
|
||||
}
|
||||
return EnsErrCd.OK.equals(errCode) ?
|
||||
EnsResponseVO.okBuilder().resultInfo(mResp).build()
|
||||
: EnsResponseVO.errBuilder()
|
||||
.errCode(errCode)
|
||||
.errMsg(errMsg)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.support;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.modules.common.biztmplt.EnsPhaseProcSupport;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydoc;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.KkoMydocRsltRespDTO;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.config.KkoMydocStat;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkRsltProvider implements EnsPhaseProcSupport<EnsResponseVO, Long> {
|
||||
|
||||
private final SendMastRepository sendMastRepository;
|
||||
private final SendDetailKkoMydocRepository sendDetailKkoMydocRepository;
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO statReady(List<Long> args) {
|
||||
log.info("no process");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO statBegin(Long arg) {
|
||||
log.info("no process");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO execute(Long sendMastId) {
|
||||
try {
|
||||
SendMast sendMast = sendMastRepository.findById(sendMastId)
|
||||
.orElseThrow(() -> new EnsException(EnsErrCd.PRVD404, String.format("일치하는 발송마스터 자료가 없습니다. [ sendMastId %s ]", sendMastId)));
|
||||
List<SendDetailKkoMydoc> sendDetailKkoMydocs = sendDetailKkoMydocRepository.findAllBySendMast(sendMast);
|
||||
|
||||
|
||||
KkoMydocRsltRespDTO respDTO = KkoMydocRsltRespDTO.builder()
|
||||
.sendMastId(sendMast.getSendMastId())
|
||||
.statCd(sendMast.getStatCd())
|
||||
.orgCd(sendMast.getOrgCd())
|
||||
.tmpltCd(sendMast.getTmpltCd())
|
||||
.postBundleTitle(sendMast.getPostBundleTitle())
|
||||
.sendDt(sendMast.getSendDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
|
||||
.closeDt(sendMast.getCloseDt().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")))
|
||||
.closeAt(this.getCloseAt(sendMast))
|
||||
.documents(sendDetailKkoMydocs.stream()
|
||||
.map(row -> KkoMydocStat.builder()
|
||||
.sendDetailId(row.getSendDetailId())
|
||||
.externalDocumentUuid(row.getPropExternalDocumentUuid())
|
||||
.documentBinderUuid(row.getDocumentBinderUuid())
|
||||
.kkoDocStat(row.getKkoDocStat())
|
||||
.kkoDocSentDt(row.getKkoDocSentDt())
|
||||
.kkoDocReceivedDt(row.getKkoDocReceivedDt())
|
||||
.kkoDocAuthFrstDt(row.getKkoDocAuthFrstDt())
|
||||
.kkoDocTokenVrfyFrstDt(row.getKkoDocTokenVrfyFrstDt())
|
||||
.kkoDocReadFrstDt(row.getKkoDocReadFrstDt())
|
||||
.kkoDocUserNotiedDt(row.getKkoDocUserNotiedDt())
|
||||
.errorCode(CmmnUtil.isEmpty(row.getError()) ? null : row.getError().getErrorCode())
|
||||
.errorMessage(CmmnUtil.isEmpty(row.getError()) ? null : row.getError().getErrorMessage())
|
||||
.build())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
|
||||
return EnsResponseVO.okBuilder().resultInfo(respDTO).build();
|
||||
} catch (EnsException e) {
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(e.getErrCd())
|
||||
.errMsg(e.getMessage())
|
||||
.resultInfo(KkoMydocRsltRespDTO.builder()
|
||||
.sendMastId(sendMastId)
|
||||
.build())
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return EnsResponseVO.errRsltBuilder()
|
||||
.errCode(EnsErrCd.ERR999)
|
||||
.errMsg(String.format("전송결과 응답 처리 실패. 실패사유: %s", e.getMessage()))
|
||||
.resultInfo(KkoMydocRsltRespDTO.builder()
|
||||
.sendMastId(sendMastId)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean getCloseAt(SendMast sendMast) {
|
||||
if (StatCd.close.equals(sendMast.getStatCd()))
|
||||
return true;
|
||||
else if (StatCd.sendfail.equals(sendMast.getStatCd()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,427 @@
|
||||
package cokr.xit.ens.modules.kkotalk.service.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import cokr.xit.ens.core.aop.EnsResponseVO;
|
||||
import cokr.xit.ens.core.exception.EnsException;
|
||||
import cokr.xit.ens.core.exception.code.EnsErrCd;
|
||||
import cokr.xit.ens.core.monitor.slack.event.MonitorEvent;
|
||||
import cokr.xit.ens.core.utils.CmmnUtil;
|
||||
import cokr.xit.ens.core.utils.MapDeserailizer;
|
||||
import cokr.xit.ens.modules.common.biztmplt.SendProcTemplate;
|
||||
import cokr.xit.ens.modules.common.code.PostSeCd;
|
||||
import cokr.xit.ens.modules.common.code.StatCd;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
|
||||
import cokr.xit.ens.modules.common.ctgy.sys.mng.service.OrgMngService;
|
||||
import cokr.xit.ens.modules.common.domain.SendMast;
|
||||
import cokr.xit.ens.modules.common.domain.repository.SendMastRepository;
|
||||
import cokr.xit.ens.modules.common.domain.support.FieldError;
|
||||
import cokr.xit.ens.modules.common.event.SendMastStatUpdateEvent;
|
||||
import cokr.xit.ens.modules.common.monitor.MessageByPhase;
|
||||
import cokr.xit.ens.modules.kkomydoc.code.KkoMydocStatusCd;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydoc;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.SendDetailKkoMydocReqHist;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.domain.repository.SendDetailKkoMydocReqHistRepository;
|
||||
import cokr.xit.ens.modules.kkomydoc.model.KkoMydocApiRespVO;
|
||||
import cokr.xit.ens.modules.kkomydoc.service.support.KkoMydocApiSpec;
|
||||
import cokr.xit.ens.modules.kkotalk.mapper.IKkoTalkMapper;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkApiDTO;
|
||||
import cokr.xit.ens.modules.kkotalk.model.KkotalkDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
// FIXME: 카카오톡 신규 추가
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class KkoTalkSender extends SendProcTemplate {
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
private final SendMastRepository sendMastRepository;
|
||||
private final SendDetailKkoMydocRepository sendDetailKkoMydocRepository;
|
||||
private final IKkoTalkMapper talkMapper;
|
||||
private final SendDetailKkoMydocReqHistRepository sendDetailKkoMydocReqHistRepository;
|
||||
private final OrgMngService orgMngService;
|
||||
private final KkoMydocApiSpec kkoMydocApi;
|
||||
private final IKkoTalkApiService kkoTalkApi;
|
||||
@Value("${contract.kakao.pay.mydoc.api.bulksend-batch-unit}")
|
||||
private int SEND_BATCH_UNIT;
|
||||
|
||||
private Gson gson = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserailizer()).disableHtmlEscaping().create();
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public EnsResponseVO execute(Long sendMastId) {
|
||||
|
||||
SendMast sendMast = null;
|
||||
List<KkotalkDTO.SendDetailKkoTalkDTO> sendDetails = null;
|
||||
EnsResponseVO respVO = null;
|
||||
try {
|
||||
if (CmmnUtil.isEmpty(sendMastId))
|
||||
throw new EnsException(EnsErrCd.SEND410, "발송마스터ID(은)는 필수조건 입니다.");
|
||||
|
||||
sendMast = sendMastRepository.findById(sendMastId).orElseThrow(() -> new EnsException(EnsErrCd.SEND404, String.format("일치하는 발송마스터 자료가 없습니다. [ sendMastId %s ]", sendMastId)));
|
||||
sendDetails = talkMapper.findAllFetchBySendMastId(sendMast.getSendMastId());
|
||||
//sendDetails = sendDetailKkoMydocRepository.findAllFetchBySendMastId(sendMast.getSendMastId());
|
||||
OrgMng orgMng = orgMngService.find(sendMast.getOrgCd()).getResultInfo();
|
||||
|
||||
|
||||
Lists.partition(sendDetails, SEND_BATCH_UNIT).stream()
|
||||
.forEach(list -> {
|
||||
|
||||
String sendRespBody = null;
|
||||
String jsonStr = null;
|
||||
try {
|
||||
|
||||
List<KkotalkApiDTO.Envelope> envelopes = this.makeMessage(list);
|
||||
KkotalkDTO.BulkSendResponse resp = kkoTalkApi.requestSendBulk(
|
||||
KkotalkDTO.BulkSendRequest.builder()
|
||||
.envelopes(envelopes)
|
||||
.signguCode(orgMng.getOrgCd())
|
||||
.ffnlgCode("11")
|
||||
|
||||
.build()
|
||||
);
|
||||
|
||||
/*
|
||||
EnsResponseVO message = this.makeMessage(list);
|
||||
if (!(EnsErrCd.OK.equals(message.getErrCode()) || null == message.getErrCode()))
|
||||
throw new EnsException(message.getErrCode(), message.getErrMsg());
|
||||
jsonStr = String.valueOf(message.getResultInfo());
|
||||
|
||||
ResponseEntity<String> resp = kkoMydocApi.bulkSend(orgMng.getKkoMdAccessToken(), orgMng.getKkoMdContractUuid(), jsonStr);
|
||||
if (log.isDebugEnabled()) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("\n==============================================================================")
|
||||
.append("\n[ Kakao Mydoc - Sending ]")
|
||||
.append("\n### Request Info...")
|
||||
.append("\n" + jsonStr)
|
||||
.append("\n### Response Info...")
|
||||
.append("\n" + resp.getBody())
|
||||
.append("\n==============================================================================");
|
||||
log.debug(sb.toString());
|
||||
}
|
||||
|
||||
sendRespBody = resp.getBody();
|
||||
if (resp.getStatusCode() != HttpStatus.OK)
|
||||
throw new EnsException(EnsErrCd.SEND620, String.format("전송요청 중.. %s %s", resp.getStatusCode().toString(), resp.getBody()));
|
||||
EnsResponseVO mResponse = this.respMsgToMap(resp.getBody());
|
||||
if (!EnsErrCd.OK.equals(mResponse.getErrCode()))
|
||||
throw new EnsException(mResponse.getErrCode(), mResponse.getErrMsg());
|
||||
List<Map<String, Object>> documents = (List<Map<String, Object>>) ((Map<String, Object>) mResponse.getResultInfo()).get("documents");
|
||||
|
||||
|
||||
|
||||
|
||||
Map<String, KkoMydocApiRespVO> mApiRespVOByExtDocUuid = documents.stream()
|
||||
.map(row -> this.toApiRespVOMap(row))
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (KkoMydocApiRespVO) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
list.stream()
|
||||
.forEach(row -> this.modifyDocSendRsltByExtDocUuid(row, mApiRespVOByExtDocUuid));
|
||||
|
||||
|
||||
|
||||
} catch (EnsException e) {
|
||||
|
||||
list.stream()
|
||||
.forEach(row -> {
|
||||
row.set(KkoMydocStatusCd.SENT_FAIL);
|
||||
row.setError(FieldError.initBuilder()
|
||||
.errorCode(e.getErrCd().getCode())
|
||||
.errorMessage(e.getMessage())
|
||||
.build());
|
||||
});
|
||||
} catch (Exception e) {
|
||||
|
||||
list.stream()
|
||||
.forEach(row -> {
|
||||
row.setKkoDocStat(KkoMydocStatusCd.SENT_FAIL);
|
||||
row.setError(FieldError.initBuilder()
|
||||
.errorCode(EnsErrCd.SEND500.getCode())
|
||||
.errorMessage(e.getMessage())
|
||||
.build());
|
||||
});
|
||||
*/
|
||||
} finally {
|
||||
// if (!CmmnUtil.isEmpty(jsonStr))
|
||||
// sendDetailKkoMydocReqHistRepository.saveAll(this.toSendDetailReqHist(list, jsonStr, sendRespBody));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
Optional<Integer> cntSuccess = sendDetails.stream()
|
||||
.map(row -> CmmnUtil.isEmpty(row.getErrorCode()) ? 1 : 0)
|
||||
.reduce(Integer::sum);
|
||||
if (cntSuccess.get() > 0)
|
||||
respVO = EnsResponseVO.okBuilder()
|
||||
.resultInfo(sendDetails.stream()
|
||||
// .map(row -> this.toResultInfo(row))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
else
|
||||
throw new EnsException(EnsErrCd.SEND500, String.format("전체건수 전송 실패(총 %d 건)", sendDetails.size()));
|
||||
|
||||
} catch (EnsException e) {
|
||||
|
||||
respVO = EnsResponseVO.errBuilder().errCode(e.getErrCd()).errMsg(e.getMessage()).build();
|
||||
} catch (Exception e) {
|
||||
|
||||
respVO = EnsResponseVO.errBuilder().errCode(EnsErrCd.SEND500).errMsg(e.getMessage()).build();
|
||||
} finally {
|
||||
if (!CmmnUtil.isEmpty(sendMast)) {
|
||||
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
sendMast.setStatCd(StatCd.sendok);
|
||||
sendMast.setError(FieldError.initBuilder().build());
|
||||
} else {
|
||||
sendMast.setStatCd(StatCd.sendfail);
|
||||
sendMast.setError(FieldError.initBuilder()
|
||||
.errorCode(respVO.getErrCode().getCode())
|
||||
.errorMessage(respVO.getErrMsg())
|
||||
.build());
|
||||
|
||||
applicationEventPublisher.publishEvent(MonitorEvent.builder()
|
||||
.message(MessageByPhase.builder()
|
||||
.oClass(getClass().getSimpleName() + "." + new Throwable().getStackTrace()[0].getMethodName())
|
||||
.postSeCd(PostSeCd.kkoMydoc)
|
||||
.statCd(StatCd.sendfail)
|
||||
.errCd(respVO.getErrCode())
|
||||
.message("-.SendMastId: " + sendMastId + "\n" + respVO.getErrMsg())
|
||||
.build())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
// if (respVO != null && EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
// applicationEventPublisher.publishEvent(KkoMydocSentEvent.builder().sendMastId(sendMastId).build());
|
||||
// } else {
|
||||
applicationEventPublisher.publishEvent(SendMastStatUpdateEvent.builder().sendMastId(sendMastId).build());
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
return respVO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 전송요청API body Message로 변환하여 반환 한다.
|
||||
*
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
private List<KkotalkApiDTO.Envelope> makeMessage(List<KkotalkDTO.SendDetailKkoTalkDTO> list) {
|
||||
final List<KkotalkApiDTO.Envelope> bulkList = new ArrayList<>();
|
||||
|
||||
for (KkotalkDTO.SendDetailKkoTalkDTO sendTgtDTO : list) {
|
||||
|
||||
KkotalkApiDTO.Envelope bulkReqDTO = null;
|
||||
if (StringUtils.isNotEmpty(sendTgtDTO.getCi())) {
|
||||
bulkReqDTO = KkotalkApiDTO.Envelope.builder()
|
||||
.ci(sendTgtDTO.getCi())
|
||||
.build();
|
||||
} else {
|
||||
bulkReqDTO = KkotalkApiDTO.Envelope.builder()
|
||||
.build();
|
||||
}
|
||||
|
||||
final KkotalkApiDTO.Content content = KkotalkApiDTO.Content.builder()
|
||||
.link(sendTgtDTO.getLink())
|
||||
.build();
|
||||
|
||||
bulkReqDTO.setExternalId(sendTgtDTO.getSendDetailId().toString());
|
||||
bulkReqDTO.setTitle(sendTgtDTO.getTitle());
|
||||
bulkReqDTO.setPayload(sendTgtDTO.getPayload());
|
||||
bulkReqDTO.setReadExpiresAt(sendTgtDTO.getReadExpiresAt());
|
||||
bulkReqDTO.setReviewExpiresAt(sendTgtDTO.getReviewExpiresAt());
|
||||
bulkReqDTO.setHash(sendTgtDTO.getHash());
|
||||
bulkReqDTO.setGuide(sendTgtDTO.getGuide());
|
||||
bulkReqDTO.setContent(content);
|
||||
|
||||
bulkList.add(bulkReqDTO);
|
||||
}
|
||||
return bulkList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 전송요청 응답결과를 API응답VO 객체에 매핑하여 반환
|
||||
*
|
||||
* @param row
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> toApiRespVOMap(Map<String, Object> row) {
|
||||
KkoMydocApiRespVO apiRespVO = KkoMydocApiRespVO.builder()
|
||||
.error_code(row.containsKey("error_code") ? String.valueOf(row.get("error_code")) : null)
|
||||
.error_message(row.containsKey("error_message") ? String.valueOf(row.get("error_message")) : null)
|
||||
.data(row.containsKey("document_binder_uuid") ? String.valueOf(row.get("document_binder_uuid")) : null)
|
||||
.build();
|
||||
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("key", row.get("external_document_uuid"));
|
||||
m.put("value", apiRespVO);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* 전송요청결과 갱신(update)
|
||||
* -. 성공/실패 여부에 따라 문서식별번호(document_binder_uuid) 및 Error 필드 갱신
|
||||
*
|
||||
* @param row
|
||||
* @param mApiRespVOByExtDocUuid
|
||||
*/
|
||||
private void modifyDocSendRsltByExtDocUuid(SendDetailKkoMydoc row, Map<String, KkoMydocApiRespVO> mApiRespVOByExtDocUuid) {
|
||||
KkoMydocApiRespVO apiRespVO = mApiRespVOByExtDocUuid.get(row.getPropExternalDocumentUuid());
|
||||
if (CmmnUtil.isEmpty(apiRespVO.getError_code())) {
|
||||
row.setKkoDocStat(KkoMydocStatusCd.SENT);
|
||||
row.setDocumentBinderUuid(String.valueOf(apiRespVO.getData()));
|
||||
row.setError(FieldError.initBuilder().build());
|
||||
} else {
|
||||
row.setKkoDocStat(KkoMydocStatusCd.valueOfEnum(apiRespVO.getError_code()));
|
||||
row.setError(FieldError.initBuilder()
|
||||
.errorCode(EnsErrCd.SEND630.getCode())
|
||||
.errorMessage(String.format("%s %s", apiRespVO.getError_code(), apiRespVO.getError_message()))
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> toResultInfo(SendDetailKkoMydoc row) {
|
||||
Map<String, String> m = new HashMap<>();
|
||||
// m.put("msgIdx", row.getMsgIdx());
|
||||
m.put("documentBinderUuid", row.getDocumentBinderUuid());
|
||||
m.put("externalDocumentUuid", row.getPropExternalDocumentUuid());
|
||||
if (!CmmnUtil.isEmpty(row.getError())) {
|
||||
m.put("errCd", row.getError().getErrorCode());
|
||||
m.put("errMsg", row.getError().getErrorMessage());
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 전송요청응답을 전송요청이력 Entity 데이터로 변환하여 반환 한다.
|
||||
*
|
||||
* @param sendMsg
|
||||
* @param respMsg
|
||||
* @return
|
||||
*/
|
||||
private List<SendDetailKkoMydocReqHist> toSendDetailReqHist(List<SendDetailKkoMydoc> list, String sendMsg, String respMsg) {
|
||||
|
||||
|
||||
List<Map<String, Object>> sendMsgList = (List<Map<String, Object>>) gson.fromJson(sendMsg, Map.class).get("documents");
|
||||
Map<String, Long> mSendDetailIds = list.stream()
|
||||
.map(row -> {
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("key", row.getPropExternalDocumentUuid());
|
||||
m.put("value", row.getSendDetailId());
|
||||
return m;
|
||||
})
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (Long) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
EnsResponseVO respVO = this.respMsgToMap(respMsg);
|
||||
|
||||
|
||||
if (EnsErrCd.OK.equals(respVO.getErrCode())) {
|
||||
Map<String, Object> mRespBody = (Map<String, Object>) respVO.getResultInfo();
|
||||
List<Map<String, String>> documents = (List<Map<String, String>>) mRespBody.get("documents");
|
||||
Map<String, Map<String, String>> mRespMsg = documents.stream()
|
||||
.map(row -> {
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
m.put("key", String.valueOf(row.get("external_document_uuid")));
|
||||
Map<String, String> mValue = new HashMap<>();
|
||||
mValue.put("document_binder_uuid", row.get("document_binder_uuid"));
|
||||
mValue.put("error_code", row.get("error_code"));
|
||||
mValue.put("error_message", row.get("error_message"));
|
||||
mValue.put("rawMsg", gson.toJson(row));
|
||||
m.put("value", mValue);
|
||||
return m;
|
||||
})
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> (Map<String, String>) m.get("value"), (k1, k2) -> k1));
|
||||
|
||||
return sendMsgList.stream()
|
||||
.map(row -> {
|
||||
Map<String, String> property = (Map<String, String>) row.get("property");
|
||||
String externalDocumentUuid = property.get("external_document_uuid");
|
||||
boolean isSuccess = CmmnUtil.isEmpty(mRespMsg.get(externalDocumentUuid).get("error_code"));
|
||||
|
||||
return SendDetailKkoMydocReqHist.builder()
|
||||
.sendDetailId(mSendDetailIds.get(externalDocumentUuid))
|
||||
.sendRawMsg(gson.toJson(row))
|
||||
.externalDocumentUuid(externalDocumentUuid)
|
||||
.documentBinderUuid(mRespMsg.get(externalDocumentUuid).get("document_binder_uuid"))
|
||||
.respRawMsg(mRespMsg.get(externalDocumentUuid).get("rawMsg"))
|
||||
.error(FieldError.initBuilder()
|
||||
.errorCode(isSuccess ? null : EnsErrCd.SEND620.getCode())
|
||||
.errorMessage(isSuccess ? null : String.format("%s %s"
|
||||
, mRespMsg.get(externalDocumentUuid).get("error_code")
|
||||
, mRespMsg.get(externalDocumentUuid).get("error_message")
|
||||
))
|
||||
.build())
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} else {
|
||||
return sendMsgList.stream()
|
||||
.map(row -> {
|
||||
Map<String, String> property = (Map<String, String>) row.get("property");
|
||||
String externalDocumentUuid = property.get("external_document_uuid");
|
||||
return SendDetailKkoMydocReqHist.builder()
|
||||
.sendDetailId(mSendDetailIds.get(externalDocumentUuid))
|
||||
.sendRawMsg(gson.toJson(row))
|
||||
.externalDocumentUuid(externalDocumentUuid)
|
||||
.respRawMsg(respMsg)
|
||||
.error(FieldError.initBuilder()
|
||||
.errorCode(respVO.getErrCode().getCode())
|
||||
.errorMessage(respVO.getErrMsg())
|
||||
.build())
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
private EnsResponseVO respMsgToMap(String respMsg) {
|
||||
EnsErrCd errCode = EnsErrCd.OK;
|
||||
String errMsg = EnsErrCd.OK.getCodeNm();
|
||||
Map<String, Object> mResp = null;
|
||||
try {
|
||||
mResp = gson.fromJson(respMsg, Map.class);
|
||||
if (CmmnUtil.isEmpty(mResp.get("documents")))
|
||||
throw new EnsException(EnsErrCd.SEND620, String.format("전송요청API 오류. documents 키값이 없습니다. %s", respMsg));
|
||||
} catch (EnsException e) {
|
||||
errCode = e.getErrCd();
|
||||
errMsg = e.getMessage();
|
||||
} catch (Exception e) {
|
||||
errCode = EnsErrCd.SEND511;
|
||||
errMsg = String.format("전송요청API 응답데이터 JSON 객체 변환 실패. %s", respMsg);
|
||||
}
|
||||
return EnsErrCd.OK.equals(errCode) ?
|
||||
EnsResponseVO.okBuilder().resultInfo(mResp).build()
|
||||
: EnsResponseVO.errBuilder()
|
||||
.errCode(errCode)
|
||||
.errMsg(errMsg)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cokr.xit.ens.modules.kkotalk.mapper.IKkoTalkMapper">
|
||||
<!-- // FIXME: 카카오톡 신규 추가 -->
|
||||
<!-- =================================================================================== -->
|
||||
<!-- ================================ accept =========================================== -->
|
||||
<!-- =================================================================================== -->
|
||||
<insert id="saveSndDtlKkoTalk" parameterType="cokr.xit.ens.modules.kkotalk.model.KkotalkDTO$SendDetailKkoTalkDTO">
|
||||
/** iup-kkotalk-mapper|saveSndDtlKkoTalk-카카오톡발송상세생성|julim */
|
||||
INSERT INTO ens_snd_dtl_kko_talk (
|
||||
send_detail_id,
|
||||
title,
|
||||
link,
|
||||
hash,
|
||||
guide,
|
||||
payload,
|
||||
read_expires_at,
|
||||
review_expires_at,
|
||||
use_non_personalized_noti,
|
||||
ci,
|
||||
phone_number,
|
||||
name,
|
||||
birthday,
|
||||
external_id,
|
||||
error_code,
|
||||
error_message,
|
||||
bill_uid,
|
||||
send_mast_id,
|
||||
regist_dt
|
||||
) VALUES (
|
||||
#{sendDetailId},
|
||||
#{title},
|
||||
#{link},
|
||||
#{hash},
|
||||
#{guide},
|
||||
#{payload},
|
||||
#{readExpiresAt},
|
||||
#{reviewExpiresAt},
|
||||
#{useNonPersonalizedNoti},
|
||||
#{ci},
|
||||
#{phoneNumber},
|
||||
#{name},
|
||||
#{birthday},
|
||||
#{externalId},
|
||||
#{errorCode},
|
||||
#{errorMessage},
|
||||
#{billUid},
|
||||
#{sendMastId},
|
||||
sysdate
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="findAllBySendMastId" parameterType="string" resultType="cokr.xit.ens.modules.kkotalk.model.KkotalkDTO$SendDetailKkoTalkDTO">
|
||||
/** iup-kkotalk-mapper|findAllBySendMastId-카카오톡발송대상 조회|julim */
|
||||
SELECT send_detail_id,
|
||||
title,
|
||||
link,
|
||||
hash,
|
||||
guide,
|
||||
payload,
|
||||
read_expires_at,
|
||||
review_expires_at,
|
||||
use_non_personalized_noti,
|
||||
ci,
|
||||
phone_number,
|
||||
name,
|
||||
birthday,
|
||||
external_id,
|
||||
error_code,
|
||||
error_message,
|
||||
bill_uid,
|
||||
send_mast_id,
|
||||
regist_dt
|
||||
FROM ens_snd_dtl_kko_talk
|
||||
WHERE send_mast_id = #{sendMastId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
|
||||
<configuration>
|
||||
<!--
|
||||
cacheEnabled 설정에서 각 mapper 에 설정된 캐시를 전역적으로 사용할지 말지에 대한 여부 true | false true
|
||||
lazyLoadingEnabled 늦은 로딩을 사용할지에 대한 여부. 사용하지 않는다면 모두 즉시 로딩할 것이다. 이 값은 fetchType 속성을 사용해서 대체할 수 있다. true | false false
|
||||
aggressiveLazyLoading 활성화 상태로 두게 되면 늦은(lazy) 로딩 프로퍼티를 가진 객체는 호출에 따라 로드될 것이다. 반면에 개별 프로퍼티는 요청할때 로드된다. true | false true
|
||||
multipleResultSetsEnabled 한개의 구문에서 여러개의 ResultSet 을 허용할지의 여부(드라이버가 해당 기능을 지원해야 함) true | false true
|
||||
useColumnLabel 칼럼명 대신에 칼럼라벨을 사용. 드라이버마다 조금 다르게 작동한다. 문서와 간단한 테스트를 통해 실제 기대하는 것처럼 작동하는지 확인해야 한다. true | false true
|
||||
useGeneratedKeys 생성키에 대한 JDBC 지원을 허용. 지원하는 드라이버가 필요하다. true 로 설정하면 생성키를 강제로 생성한다. 일부 드라이버(예를들면, Derby)에서는 이 설정을 무시한다. true | false False
|
||||
autoMappingBehavior MyBatis 가 칼럼을 필드/프로퍼티에 자동으로 매핑할지와 방법에 대해 명시. PARTIAL 은 간단한 자동매핑만 할뿐, 내포된 결과에 대해서는 처리하지 않는다. FULL 은 처리가능한 모든 자동매핑을 처리한다. NONE, PARTIAL, FULL PARTIAL
|
||||
defaultExecutorType 디폴트 실행자(executor) 설정. SIMPLE 실행자는 특별히 하는 것이 없다. REUSE 실행자는 PreparedStatement 를 재사용한다. BATCH 실행자는 구문을 재사용하고 수정을 배치처리한다. SIMPLE REUSE BATCH SIMPLE
|
||||
defaultStatementTimeout 데이터베이스로의 응답을 얼마나 오래 기다릴지를 판단하는 타임아웃을 셋팅 양수 셋팅되지 않음(null)
|
||||
safeRowBoundsEnabled 중첩구문내 RowBound 사용을 허용 true | false False
|
||||
mapUnderscoreToCamelCase 전통적인 데이터베이스 칼럼명 형태인 A_COLUMN을 CamelCase형태의 자바 프로퍼티명 형태인 aColumn으로 자동으로 매핑하도록 함 true | false False
|
||||
localCacheScope 마이바티스는 순환참조를 막거나 반복된 쿼리의 속도를 높히기 위해 로컬캐시를 사용한다. 디폴트 설정인 SESSION을 사용해서 동일 세션의 모든 쿼리를 캐시한다. localCacheScope=STATEMENT 로 설정하면 로컬 세션은 구문 실행할때만 사용하고 같은 SqlSession에서 두개의 다른 호출사이에는 데이터를 공유하지 않는다. SESSION | STATEMENT SESSION
|
||||
jdbcTypeForNull JDBC타입을 파라미터에 제공하지 않을때 null값을 처리한 JDBC타입을 명시한다. 일부 드라이버는 칼럼의 JDBC타입을 정의하도록 요구하지만 대부분은 NULL, VARCHAR 나 OTHER 처럼 일반적인 값을 사용해서 동작한다. JdbcType 이늄. 대부분은 NULL, VARCHAR 나 OTHER 를 공통적으로 사용한다. OTHER
|
||||
lazyLoadTriggerMethods 늦은 로딩을 야기하는 객체의 메소드를 명시 메소드 이름을 나열하고 여러개일 경우 콤마(,) 로 구분 equals,clone,hashCode,toString
|
||||
defaultScriptingLanguage 동적으로 SQL을 만들기 위해 기본적으로 사용하는 언어를 명시 타입별칭이나 패키지 경로를 포함한 클래스명 org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
|
||||
callSettersOnNulls 가져온 값이 null일때 setter나 맵의 put 메소드를 호출할지를 명시 Map.keySet() 이나 null값을 초기화할때 유용하다. int, boolean 등과 같은 원시타입은 null을 셋팅할 수 없다는 점은 알아두면 좋다. true | false false
|
||||
logPrefix 마이바티스가 로거(logger) 이름에 추가할 접두사 문자열을 명시 문자열 셋팅하지 않음
|
||||
logImpl 마이바티스가 사용할 로깅 구현체를 명시 이 설정을 사용하지 않으면 마이바티스가 사용할 로깅 구현체를 자동으로 찾는다. SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 셋팅하지 않음
|
||||
proxyFactory 마이바티스가 늦은 로딩을 처리할 객체를 생성할 때 사용할 프록시 툴을 명시 CGLIB | JAVASSIST CGLIB
|
||||
-->
|
||||
<settings>
|
||||
<!--
|
||||
Settings 설정 옵션 사이트 참조
|
||||
-.사이트주소: https://postitforhooney.tistory.com/entry/MyBatisSetting-Mybatis%EC%97%90%EC%84%9C-%ED%95%84%EC%9A%94%ED%95%9C-%EB%B6%80%EB%B6%84%EB%93%A4-setting%EC%9E%90%EB%A3%8C
|
||||
-->
|
||||
<setting name="mapUnderscoreToCamelCase" value="true"/>
|
||||
<setting name="cacheEnabled" value="true" />
|
||||
<setting name="jdbcTypeForNull" value="VARCHAR" /><!-- NULL / VARCHAR / OTHER-->
|
||||
<setting name="callSettersOnNulls" value="true"/> <!-- resultType으로 Map Collection 지정 시 value가 null일 떄 컬럼 누락문제 해결을 위한 설정 -->
|
||||
|
||||
<setting name="lazyLoadingEnabled" value="false" />
|
||||
<setting name="multipleResultSetsEnabled" value="true" />
|
||||
<setting name="useColumnLabel" value="true" />
|
||||
<setting name="useGeneratedKeys" value="false" />
|
||||
<setting name="autoMappingBehavior" value="PARTIAL" /><!-- NONE / PARTIAL / FULL-->
|
||||
<setting name="defaultExecutorType" value="SIMPLE" /><!-- SIMPLE / REUSE / BATCH-->
|
||||
<setting name="defaultStatementTimeout" value="25" />
|
||||
<setting name="safeRowBoundsEnabled" value="false" />
|
||||
<setting name="localCacheScope" value="SESSION" /><!-- SESSION / STATEMENT-->
|
||||
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
|
||||
<setting name="aggressiveLazyLoading" value="true" />
|
||||
</settings>
|
||||
|
||||
<!-- Type Aliases 설정-->
|
||||
<!-- <typeAliases>-->
|
||||
<!-- <typeAlias alias="egovMap" type="org.egovframe.rte.psl.dataaccess.util.EgovMap" />-->
|
||||
<!-- <typeAlias alias="ComDefaultCodeVO" type="egovframework.com.cmm.model.ComDefaultCodeVO" />-->
|
||||
<!-- <typeAlias alias="comDefaultVO" type="egovframework.com.cmm.model.ComDefaultVO" />-->
|
||||
<!-- </typeAliases>-->
|
||||
|
||||
</configuration>
|
Loading…
Reference in New Issue