# LogbookNotificationController.java

    package cloud.wconnect.frontoffice.controller.logbook;

    import cloud.wconnect.commonlib.annotation.ApiId;
    import cloud.wconnect.commonlib.component.SessionContext;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.UserDTO;
    import cloud.wconnect.commonlib.pojo.dto.UsergroupDTO;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.service.UsergroupInternalService;
    import cloud.wconnect.frontoffice.entity.logbook.LogbookCategory;
    import cloud.wconnect.frontoffice.entity.logbook.LogbookNotification;
    import cloud.wconnect.frontoffice.pojo.dto.logbook.LogbookNotificationDTO;
    import cloud.wconnect.frontoffice.pojo.dto.logbook.LogbookNotificationTargetDTO;
    import cloud.wconnect.frontoffice.pojo.query.logbook.LogbookNotificationQuery;
    import cloud.wconnect.frontoffice.service.logbook.ILogbookCategoryService;
    import cloud.wconnect.frontoffice.service.logbook.ILogbookNotificationService;
    import com.google.common.collect.ImmutableMap;
    import com.google.common.collect.Lists;
    import jakarta.validation.Valid;
    import org.apache.commons.collections.CollectionUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;

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

    /**
     * 控制层：Logbook Notification
     *
     * @author yyt
     * 2023/3/22
     */
    @RestController
    @RequestMapping("/logbook/notification")
    public class LogbookNotificationController {

        @Autowired
        private ILogbookNotificationService logbookNotificationService;
        @Autowired
        private ILogbookCategoryService logbookCategoryService;
        @Autowired
        private SessionContext sessionContext;
        @Autowired
        private UsergroupInternalService usergroupInternalService;
        @Autowired
        private UserInternalService userInternalService;

        /**
         * 获取通知列表
         *
         * @param logbookNotificationQuery 查询条件
         * @return 通知列表
         * @author yyt
         * @date 2023/3/22
         */
        @ApiId(151)
        @GetMapping
        public ListPagedDTO<LogbookNotificationDTO> listNotification(@Valid LogbookNotificationQuery logbookNotificationQuery) {
            return logbookNotificationService.listNotificationDTO(sessionContext.getPropertyId(logbookNotificationQuery.getProperty()), logbookNotificationQuery);
        }

        /**
         * 新增、修改通知
         *
         * @param id              通知 id
         * @param property        资产标识
         * @param notificationDTO 配置内容
         * @return 通知 id
         * @author yyt
         * @date 2023/3/22
         */
        @ApiId(152)
        @PostMapping("/{id:\\d+}")
        public Map saveNotification(@PathVariable("id") int id, @RequestParam String property,
                                    @Valid @RequestBody LogbookNotificationDTO notificationDTO) {
            int propertyId = sessionContext.getPropertyId(property);
            LogbookCategory category = logbookCategoryService.checkExist(notificationDTO.getCategory());
            if (!category.getPropertyId().equals(propertyId)) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(), "the property id parameter is different from " +
                        "the property id of the logbookCategory;propertyId:" + propertyId + ",logbookCategoryPropertyId:" +
                        category.getPropertyId() + ",logbookCategoryId:" + category.getId());
            }

            // 检查目标（用户/用户组）是否存在
            checkTargetExist(propertyId, notificationDTO.getUsers());

            if (id == 0) {
                id = logbookNotificationService.saveNotification(propertyId, notificationDTO, sessionContext.getLoginUserId());
            } else {
                LogbookNotification logbookNotification = logbookNotificationService.checkExist(id);

                checkPropertySame(logbookNotification, propertyId);

                logbookNotificationService.updateNotification(logbookNotification, notificationDTO, sessionContext.getLoginUserId());
            }

            return ImmutableMap.of("id", id);
        }

        /**
         * 检查目标（用户/用户组）是否存在
         *
         * @param propertyId 资产 id
         * @param users      目标
         * @author yyt
         * @date 2024/3/12
         **/
        private void checkTargetExist(Integer propertyId, List<LogbookNotificationTargetDTO> users) {
            if (CollectionUtils.isEmpty(users)) {
                return;
            }
            List<Integer> userIds = Lists.newArrayList();
            List<Integer> userGroupIds = Lists.newArrayList();
            Map<Integer, List<Integer>> targetIdByUserSource = users.stream().collect(Collectors.groupingBy(LogbookNotificationTargetDTO::getSource,
                    Collectors.collectingAndThen(Collectors.toList(), item -> item.stream().map(LogbookNotificationTargetDTO::getIdentityId).toList())));
            userIds.addAll(targetIdByUserSource.getOrDefault(EmailConfigCons.SOURCE_USER, Collections.emptyList()));
            userGroupIds.addAll(targetIdByUserSource.getOrDefault(EmailConfigCons.SOURCE_USERGROUP, Collections.emptyList()));

            Integer tenantId = sessionContext.getTenantSymbolBO().getId();
            if (CollectionUtils.isNotEmpty(userIds)) {
                List<UserDTO> userDTOs = userInternalService.getUsers(tenantId, userIds);
                if (userDTOs.size() != userIds.size()) {
                    throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the user is not found");
                }
            }
            if (CollectionUtils.isNotEmpty(userGroupIds)) {
                List<UsergroupDTO> usergroups = usergroupInternalService.getUsergroups(tenantId, propertyId, userGroupIds);
                if (usergroups.size() != userGroupIds.size()) {
                    throw new BadRequestException(CommonErrorI18nConstant.DATA_NOT_FOUND,
                            BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "the userGroup is not found");
                }
            }
        }

        /**
         * 校验 logbook notification property 与 参数 property 一致
         *
         * @param logbookNotification logbook notification
         * @param paramPropertyId     参数 property
         * @author yyt
         * @date 2023/3/21
         */
        private void checkPropertySame(LogbookNotification logbookNotification, int paramPropertyId) {
            if (logbookNotification.getPropertyId() != paramPropertyId) {
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(), "the property id parameter is different from " +
                        "the property id of the logbookNotification;propertyId:" + paramPropertyId + ",logbookNotificationPropertyId:" +
                        logbookNotification.getPropertyId() + ",logbookNotificationId:" + logbookNotification.getId());
            }
        }

        /**
         * 删除通知
         *
         * @param id       通知 id
         * @param property 资产标识
         * @return {}
         * @author yyt
         * @date 2023/3/22
         */
        @ApiId(153)
        @DeleteMapping("/{id:\\d+}")
        public Map deleteNotification(@PathVariable("id") int id, @RequestParam String property) {
            LogbookNotification logbookNotification = logbookNotificationService.checkExist(id);

            checkPropertySame(logbookNotification, sessionContext.getPropertyId(property));

            logbookNotificationService.deleteNotification(id);

            return Collections.emptyMap();
        }

    }