# TaRecordsStatusManualServiceImpl.java

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

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.JsonUtils;
    import cloud.wconnect.finance.cons.ta.TaRecordsStatusEnum;
    import cloud.wconnect.finance.entity.ta.TaCreditCard;
    import cloud.wconnect.finance.entity.ta.TaPortal;
    import cloud.wconnect.finance.entity.ta.TaRecordNotes;
    import cloud.wconnect.finance.entity.ta.TaRecordsStatus;
    import cloud.wconnect.finance.pojo.dto.ta.TaPortalJsonDTO;
    import cloud.wconnect.finance.pojo.dto.ta.manualrecords.TaCreditCardManualDTO;
    import cloud.wconnect.finance.pojo.dto.ta.manualrecords.TaPortalManualDTO;
    import cloud.wconnect.finance.pojo.dto.ta.manualrecords.TaRecordsStatusManualDTO;
    import cloud.wconnect.finance.pojo.dto.ta.manualrecords.TaTbaManualDTO;
    import cloud.wconnect.finance.service.ta.*;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import jakarta.annotation.Resource;
    import jakarta.validation.Valid;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Objects;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;

    /**
     * <p>
     * 服务实现类
     * </p>
     *
     * @author zc
     * @since 2023-07-14
     */
    @Service
    @DS("finance")
    public class TaRecordsStatusManualServiceImpl implements ITaRecordsStatusManualService {
        @Resource
        private ITaCreditCardService creditCardService;
        @Resource
        private ITaPortalService portalService;
        @Resource
        private ITaRecordsStatusService recordsStatusService;
        @Resource
        private ITaRecordNotesService recordNotesService;
        @Resource
        private BeanMapper beanMapper;
        @Resource
        private ObjectMapper objectMapper;

        /**
         * 获取手动创建的数据详情
         *
         * @param taRecordsStatus TaRecordsStatus 数据
         * @return TaRecordsStatusManualDTO
         * @author zc
         * @date 2023/7/14
         */
        @Override
        public TaRecordsStatusManualDTO getDetails(TaRecordsStatus taRecordsStatus) {
            TaRecordsStatusManualDTO taRecordsStatusManual = new TaRecordsStatusManualDTO();
            taRecordsStatusManual.setId(taRecordsStatus.getId());
            taRecordsStatusManual.setAirline(taRecordsStatus.getAirline());

            // 组装 Credit Card
            List<Long> creditCardIds = Stream.of(StringUtils.split(taRecordsStatus.getOIds(), ","))
                    .map(Long::parseLong).toList();
            List<TaCreditCard> creditCardList = creditCardService.listByIds(creditCardIds);
            taRecordsStatusManual.setCreditCardList(beanMapper.mapList(creditCardList, TaCreditCardManualDTO.class,
                    (creditCard, dto) -> dto.setLastFourDigits(creditCard.getCardNo())));

            if (taRecordsStatus.getStatus().equals(TaRecordsStatusEnum.MATCHED.getCode())) {
                // 组装 Portal
                TaPortal portal = portalService.getById(taRecordsStatus.getPId());
                TaPortalJsonDTO taPortalJsonDTO = JsonUtils.convertStringToObject(objectMapper,
                        portal.getDetails(), TaPortalJsonDTO.class);
                taRecordsStatusManual.setPortal(beanMapper.map(portal, TaPortalManualDTO.class, item -> {
                    item.setAirline(taPortalJsonDTO.getAirline());
                    item.setDepartureDate(taPortalJsonDTO.getDepartDate());
                    item.setVoucher(taPortalJsonDTO.getVoucher());
                    item.setCustomerNumber(taPortalJsonDTO.getCustomerNumber());
                    item.setLastFourDigits(portal.getCardNo());
                }));
            } else {
                // 组装 Airline
                taRecordsStatusManual.setTba(TaTbaManualDTO.builder()
                        .airline(taRecordsStatus.getAirline()).build());
            }
            return taRecordsStatusManual;
        }

        /**
         * 新增数据
         *
         * @param propertyId               资产 id
         * @param userId                   用户 id
         * @param taRecordsStatusManualDTO 新增数据
         * @return id
         * @author zc
         * @date 2023/7/14
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public long add(int propertyId, int userId, TaRecordsStatusManualDTO taRecordsStatusManualDTO) {
            TaRecordsStatus taRecordsStatus = new TaRecordsStatus();

            TaPortalManualDTO portal = taRecordsStatusManualDTO.getPortal();
            List<TaCreditCardManualDTO> creditCardList = taRecordsStatusManualDTO.getCreditCardList();
            if (Objects.nonNull(portal)) {
                // 组装数据
                packageTaPortal(portal, taRecordsStatus);

                // 保存 Portal
                long portalId = portalService.addManual(propertyId, portal);
                taRecordsStatus.setPId(portalId);
            } else {
                TaCreditCardManualDTO creditCard = creditCardList.stream().min(Comparator.comparing(TaCreditCardManualDTO::getArrivalDate)).get();
                // 组装数据
                packageTaTba(taRecordsStatusManualDTO.getTba(), creditCard, taRecordsStatus);
            }

            // 保存 CreditCard
            List<Long> creditCardIds = creditCardService.addManual(propertyId, creditCardList);

            // 组装数据
            taRecordsStatus.setPropertyId(propertyId);
            taRecordsStatus.setOIds(StringUtils.join(creditCardIds, ","));
            taRecordsStatus.setStatusDetail(StringUtils.EMPTY);
            taRecordsStatus.setCategory(TaRecordsStatus.CATEGORY_OTHER);
            taRecordsStatus.setCreateId(userId);
            taRecordsStatus.setOperatorId(BaseConstant.ZERO);
            taRecordsStatus.setUpdateTime(DateTimeUtils.nowTimestamp());
            taRecordsStatus.setRoomsNo(creditCardList.stream().map(TaCreditCardManualDTO::getRoomNo).collect(Collectors.joining(",")));
            taRecordsStatus.setType(TaRecordsStatus.PLATFORM_TYPE_TA);
            taRecordsStatus.setCanChoose(Boolean.FALSE);
            taRecordsStatus.setConfirmation(StringUtils.EMPTY);
            recordsStatusService.save(taRecordsStatus);

            return taRecordsStatus.getId();
        }

        /**
         * 更新数据
         *
         * @param propertyId               资产 id
         * @param userId                   用户 id
         * @param originTaRecordsStatus    原数据
         * @param taRecordsStatusManualDTO 更新数据
         * @author zc
         * @date 2023/7/14
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void update(int propertyId, int userId, TaRecordsStatus originTaRecordsStatus,
                           TaRecordsStatusManualDTO taRecordsStatusManualDTO) {
            TaRecordsStatus taRecordsStatus = new TaRecordsStatus();

            // 原数据有 portalId，则需要删除该 Portal 数据
            if (originTaRecordsStatus.getPId() > BaseConstant.LONG_ZERO) {
                portalService.removeById(originTaRecordsStatus.getPId());
            }
            TaPortalManualDTO portal = taRecordsStatusManualDTO.getPortal();
            List<TaCreditCardManualDTO> taCreditCardManualList = taRecordsStatusManualDTO.getCreditCardList();
            if (Objects.nonNull(portal)) {
                // 组装数据
                packageTaPortal(portal, taRecordsStatus);
                // 保存 Portal
                long portalId = portalService.addManual(propertyId, portal);
                taRecordsStatus.setPId(portalId);
            } else {
                TaCreditCardManualDTO creditCard = taCreditCardManualList.stream().min(Comparator.comparing(TaCreditCardManualDTO::getArrivalDate)).get();
                // 组装数据
                packageTaTba(taRecordsStatusManualDTO.getTba(), creditCard, taRecordsStatus);
            }

            // 先删除之前关联的 PMS Credit Card，再重新保存 PMS Credit Card
            List<Long> originCreditCardIds = Stream.of(StringUtils.split(originTaRecordsStatus.getOIds(), ","))
                    .map(Long::parseLong).toList();
            creditCardService.removeByIds(originCreditCardIds);
            List<Long> creditCardIds = creditCardService.addManual(propertyId, taCreditCardManualList);

            // 组装数据
            taRecordsStatus.setId(originTaRecordsStatus.getId());
            taRecordsStatus.setOIds(StringUtils.join(creditCardIds, ","));
            taRecordsStatus.setCreateId(userId);
            taRecordsStatus.setUpdateTime(DateTimeUtils.nowTimestamp());
            taRecordsStatus.setRoomsNo(taCreditCardManualList.stream().map(TaCreditCardManualDTO::getRoomNo).collect(Collectors.joining(",")));
            recordsStatusService.updateById(taRecordsStatus);
        }

        /**
         * 组装 TaRecordStatus 数据 by Portal
         *
         * @param portal          Portal
         * @param taRecordsStatus 组装对象
         * @author zc
         * @date 2023/7/14
         */
        private void packageTaPortal(@Valid TaPortalManualDTO portal,
                                     TaRecordsStatus taRecordsStatus) {
            taRecordsStatus.setStatus(TaRecordsStatusEnum.MATCHED.getCode());
            taRecordsStatus.setArrivalDate(portal.getArrivalDate());
            taRecordsStatus.setName(portal.getName());
            taRecordsStatus.setAirline(portal.getAirline());
            taRecordsStatus.setCardNo(portal.getLastFourDigits());
        }

        /**
         * 组装 TaRecordStatus 数据 by TBA
         *
         * @param tba             TBA
         * @param creditCard      CreditCard
         * @param taRecordsStatus 组装对象
         * @author zc
         * @date 2023/7/14
         */
        private void packageTaTba(@Valid TaTbaManualDTO tba,
                                  TaCreditCardManualDTO creditCard,
                                  TaRecordsStatus taRecordsStatus) {
            taRecordsStatus.setPId(BaseConstant.LONG_ZERO);
            taRecordsStatus.setStatus(TaRecordsStatusEnum.TBA.getCode());
            taRecordsStatus.setArrivalDate(creditCard.getArrivalDate());
            taRecordsStatus.setName(creditCard.getName());
            taRecordsStatus.setAirline(tba.getAirline());
            taRecordsStatus.setCardNo(creditCard.getLastFourDigits());
        }

        /**
         * 删除手动创建的数据
         *
         * @param taRecordsStatus 原数据
         * @author zc
         * @date 2023/7/14
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void remove(TaRecordsStatus taRecordsStatus) {
            // 删除关联的 ta credit card
            List<Long> taCreditCardIds = Stream.of(StringUtils.split(taRecordsStatus.getOIds(), ","))
                    .map(Long::parseLong).toList();
            creditCardService.removeByIds(taCreditCardIds);

            // 删除关联的 ta portal
            portalService.removeById(taRecordsStatus.getPId());

            // 删除 ta records status
            recordsStatusService.removeById(taRecordsStatus.getId());

            // 删除 ta records note
            recordNotesService.remove(new QueryWrapper<TaRecordNotes>().lambda()
                    .eq(TaRecordNotes::getRId, taRecordsStatus.getId()));
        }
    }