feat: add job seeker notice settings API
This commit is contained in:
64
docs/mobile-notice-settings-api.md
Normal file
64
docs/mobile-notice-settings-api.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# 移动端消息接收设置接口
|
||||
|
||||
## 通用约定
|
||||
|
||||
- 基础地址:沿用移动端当前后端地址。
|
||||
- 请求头:`Authorization: Bearer <移动端求职者登录 Token>`。
|
||||
- 仅移动端**求职者**可调用;未携带或失效 Token 返回 HTTP 401,企业及其他角色返回业务码 `403`。
|
||||
- 四个字段均为布尔值,`true` 表示接收该类消息,`false` 表示不接收。保存时必须一次传齐四项。
|
||||
|
||||
## 查看设置
|
||||
|
||||
`GET /app/notice/settings`
|
||||
|
||||
无需请求参数或请求体。首次查看(尚未保存过)会返回四项均开启的默认设置,且不会创建数据库记录。
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"jobUpdateEnabled": true,
|
||||
"appointmentReminderEnabled": true,
|
||||
"systemNotificationEnabled": true,
|
||||
"interviewNotificationEnabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
| 字段 | 对应按钮 |
|
||||
| --- | --- |
|
||||
| `jobUpdateEnabled` | 职位上新 |
|
||||
| `appointmentReminderEnabled` | 预约提醒 |
|
||||
| `systemNotificationEnabled` | 系统通知 |
|
||||
| `interviewNotificationEnabled` | 面试通知 |
|
||||
|
||||
## 保存设置
|
||||
|
||||
`PUT /app/notice/settings`
|
||||
|
||||
请求头 `Content-Type: application/json`,请求体示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"jobUpdateEnabled": true,
|
||||
"appointmentReminderEnabled": false,
|
||||
"systemNotificationEnabled": true,
|
||||
"interviewNotificationEnabled": false
|
||||
}
|
||||
```
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功"
|
||||
}
|
||||
```
|
||||
|
||||
接口按登录 Token 自动识别当前用户,不接收也不允许客户端传入用户 ID。任一开关字段缺失或为 `null` 时,返回参数校验错误。
|
||||
@@ -2,16 +2,27 @@ package com.ruoyi.cms.controller.app;
|
||||
|
||||
import com.ruoyi.cms.domain.Job;
|
||||
import com.ruoyi.cms.domain.Notice;
|
||||
import com.ruoyi.cms.domain.dto.NoticeSettingRequest;
|
||||
import com.ruoyi.cms.domain.vo.NoticeSettingVO;
|
||||
import com.ruoyi.cms.service.IAppNoticeService;
|
||||
import com.ruoyi.cms.service.IAppUserNoticeSettingService;
|
||||
import com.ruoyi.common.annotation.BussinessLog;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginSiteUser;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.cms.util.StringUtil;
|
||||
import com.ruoyi.common.utils.SiteSecurityUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@@ -21,6 +32,35 @@ public class AppNoticeInfoController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IAppNoticeService appNoticeService;
|
||||
@Autowired
|
||||
private IAppUserNoticeSettingService appUserNoticeSettingService;
|
||||
|
||||
@ApiOperation("查看消息接收设置")
|
||||
@GetMapping("/settings")
|
||||
public AjaxResult getSettings()
|
||||
{
|
||||
Long userId = currentJobSeekerId();
|
||||
if (userId == null)
|
||||
{
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "仅求职者可查看消息接收设置");
|
||||
}
|
||||
NoticeSettingVO settings = appUserNoticeSettingService.getSettings(userId);
|
||||
return AjaxResult.success(settings);
|
||||
}
|
||||
|
||||
@ApiOperation("保存消息接收设置")
|
||||
@PutMapping("/settings")
|
||||
@BussinessLog(title = "保存消息接收设置")
|
||||
public AjaxResult saveSettings(@Validated @RequestBody NoticeSettingRequest request)
|
||||
{
|
||||
Long userId = currentJobSeekerId();
|
||||
if (userId == null)
|
||||
{
|
||||
return AjaxResult.error(HttpStatus.FORBIDDEN, "仅求职者可保存消息接收设置");
|
||||
}
|
||||
appUserNoticeSettingService.saveSettings(userId, request);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
@ApiOperation("消息列表")
|
||||
@GetMapping("/info")
|
||||
public AjaxResult listNotRead(@RequestParam(required = false) Integer isRead)
|
||||
@@ -60,4 +100,24 @@ public class AppNoticeInfoController extends BaseController {
|
||||
List<Notice> list = appNoticeService.sysNoticeList();
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅允许经移动端 Token 认证的求职者读写自己的设置。
|
||||
*/
|
||||
private Long currentJobSeekerId()
|
||||
{
|
||||
Authentication authentication = SiteSecurityUtils.getAuthentication();
|
||||
if (authentication == null || !(authentication.getPrincipal() instanceof LoginSiteUser))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
LoginSiteUser loginUser = (LoginSiteUser) authentication.getPrincipal();
|
||||
AppUser appUser = loginUser.getUser();
|
||||
if (loginUser.getUserId() == null || appUser == null
|
||||
|| !StringUtil.IS_JOB_REQUEST_USER.equals(appUser.getIsCompanyUser()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return loginUser.getUserId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 移动端求职者消息接收设置。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("移动端求职者消息接收设置")
|
||||
@TableName("app_user_notice_setting")
|
||||
public class AppUserNoticeSetting extends BaseEntity
|
||||
{
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** APP 用户 ID,每名用户仅有一条设置。 */
|
||||
private Long userId;
|
||||
|
||||
/** 职位上新。 */
|
||||
private Boolean jobUpdateEnabled;
|
||||
|
||||
/** 招聘会预约提醒。 */
|
||||
private Boolean appointmentReminderEnabled;
|
||||
|
||||
/** 平台系统通知。 */
|
||||
private Boolean systemNotificationEnabled;
|
||||
|
||||
/** 企业面试通知。 */
|
||||
private Boolean interviewNotificationEnabled;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.cms.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 移动端消息接收设置保存请求。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("移动端消息接收设置保存请求")
|
||||
public class NoticeSettingRequest
|
||||
{
|
||||
@NotNull(message = "职位上新开关不能为空")
|
||||
@ApiModelProperty(value = "是否接收职位上新通知", required = true, example = "true")
|
||||
private Boolean jobUpdateEnabled;
|
||||
|
||||
@NotNull(message = "预约提醒开关不能为空")
|
||||
@ApiModelProperty(value = "是否接收招聘会预约提醒", required = true, example = "true")
|
||||
private Boolean appointmentReminderEnabled;
|
||||
|
||||
@NotNull(message = "系统通知开关不能为空")
|
||||
@ApiModelProperty(value = "是否接收系统通知", required = true, example = "true")
|
||||
private Boolean systemNotificationEnabled;
|
||||
|
||||
@NotNull(message = "面试通知开关不能为空")
|
||||
@ApiModelProperty(value = "是否接收面试通知", required = true, example = "true")
|
||||
private Boolean interviewNotificationEnabled;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.cms.domain.vo;
|
||||
|
||||
import com.ruoyi.cms.domain.AppUserNoticeSetting;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 移动端消息接收设置返回对象。
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("移动端消息接收设置")
|
||||
public class NoticeSettingVO
|
||||
{
|
||||
@ApiModelProperty(value = "是否接收职位上新通知", example = "true")
|
||||
private Boolean jobUpdateEnabled;
|
||||
|
||||
@ApiModelProperty(value = "是否接收招聘会预约提醒", example = "true")
|
||||
private Boolean appointmentReminderEnabled;
|
||||
|
||||
@ApiModelProperty(value = "是否接收系统通知", example = "true")
|
||||
private Boolean systemNotificationEnabled;
|
||||
|
||||
@ApiModelProperty(value = "是否接收面试通知", example = "true")
|
||||
private Boolean interviewNotificationEnabled;
|
||||
|
||||
public static NoticeSettingVO from(AppUserNoticeSetting setting)
|
||||
{
|
||||
NoticeSettingVO result = new NoticeSettingVO();
|
||||
result.setJobUpdateEnabled(setting.getJobUpdateEnabled());
|
||||
result.setAppointmentReminderEnabled(setting.getAppointmentReminderEnabled());
|
||||
result.setSystemNotificationEnabled(setting.getSystemNotificationEnabled());
|
||||
result.setInterviewNotificationEnabled(setting.getInterviewNotificationEnabled());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.AppUserNoticeSetting;
|
||||
|
||||
/**
|
||||
* 移动端用户消息接收设置 Mapper。
|
||||
*/
|
||||
public interface AppUserNoticeSettingMapper extends BaseMapper<AppUserNoticeSetting>
|
||||
{
|
||||
/**
|
||||
* 保存设置。user_id 唯一约束保证并发首次保存时只会保留一条记录。
|
||||
*/
|
||||
int upsert(AppUserNoticeSetting setting);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.cms.service;
|
||||
|
||||
import com.ruoyi.cms.domain.dto.NoticeSettingRequest;
|
||||
import com.ruoyi.cms.domain.vo.NoticeSettingVO;
|
||||
|
||||
/**
|
||||
* 移动端求职者消息接收设置服务。
|
||||
*/
|
||||
public interface IAppUserNoticeSettingService
|
||||
{
|
||||
/**
|
||||
* 查询用户设置;尚未保存过时返回四项均开启的默认设置。
|
||||
*/
|
||||
NoticeSettingVO getSettings(Long userId);
|
||||
|
||||
/**
|
||||
* 保存用户的完整四项设置。
|
||||
*/
|
||||
void saveSettings(Long userId, NoticeSettingRequest request);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ruoyi.cms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.ruoyi.cms.domain.AppUserNoticeSetting;
|
||||
import com.ruoyi.cms.domain.dto.NoticeSettingRequest;
|
||||
import com.ruoyi.cms.domain.vo.NoticeSettingVO;
|
||||
import com.ruoyi.cms.mapper.AppUserNoticeSettingMapper;
|
||||
import com.ruoyi.cms.service.IAppUserNoticeSettingService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 移动端求职者消息接收设置服务实现。
|
||||
*/
|
||||
@Service
|
||||
public class AppUserNoticeSettingServiceImpl
|
||||
extends ServiceImpl<AppUserNoticeSettingMapper, AppUserNoticeSetting>
|
||||
implements IAppUserNoticeSettingService
|
||||
{
|
||||
private final AppUserNoticeSettingMapper noticeSettingMapper;
|
||||
|
||||
public AppUserNoticeSettingServiceImpl(AppUserNoticeSettingMapper noticeSettingMapper)
|
||||
{
|
||||
this.noticeSettingMapper = noticeSettingMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoticeSettingVO getSettings(Long userId)
|
||||
{
|
||||
AppUserNoticeSetting setting = noticeSettingMapper.selectOne(
|
||||
Wrappers.<AppUserNoticeSetting>lambdaQuery()
|
||||
.eq(AppUserNoticeSetting::getUserId, userId));
|
||||
if (setting == null)
|
||||
{
|
||||
setting = defaultSetting(userId);
|
||||
}
|
||||
return NoticeSettingVO.from(setting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveSettings(Long userId, NoticeSettingRequest request)
|
||||
{
|
||||
AppUserNoticeSetting setting = new AppUserNoticeSetting();
|
||||
setting.setUserId(userId);
|
||||
setting.setJobUpdateEnabled(request.getJobUpdateEnabled());
|
||||
setting.setAppointmentReminderEnabled(request.getAppointmentReminderEnabled());
|
||||
setting.setSystemNotificationEnabled(request.getSystemNotificationEnabled());
|
||||
setting.setInterviewNotificationEnabled(request.getInterviewNotificationEnabled());
|
||||
noticeSettingMapper.upsert(setting);
|
||||
}
|
||||
|
||||
private AppUserNoticeSetting defaultSetting(Long userId)
|
||||
{
|
||||
AppUserNoticeSetting setting = new AppUserNoticeSetting();
|
||||
setting.setUserId(userId);
|
||||
setting.setJobUpdateEnabled(Boolean.TRUE);
|
||||
setting.setAppointmentReminderEnabled(Boolean.TRUE);
|
||||
setting.setSystemNotificationEnabled(Boolean.TRUE);
|
||||
setting.setInterviewNotificationEnabled(Boolean.TRUE);
|
||||
return setting;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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="com.ruoyi.cms.mapper.AppUserNoticeSettingMapper">
|
||||
|
||||
<insert id="upsert" parameterType="AppUserNoticeSetting">
|
||||
INSERT INTO app_user_notice_setting
|
||||
(user_id, job_update_enabled, appointment_reminder_enabled,
|
||||
system_notification_enabled, interview_notification_enabled,
|
||||
create_time, update_time, del_flag)
|
||||
VALUES
|
||||
(#{userId}, #{jobUpdateEnabled}, #{appointmentReminderEnabled},
|
||||
#{systemNotificationEnabled}, #{interviewNotificationEnabled},
|
||||
NOW(), NOW(), '0')
|
||||
ON CONFLICT (user_id) DO UPDATE
|
||||
SET job_update_enabled = EXCLUDED.job_update_enabled,
|
||||
appointment_reminder_enabled = EXCLUDED.appointment_reminder_enabled,
|
||||
system_notification_enabled = EXCLUDED.system_notification_enabled,
|
||||
interview_notification_enabled = EXCLUDED.interview_notification_enabled,
|
||||
update_time = NOW(),
|
||||
del_flag = '0'
|
||||
</insert>
|
||||
</mapper>
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.ruoyi.cms.controller.app;
|
||||
|
||||
import com.ruoyi.cms.domain.dto.NoticeSettingRequest;
|
||||
import com.ruoyi.cms.domain.vo.NoticeSettingVO;
|
||||
import com.ruoyi.cms.service.IAppUserNoticeSettingService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginSiteUser;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class AppNoticeInfoControllerTest
|
||||
{
|
||||
@AfterEach
|
||||
void clearSecurityContext()
|
||||
{
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void jobSeekerCanReadOwnSettings() throws Exception
|
||||
{
|
||||
IAppUserNoticeSettingService service = mock(IAppUserNoticeSettingService.class);
|
||||
NoticeSettingVO expected = new NoticeSettingVO();
|
||||
expected.setJobUpdateEnabled(true);
|
||||
expected.setAppointmentReminderEnabled(true);
|
||||
expected.setSystemNotificationEnabled(false);
|
||||
expected.setInterviewNotificationEnabled(true);
|
||||
when(service.getSettings(12L)).thenReturn(expected);
|
||||
authenticateSiteUser(12L, "1");
|
||||
|
||||
AppNoticeInfoController controller = controllerWith(service);
|
||||
AjaxResult result = controller.getSettings();
|
||||
|
||||
assertEquals(200, result.get(AjaxResult.CODE_TAG));
|
||||
assertEquals(expected, result.get(AjaxResult.DATA_TAG));
|
||||
verify(service).getSettings(12L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonJobSeekerCannotSaveSettings() throws Exception
|
||||
{
|
||||
IAppUserNoticeSettingService service = mock(IAppUserNoticeSettingService.class);
|
||||
authenticateSiteUser(12L, "0");
|
||||
NoticeSettingRequest request = new NoticeSettingRequest();
|
||||
request.setJobUpdateEnabled(true);
|
||||
request.setAppointmentReminderEnabled(true);
|
||||
request.setSystemNotificationEnabled(true);
|
||||
request.setInterviewNotificationEnabled(true);
|
||||
|
||||
AppNoticeInfoController controller = controllerWith(service);
|
||||
AjaxResult result = controller.saveSettings(request);
|
||||
|
||||
assertEquals(403, result.get(AjaxResult.CODE_TAG));
|
||||
verify(service, never()).saveSettings(eq(12L), any(NoticeSettingRequest.class));
|
||||
}
|
||||
|
||||
private AppNoticeInfoController controllerWith(IAppUserNoticeSettingService service) throws Exception
|
||||
{
|
||||
AppNoticeInfoController controller = new AppNoticeInfoController();
|
||||
Field field = AppNoticeInfoController.class.getDeclaredField("appUserNoticeSettingService");
|
||||
field.setAccessible(true);
|
||||
field.set(controller, service);
|
||||
return controller;
|
||||
}
|
||||
|
||||
private void authenticateSiteUser(Long userId, String userType)
|
||||
{
|
||||
AppUser appUser = new AppUser();
|
||||
appUser.setIsCompanyUser(userType);
|
||||
LoginSiteUser loginUser = new LoginSiteUser(userId, appUser);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
loginUser, null, Collections.emptyList());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.ruoyi.cms.service.impl;
|
||||
|
||||
import com.ruoyi.cms.domain.AppUserNoticeSetting;
|
||||
import com.ruoyi.cms.domain.dto.NoticeSettingRequest;
|
||||
import com.ruoyi.cms.domain.vo.NoticeSettingVO;
|
||||
import com.ruoyi.cms.mapper.AppUserNoticeSettingMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class AppUserNoticeSettingServiceImplTest
|
||||
{
|
||||
@Test
|
||||
void returnsAllEnabledDefaultsWhenUserHasNotSavedSettings()
|
||||
{
|
||||
AppUserNoticeSettingMapper mapper = mock(AppUserNoticeSettingMapper.class);
|
||||
when(mapper.selectOne(any())).thenReturn(null);
|
||||
AppUserNoticeSettingServiceImpl service = new AppUserNoticeSettingServiceImpl(mapper);
|
||||
|
||||
NoticeSettingVO result = service.getSettings(12L);
|
||||
|
||||
assertTrue(result.getJobUpdateEnabled());
|
||||
assertTrue(result.getAppointmentReminderEnabled());
|
||||
assertTrue(result.getSystemNotificationEnabled());
|
||||
assertTrue(result.getInterviewNotificationEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsPersistedSettingsForCurrentUser()
|
||||
{
|
||||
AppUserNoticeSettingMapper mapper = mock(AppUserNoticeSettingMapper.class);
|
||||
AppUserNoticeSetting setting = new AppUserNoticeSetting();
|
||||
setting.setJobUpdateEnabled(false);
|
||||
setting.setAppointmentReminderEnabled(true);
|
||||
setting.setSystemNotificationEnabled(false);
|
||||
setting.setInterviewNotificationEnabled(true);
|
||||
when(mapper.selectOne(any())).thenReturn(setting);
|
||||
AppUserNoticeSettingServiceImpl service = new AppUserNoticeSettingServiceImpl(mapper);
|
||||
|
||||
NoticeSettingVO result = service.getSettings(12L);
|
||||
|
||||
assertFalse(result.getJobUpdateEnabled());
|
||||
assertTrue(result.getAppointmentReminderEnabled());
|
||||
assertFalse(result.getSystemNotificationEnabled());
|
||||
assertTrue(result.getInterviewNotificationEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void savesAllFourSettingsForTheAuthenticatedUser()
|
||||
{
|
||||
AppUserNoticeSettingMapper mapper = mock(AppUserNoticeSettingMapper.class);
|
||||
AppUserNoticeSettingServiceImpl service = new AppUserNoticeSettingServiceImpl(mapper);
|
||||
NoticeSettingRequest request = new NoticeSettingRequest();
|
||||
request.setJobUpdateEnabled(true);
|
||||
request.setAppointmentReminderEnabled(false);
|
||||
request.setSystemNotificationEnabled(true);
|
||||
request.setInterviewNotificationEnabled(false);
|
||||
|
||||
service.saveSettings(12L, request);
|
||||
|
||||
ArgumentCaptor<AppUserNoticeSetting> captor = ArgumentCaptor.forClass(AppUserNoticeSetting.class);
|
||||
verify(mapper).upsert(captor.capture());
|
||||
AppUserNoticeSetting saved = captor.getValue();
|
||||
assertEquals(12L, saved.getUserId());
|
||||
assertTrue(saved.getJobUpdateEnabled());
|
||||
assertFalse(saved.getAppointmentReminderEnabled());
|
||||
assertTrue(saved.getSystemNotificationEnabled());
|
||||
assertFalse(saved.getInterviewNotificationEnabled());
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,9 @@ public class SecurityConfig
|
||||
"/cms/policyInfo/detail","/cms/policyInfo/list","/cms/industry/treeselect").permitAll()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||
// 移动端消息接收设置包含用户个人偏好,必须使用站点 Token 访问。
|
||||
// 该规则需位于 /app/** 的公共查询规则之前。
|
||||
.antMatchers("/app/notice/settings").authenticated()
|
||||
// 移动端公用查询,可匿名访问
|
||||
.antMatchers("/app/common/**").permitAll()
|
||||
.antMatchers("/app/**").permitAll()
|
||||
|
||||
30
sql/migration_app_user_notice_setting.sql
Normal file
30
sql/migration_app_user_notice_setting.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
-- 移动端求职者消息接收设置。
|
||||
-- 瀚高 / PostgreSQL 兼容;重复执行安全。表放在 shz schema,应用通过 search_path 访问。
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS shz.app_user_notice_setting_id_seq
|
||||
START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS shz.app_user_notice_setting (
|
||||
id BIGINT NOT NULL DEFAULT nextval('shz.app_user_notice_setting_id_seq'::regclass) PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
job_update_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
appointment_reminder_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
system_notification_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
interview_notification_enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
create_by VARCHAR(64) DEFAULT '',
|
||||
create_time TIMESTAMP(0),
|
||||
update_by VARCHAR(64) DEFAULT '',
|
||||
update_time TIMESTAMP(0),
|
||||
remark VARCHAR(500),
|
||||
del_flag CHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_app_user_notice_setting_user_id
|
||||
ON shz.app_user_notice_setting (user_id);
|
||||
|
||||
COMMENT ON TABLE shz.app_user_notice_setting IS '移动端求职者消息接收设置';
|
||||
COMMENT ON COLUMN shz.app_user_notice_setting.user_id IS 'APP 用户 ID,每用户唯一';
|
||||
COMMENT ON COLUMN shz.app_user_notice_setting.job_update_enabled IS '是否接收职位上新通知';
|
||||
COMMENT ON COLUMN shz.app_user_notice_setting.appointment_reminder_enabled IS '是否接收招聘会预约提醒';
|
||||
COMMENT ON COLUMN shz.app_user_notice_setting.system_notification_enabled IS '是否接收系统通知';
|
||||
COMMENT ON COLUMN shz.app_user_notice_setting.interview_notification_enabled IS '是否接收面试通知';
|
||||
Reference in New Issue
Block a user