# CbAdjSenderServiceImpl.java

    package cloud.wconnect.finance.service.chargeback.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.MoudleEventSubjectEnum;
    import cloud.wconnect.commonlib.cons.OperationAdjCons;
    import cloud.wconnect.commonlib.pojo.bo.adj.chargeback.ChargebackAdjBO;
    import cloud.wconnect.commonlib.pojo.bo.adj.chargeback.ChargebackAdjCommentBO;
    import cloud.wconnect.commonlib.pojo.bo.adj.chargeback.ChargebackBatchAdjBO;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.finance.entity.chargeback.CbAdj;
    import cloud.wconnect.finance.entity.chargeback.CbAdjComment;
    import cloud.wconnect.finance.entity.chargeback.CbCase;
    import cloud.wconnect.finance.service.chargeback.ICbAdjCommentService;
    import cloud.wconnect.finance.service.chargeback.ICbAdjSenderService;
    import cloud.wconnect.sns.http.processor.Sender;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;
    import software.amazon.awssdk.services.sns.model.PublishResponse;

    import java.util.Collections;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;

    /**
     * Cb Adj Sender实现类
     *
     * @author lichen
     * @date 2026/2/9
     */
    @Service
    @DS("finance")
    @Slf4j
    public class CbAdjSenderServiceImpl implements ICbAdjSenderService {

        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private Sender moduleEventSender;
        @Autowired
        @Lazy
        private ICbAdjCommentService cbAdjCommentService;

        /**
         * 保存调账数据时，发送事件
         *
         * @param cs        case 信息
         * @param cbAdjList cb adj数据
         * @author lichen
         * @date 2026/2/9
         */
        @Override
        public void handleSentSaveAdjEvent(CbCase cs, List<CbAdj> cbAdjList) {
            if (CollectionUtils.isEmpty(cbAdjList)) return;

            handleDataChangeAdjEvent(cs, cbAdjList, OperationAdjCons.SAVE);
        }

        /**
         * 绑定调账数据时，发送事件
         *
         * @param cs        case 信息
         * @param cbAdjList cb adj数据
         * @author lichen
         * @date 2026/2/9
         */
        @Override
        public void handleSentBindAdjEvent(CbCase cs, List<CbAdj> cbAdjList) {
            if (CollectionUtils.isEmpty(cbAdjList)) return;

            handleDataChangeAdjEvent(cs, cbAdjList, OperationAdjCons.BIND);
        }

        /**
         * 解绑调账数据时，发送事件
         *
         * @param cs               case 信息
         * @param unbindAdjNumbers 解绑adj编号
         * @author lichen
         * @date 2026/2/9
         */
        @Override
        public void handleSentUnbindAdjEvent(CbCase cs, List<String> unbindAdjNumbers) {
            if (CollectionUtils.isEmpty(unbindAdjNumbers)) {
                return;
            }
            handleStatusChangeAdjEvent(cs.getPropertyId(), unbindAdjNumbers, OperationAdjCons.UNBIND);
        }

        /**
         * 删除调账数据时，发送事件
         *
         * @param cs     case 信息
         * @param cbAdjs cb adj数据
         * @author lichen
         * @date 2026/2/10
         */
        @Override
        public void handleSentDeleteAdjEvent(CbCase cs, List<CbAdj> cbAdjs) {
            if (CollectionUtils.isEmpty(cbAdjs)) {
                return;
            }
            Map<Boolean, List<CbAdj>> isBindCbAdjs = cbAdjs.stream().collect(Collectors.partitioningBy(item -> item.getType() == CbAdj.TYPE_BIND));

            // 绑定的 adj数据，发送解绑消息
            List<String> bindAdjNumbers = isBindCbAdjs.getOrDefault(true, Collections.emptyList())
                    .stream().map(CbAdj::getAdjNumber).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(bindAdjNumbers)){
                handleStatusChangeAdjEvent(cs.getPropertyId(), bindAdjNumbers, OperationAdjCons.UNBIND);
            }

            // 手动创建的adj数据，发送删除消息
            List<String> manualCreateAdjNumbers = isBindCbAdjs.getOrDefault(false, Collections.emptyList())
                    .stream().map(CbAdj::getAdjNumber).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(manualCreateAdjNumbers)){
                handleStatusChangeAdjEvent(cs.getPropertyId(), manualCreateAdjNumbers, OperationAdjCons.DELETE);
            }
        }

        /**
         * 维护评论时，发送事件
         *
         * @param cbAdj adj数据
         * @author lichen
         * @date 2026/2/10
         */
        @Override
        public void handleSentAdjCommentEvent(CbAdj cbAdj) {
            ChargebackAdjBO chargebackAdjBO = new ChargebackAdjBO();
            chargebackAdjBO.setAdjNumber(cbAdj.getAdjNumber());
            // 备注
            List<CbAdjComment> comments = cbAdjCommentService.listByCbAdjIds(Collections.singletonList(cbAdj.getId()));
            chargebackAdjBO.setComments(beanMapper.mapList(comments, ChargebackAdjCommentBO.class));

            ChargebackBatchAdjBO chargebackBatchAdjBO = new ChargebackBatchAdjBO(OperationAdjCons.COMMENT, cbAdj.getPropertyId(), Collections.singletonList(chargebackAdjBO));
            String msg = JsonUtils.convertObjToString(objectMapper, chargebackBatchAdjBO);
            PublishResponse response = moduleEventSender.publish(MoudleEventSubjectEnum.CHARGEBACK_ADJ.getSubject(), msg);
            log.info("Chargeback send adj comment,msgId:{}, body:{}", response.messageId(), msg);
        }

        /**
         * 审批通过调账数据时，发送事件
         *
         * @param cbCase case 信息
         * @param cbAdjs adj数据
         * @author lichen
         * @date 2026/2/10
         */
        @Override
        public void handleSentApprovedAdjEvent(CbCase cbCase, List<CbAdj> cbAdjs) {
            if (CollectionUtils.isEmpty(cbAdjs)) {
                return;
            }
            List<String> adjNumbers = cbAdjs.stream().map(CbAdj::getAdjNumber).collect(Collectors.toList());
            handleStatusChangeAdjEvent(cbCase.getPropertyId(), adjNumbers, OperationAdjCons.APPROVED);
        }

        /**
         * 状态变更时发送调账事件，绑定、解绑、删除、审批通过
         *
         * @param propertyId    资产id
         * @param adjNumbers    adj编号集合
         * @param operationType 操作类型
         * @author lichen
         * @date 2026/2/10
         */
        private void handleStatusChangeAdjEvent(int propertyId, List<String> adjNumbers, int operationType) {
            List<ChargebackAdjBO> chargebackAdjBOS = adjNumbers.stream().map(adjNumber -> {
                ChargebackAdjBO chargebackAdjBO = new ChargebackAdjBO();
                chargebackAdjBO.setAdjNumber(adjNumber);
                return chargebackAdjBO;
            }).collect(Collectors.toList());

            ChargebackBatchAdjBO chargebackBatchAdjBO = new ChargebackBatchAdjBO(operationType, propertyId, chargebackAdjBOS);
            String msg = JsonUtils.convertObjToString(objectMapper, chargebackBatchAdjBO);
            PublishResponse response = moduleEventSender.publish(MoudleEventSubjectEnum.CHARGEBACK_ADJ.getSubject(), msg);
            log.info("Chargeback send adj, operationType:{}, msgId:{}, body:{}", operationType, response.messageId(), msg);
        }

        /**
         * 数据变更时发送调账事件，绑定、保存
         *
         * @param cs            case 信息
         * @param cbAdjList     cb adj数据
         * @param operationType 操作类型
         * @author lichen
         * @date 2026/2/10
         */
        private void handleDataChangeAdjEvent(CbCase cs, List<CbAdj> cbAdjList, int operationType) {
            Integer propertyId = cs.getPropertyId();
            String caseNumber = cs.getCaseNumber();

            List<ChargebackAdjBO> chargebackAdjBOS = beanMapper.mapList(cbAdjList, ChargebackAdjBO.class, (entity, bo) -> {
                bo.setRequestType(OperationAdjCons.REQUEST_TYPE_CHARGEBACK);
                bo.setAdjustedDollar(entity.getDisputeAmount());
                bo.setCbAdjId(entity.getId());
                bo.setCaseNumber(caseNumber);
                bo.setDutyUser(entity.getRequestedBy());
            });

            ChargebackBatchAdjBO chargebackBatchAdjBO = new ChargebackBatchAdjBO(operationType, propertyId, chargebackAdjBOS);
            String msg = JsonUtils.convertObjToString(objectMapper, chargebackBatchAdjBO);
            PublishResponse response = moduleEventSender.publish(MoudleEventSubjectEnum.CHARGEBACK_ADJ.getSubject(), msg);
            log.info("Chargeback send adj, operationType:{}, msgId:{}, body:{}", operationType, response.messageId(), msg);
        }

    }