feat: 新增招聘会企业签到与未参会统计
This commit is contained in:
@@ -8,6 +8,7 @@ import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import com.ruoyi.cms.domain.OutdoorFairAttendee;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBooth;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
|
||||
import com.ruoyi.cms.domain.OutdoorFairCompanyAttendance;
|
||||
import com.ruoyi.cms.domain.OutdoorFairDevice;
|
||||
import com.ruoyi.cms.mapper.CompanyMapper;
|
||||
import com.ruoyi.cms.mapper.FairCompanyMapper;
|
||||
@@ -15,12 +16,14 @@ import com.ruoyi.cms.mapper.OutdoorFairBoothMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairDeviceMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairJobMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairCompanyAttendanceMapper;
|
||||
import com.ruoyi.cms.domain.rc.PublicJobFair;
|
||||
import com.ruoyi.cms.domain.rc.PublicJobFairQuery;
|
||||
import com.ruoyi.cms.domain.rc.PublicJobFairResponse;
|
||||
import com.ruoyi.cms.service.IAppUserService;
|
||||
import com.ruoyi.cms.service.IOutdoorFairAttendeeService;
|
||||
import com.ruoyi.cms.service.IOutdoorFairService;
|
||||
import com.ruoyi.cms.util.RoleUtils;
|
||||
import com.ruoyi.cms.util.StringUtil;
|
||||
import com.ruoyi.common.annotation.BussinessLog;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
@@ -40,6 +43,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.text.ParseException;
|
||||
@@ -83,6 +87,9 @@ public class AppOutdoorFairController extends BaseController
|
||||
@Autowired
|
||||
private OutdoorFairJobMapper outdoorFairJobMapper;
|
||||
|
||||
@Autowired
|
||||
private OutdoorFairCompanyAttendanceMapper outdoorFairCompanyAttendanceMapper;
|
||||
|
||||
@Autowired
|
||||
private IOutdoorFairAttendeeService outdoorFairAttendeeService;
|
||||
|
||||
@@ -221,6 +228,113 @@ public class AppOutdoorFairController extends BaseController
|
||||
return checkIn(fairId, SiteSecurityUtils.getUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录企业在招聘会举办期间签到。小程序暂不接入页面,但保留独立的企业接口供后续使用。
|
||||
*/
|
||||
@BussinessLog(title = "户外招聘会企业签到")
|
||||
@ApiOperation("移动端企业签到户外招聘会")
|
||||
@PostMapping("/company/check-in")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult companyCheckIn(@RequestParam Long fairId)
|
||||
{
|
||||
if (!SiteSecurityUtils.isLogin()) {
|
||||
return AjaxResult.error("请先登录");
|
||||
}
|
||||
AppUser appUser = RoleUtils.getAppUser();
|
||||
return companyCheckIn(fairId, appUser);
|
||||
}
|
||||
|
||||
/** 签到业务实现单独保留 AppUser 入参,便于单元测试覆盖企业权限和业务规则。 */
|
||||
AjaxResult companyCheckIn(Long fairId, AppUser appUser)
|
||||
{
|
||||
if (fairId == null) {
|
||||
return AjaxResult.error("缺少招聘会参数");
|
||||
}
|
||||
if (appUser == null) {
|
||||
return AjaxResult.error("用户信息不存在,请重新登录");
|
||||
}
|
||||
if (!StringUtil.IS_COMPANY_USER.equals(appUser.getIsCompanyUser())) {
|
||||
return AjaxResult.error("仅移动端企业可以签到");
|
||||
}
|
||||
|
||||
Company company = null;
|
||||
if (StringUtils.isNotBlank(appUser.getIdCard())) {
|
||||
company = companyMapper.selectOne(new LambdaQueryWrapper<Company>()
|
||||
.eq(Company::getCode, appUser.getIdCard())
|
||||
.eq(Company::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
if (company == null && appUser.getUserId() != null) {
|
||||
company = companyMapper.selectOne(new LambdaQueryWrapper<Company>()
|
||||
.eq(Company::getUserId, appUser.getUserId())
|
||||
.eq(Company::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
if (company == null) {
|
||||
return AjaxResult.error("未找到当前企业信息");
|
||||
}
|
||||
|
||||
OutdoorFair fair = outdoorFairService.getById(fairId);
|
||||
if (fair == null) {
|
||||
return AjaxResult.error("招聘会不存在");
|
||||
}
|
||||
String timeError = validateCompanyCheckInTime(fair, new Date());
|
||||
if (timeError != null) {
|
||||
return AjaxResult.error(timeError);
|
||||
}
|
||||
|
||||
FairCompany relation = fairCompanyMapper.selectOne(new LambdaQueryWrapper<FairCompany>()
|
||||
.eq(FairCompany::getJobFairId, fairId)
|
||||
.eq(FairCompany::getCompanyId, company.getCompanyId())
|
||||
.eq(FairCompany::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
if (relation == null) {
|
||||
return AjaxResult.error("该企业未报名当前招聘会");
|
||||
}
|
||||
if (!"1".equals(relation.getReviewStatus())) {
|
||||
return AjaxResult.error("报名审核通过后才能签到");
|
||||
}
|
||||
|
||||
OutdoorFairCompanyAttendance attendance = outdoorFairCompanyAttendanceMapper.selectOne(
|
||||
new LambdaQueryWrapper<OutdoorFairCompanyAttendance>()
|
||||
.eq(OutdoorFairCompanyAttendance::getFairId, fairId)
|
||||
.eq(OutdoorFairCompanyAttendance::getCompanyId, company.getCompanyId())
|
||||
.eq(OutdoorFairCompanyAttendance::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
if (attendance != null && "1".equals(attendance.getAttendanceStatus())) {
|
||||
return AjaxResult.error("该企业已签到,无需重复签到");
|
||||
}
|
||||
|
||||
Date checkInTime = new Date();
|
||||
if (attendance == null) {
|
||||
attendance = new OutdoorFairCompanyAttendance();
|
||||
attendance.setFairId(fairId);
|
||||
attendance.setCompanyId(company.getCompanyId());
|
||||
attendance.setCreateBy(String.valueOf(appUser.getUserId()));
|
||||
attendance.setCreateTime(checkInTime);
|
||||
}
|
||||
attendance.setCompanyName(company.getName());
|
||||
attendance.setContactPerson(company.getContactPerson());
|
||||
attendance.setContactPhone(company.getContactPersonPhone());
|
||||
attendance.setAttendanceStatus("1");
|
||||
attendance.setCheckInTime(checkInTime);
|
||||
attendance.setUpdateBy(String.valueOf(appUser.getUserId()));
|
||||
attendance.setUpdateTime(checkInTime);
|
||||
boolean saved = attendance.getId() == null
|
||||
? outdoorFairCompanyAttendanceMapper.insert(attendance) > 0
|
||||
: outdoorFairCompanyAttendanceMapper.updateById(attendance) > 0;
|
||||
if (!saved) {
|
||||
return AjaxResult.error("签到失败,请稍后重试");
|
||||
}
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("fairId", fairId);
|
||||
data.put("companyId", company.getCompanyId());
|
||||
data.put("checkInTime", checkInTime);
|
||||
data.put("attendanceStatus", "checked_in");
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到业务实现单独保留 userId 入参,便于无 Web 容器的单元测试覆盖业务规则。
|
||||
*/
|
||||
@@ -276,6 +390,20 @@ public class AppOutdoorFairController extends BaseController
|
||||
&& !currentTime.before(fair.getHoldTime());
|
||||
}
|
||||
|
||||
private static String validateCompanyCheckInTime(OutdoorFair fair, Date currentTime)
|
||||
{
|
||||
if (fair == null || fair.getHoldTime() == null || fair.getEndTime() == null || currentTime == null) {
|
||||
return "招聘会举办时间不完整,暂不能签到";
|
||||
}
|
||||
if (currentTime.before(fair.getHoldTime())) {
|
||||
return "招聘会还没有开始,暂不能签到";
|
||||
}
|
||||
if (currentTime.after(fair.getEndTime())) {
|
||||
return "招聘会已结束,不能签到";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean hasCheckedIn(Long fairId)
|
||||
{
|
||||
if (!SiteSecurityUtils.isLogin()) {
|
||||
|
||||
@@ -2,8 +2,10 @@ package com.ruoyi.cms.controller.cms;
|
||||
|
||||
|
||||
import com.ruoyi.cms.domain.query.CompanySearch;
|
||||
import com.ruoyi.cms.domain.vo.CompanyMissedOutdoorFairVO;
|
||||
import com.ruoyi.cms.domain.query.JobSearch;
|
||||
import com.ruoyi.cms.mapper.AppUserMapper;
|
||||
import com.ruoyi.cms.mapper.CompanyMapper;
|
||||
import com.ruoyi.cms.util.RoleUtils;
|
||||
import com.ruoyi.cms.util.sensitiveWord.SensitiveWordChecker;
|
||||
import com.ruoyi.common.core.domain.entity.AppUser;
|
||||
@@ -46,6 +48,9 @@ public class CompanyController extends BaseController
|
||||
@Autowired
|
||||
private AppUserMapper appUserMapper;
|
||||
|
||||
@Autowired
|
||||
private CompanyMapper companyMapper;
|
||||
|
||||
@Autowired
|
||||
SensitiveWordChecker sensitiveWordChecker;
|
||||
|
||||
@@ -70,6 +75,26 @@ public class CompanyController extends BaseController
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询企业未参加的已结束户外招聘会明细。
|
||||
* 失信口径为:报名审核通过、招聘会已结束且企业签到状态不是已签到。
|
||||
*/
|
||||
@ApiOperation("查询企业未参加招聘会明细")
|
||||
@PreAuthorize("@ss.hasPermi('cms:company:list')")
|
||||
@GetMapping("/{companyId}/missed-outdoor-fairs")
|
||||
public TableDataInfo missedOutdoorFairs(@PathVariable Long companyId)
|
||||
{
|
||||
if (RoleUtils.isCompanyAdmin()) {
|
||||
Company currentCompany = getCurrentCompany();
|
||||
if (currentCompany == null || !companyId.equals(currentCompany.getCompanyId())) {
|
||||
return getDataTable(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
startPage();
|
||||
List<CompanyMissedOutdoorFairVO> list = companyMapper.selectMissedOutdoorFairList(companyId);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出公司列表
|
||||
*/
|
||||
|
||||
@@ -24,15 +24,18 @@ import com.ruoyi.cms.domain.Job;
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBooth;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
|
||||
import com.ruoyi.cms.domain.OutdoorFairCompanyAttendance;
|
||||
import com.ruoyi.cms.domain.OutdoorFairCompanyUnsubscribe;
|
||||
import com.ruoyi.cms.domain.OutdoorFairDevice;
|
||||
import com.ruoyi.cms.domain.OutdoorFairDictDataRequest;
|
||||
import com.ruoyi.cms.domain.OutdoorFairJob;
|
||||
import com.ruoyi.cms.domain.VenueBooth;
|
||||
import com.ruoyi.cms.domain.VenueInfo;
|
||||
import com.ruoyi.cms.domain.vo.OutdoorFairCompanyAttendanceVO;
|
||||
import com.ruoyi.cms.mapper.FairCompanyMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairCompanyAttendanceMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairDeviceMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairCompanyUnsubscribeMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairJobMapper;
|
||||
@@ -97,6 +100,9 @@ public class OutdoorFairController extends BaseController
|
||||
@Autowired
|
||||
private OutdoorFairCompanyUnsubscribeMapper outdoorFairCompanyUnsubscribeMapper;
|
||||
|
||||
@Autowired
|
||||
private OutdoorFairCompanyAttendanceMapper outdoorFairCompanyAttendanceMapper;
|
||||
|
||||
@Autowired
|
||||
private CompanyMapper companyMapper;
|
||||
|
||||
@@ -604,6 +610,7 @@ public class OutdoorFairController extends BaseController
|
||||
.set("company_name", null)
|
||||
.set("bind_time", null));
|
||||
fairCompanyMapper.deleteById(relation.getId());
|
||||
invalidateCompanyAttendanceRecord(fairId, company.getCompanyId());
|
||||
return success();
|
||||
}
|
||||
|
||||
@@ -618,6 +625,116 @@ public class OutdoorFairController extends BaseController
|
||||
return success(buildCompanyQrCodeData(request, fairId, company.getCompanyId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前企业在招聘会举办期间签到。
|
||||
* 只有企业账号、当前企业已报名且审核通过,并且当前时间处于举办时间闭区间内时才允许签到。
|
||||
*/
|
||||
@ApiOperation("企业签到户外招聘会")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:companyCheckIn')")
|
||||
@Log(title = "户外招聘会企业签到", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/{fairId}/company/check-in")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AjaxResult checkInCompany(@PathVariable Long fairId)
|
||||
{
|
||||
if (!RoleUtils.isCompanyAdmin()) {
|
||||
return AjaxResult.error("仅企业用户可以签到");
|
||||
}
|
||||
Company company = getCurrentCompanyOrThrow();
|
||||
OutdoorFair fair = outdoorFairService.getById(fairId);
|
||||
if (fair == null) {
|
||||
return AjaxResult.error("户外招聘会不存在");
|
||||
}
|
||||
String timeError = validateCompanyCheckInTime(fair, new Date());
|
||||
if (timeError != null) {
|
||||
return AjaxResult.error(timeError);
|
||||
}
|
||||
|
||||
FairCompany relation = fairCompanyMapper.selectOne(new LambdaQueryWrapper<FairCompany>()
|
||||
.eq(FairCompany::getJobFairId, fairId)
|
||||
.eq(FairCompany::getCompanyId, company.getCompanyId())
|
||||
.eq(FairCompany::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
if (relation == null) {
|
||||
return AjaxResult.error("该企业未报名当前招聘会");
|
||||
}
|
||||
if (!"1".equals(relation.getReviewStatus())) {
|
||||
return AjaxResult.error("报名审核通过后才能签到");
|
||||
}
|
||||
|
||||
OutdoorFairCompanyAttendance attendance = outdoorFairCompanyAttendanceMapper.selectOne(
|
||||
new LambdaQueryWrapper<OutdoorFairCompanyAttendance>()
|
||||
.eq(OutdoorFairCompanyAttendance::getFairId, fairId)
|
||||
.eq(OutdoorFairCompanyAttendance::getCompanyId, company.getCompanyId())
|
||||
.eq(OutdoorFairCompanyAttendance::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
if (attendance != null && "1".equals(attendance.getAttendanceStatus())) {
|
||||
return AjaxResult.error("该企业已签到,无需重复签到");
|
||||
}
|
||||
|
||||
Date checkInTime = new Date();
|
||||
if (attendance == null) {
|
||||
attendance = new OutdoorFairCompanyAttendance();
|
||||
attendance.setFairId(fairId);
|
||||
attendance.setCompanyId(company.getCompanyId());
|
||||
attendance.setCreateBy(getUsername());
|
||||
attendance.setCreateTime(checkInTime);
|
||||
}
|
||||
attendance.setCompanyName(company.getName());
|
||||
attendance.setContactPerson(company.getContactPerson());
|
||||
attendance.setContactPhone(company.getContactPersonPhone());
|
||||
attendance.setAttendanceStatus("1");
|
||||
attendance.setCheckInTime(checkInTime);
|
||||
attendance.setUpdateBy(getUsername());
|
||||
attendance.setUpdateTime(checkInTime);
|
||||
boolean saved = attendance.getId() == null
|
||||
? outdoorFairCompanyAttendanceMapper.insert(attendance) > 0
|
||||
: outdoorFairCompanyAttendanceMapper.updateById(attendance) > 0;
|
||||
if (!saved) {
|
||||
return AjaxResult.error("签到失败,请稍后重试");
|
||||
}
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("fairId", fairId);
|
||||
data.put("companyId", company.getCompanyId());
|
||||
data.put("checkInTime", checkInTime);
|
||||
data.put("attendanceStatus", "checked_in");
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单场招聘会已签到/未签到企业。checkedIn=true 为已签到,false 为未签到。
|
||||
*/
|
||||
@ApiOperation("查询招聘会企业签到情况")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
|
||||
@GetMapping("/{fairId}/company-attendance")
|
||||
public AjaxResult listCompanyAttendance(@PathVariable Long fairId,
|
||||
String companyName,
|
||||
Boolean checkedIn,
|
||||
Integer current,
|
||||
Integer pageSize)
|
||||
{
|
||||
ensureFairExists(fairId);
|
||||
Long companyId = null;
|
||||
if (RoleUtils.isCompanyAdmin()) {
|
||||
Company company = getCurrentCompanyOrNull();
|
||||
if (company == null) {
|
||||
return emptyAjaxPage();
|
||||
}
|
||||
companyId = company.getCompanyId();
|
||||
}
|
||||
List<OutdoorFairCompanyAttendanceVO> rows = outdoorFairCompanyAttendanceMapper
|
||||
.selectCompanyAttendanceList(fairId, companyId, companyName, checkedIn);
|
||||
int total = rows.size();
|
||||
int page = current == null || current < 1 ? 1 : current;
|
||||
int size = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 100);
|
||||
int fromIndex = Math.min((page - 1) * size, total);
|
||||
int toIndex = Math.min(fromIndex + size, total);
|
||||
AjaxResult result = AjaxResult.success();
|
||||
result.put("rows", rows.subList(fromIndex, toIndex));
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ApiOperation("查询户外招聘会参会企业")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
|
||||
@GetMapping("/{fairId}/companies")
|
||||
@@ -665,6 +782,13 @@ public class OutdoorFairController extends BaseController
|
||||
.isNotNull(OutdoorFairDevice::getCompanyId))
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OutdoorFairDevice::getCompanyId, item -> item, (a, b) -> a));
|
||||
Map<Long, OutdoorFairCompanyAttendance> attendanceMap = outdoorFairCompanyAttendanceMapper.selectList(
|
||||
new LambdaQueryWrapper<OutdoorFairCompanyAttendance>()
|
||||
.eq(OutdoorFairCompanyAttendance::getFairId, fairId)
|
||||
.eq(OutdoorFairCompanyAttendance::getDelFlag, "0"))
|
||||
.stream()
|
||||
.filter(item -> item.getCompanyId() != null)
|
||||
.collect(Collectors.toMap(OutdoorFairCompanyAttendance::getCompanyId, item -> item, (a, b) -> a));
|
||||
|
||||
List<Map<String, Object>> rows = new ArrayList<>();
|
||||
for (FairCompany relation : relations) {
|
||||
@@ -693,6 +817,10 @@ public class OutdoorFairController extends BaseController
|
||||
row.put("reviewTime", relation.getReviewTime());
|
||||
row.put("reviewRemark", relation.getReviewRemark());
|
||||
row.put("registrationTime", relation.getCreateTime());
|
||||
OutdoorFairCompanyAttendance attendance = attendanceMap.get(company.getCompanyId());
|
||||
row.put("companyCheckInStatus", attendance != null && "1".equals(attendance.getAttendanceStatus())
|
||||
? "checked_in" : "not_checked_in");
|
||||
row.put("companyCheckInTime", attendance == null ? null : attendance.getCheckInTime());
|
||||
OutdoorFairDevice device = deviceMap.get(company.getCompanyId());
|
||||
String h5Url = buildOutdoorFairCompanyH5Url(request, fairId, company.getCompanyId());
|
||||
row.put("deviceId", device == null ? null : device.getId());
|
||||
@@ -810,12 +938,16 @@ public class OutdoorFairController extends BaseController
|
||||
if (company == null || company.getStatus() == null || company.getStatus() != 1) {
|
||||
return AjaxResult.error("只能添加审核通过的企业");
|
||||
}
|
||||
ensureFairCompany(fairId, companyId);
|
||||
FairCompany relation = ensureFairCompany(fairId, companyId);
|
||||
if ("1".equals(relation.getReviewStatus())) {
|
||||
ensureCompanyAttendanceRecord(fairId, company);
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
@ApiOperation("审核户外招聘会参会企业")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@PutMapping("/{fairId}/companies/{id}/review")
|
||||
public AjaxResult reviewCompany(@PathVariable Long fairId, @PathVariable Long id,
|
||||
@RequestBody Map<String, Object> request)
|
||||
@@ -828,11 +960,19 @@ public class OutdoorFairController extends BaseController
|
||||
}
|
||||
String reviewRemark = request.get("reviewRemark") == null ? null : String.valueOf(request.get("reviewRemark"));
|
||||
validateRejectRemark(reviewStatus, reviewRemark);
|
||||
String previousReviewStatus = relation.getReviewStatus();
|
||||
relation.setReviewStatus(reviewStatus);
|
||||
relation.setReviewBy(getUsername());
|
||||
relation.setReviewTime(new Date());
|
||||
relation.setReviewRemark(reviewRemark);
|
||||
return toAjax(fairCompanyMapper.updateById(relation));
|
||||
int updated = fairCompanyMapper.updateById(relation);
|
||||
if (updated > 0 && "1".equals(reviewStatus) && !"1".equals(previousReviewStatus)) {
|
||||
Company company = companyMapper.selectById(relation.getCompanyId());
|
||||
if (company != null) {
|
||||
ensureCompanyAttendanceRecord(fairId, company);
|
||||
}
|
||||
}
|
||||
return toAjax(updated);
|
||||
}
|
||||
|
||||
@ApiOperation("移除户外招聘会参会企业")
|
||||
@@ -851,7 +991,11 @@ public class OutdoorFairController extends BaseController
|
||||
outdoorFairJobMapper.delete(new LambdaQueryWrapper<OutdoorFairJob>()
|
||||
.eq(OutdoorFairJob::getFairId, fairId)
|
||||
.eq(OutdoorFairJob::getCompanyId, relation.getCompanyId()));
|
||||
return toAjax(fairCompanyMapper.deleteById(id));
|
||||
int deleted = fairCompanyMapper.deleteById(id);
|
||||
if (deleted > 0) {
|
||||
invalidateCompanyAttendanceRecord(fairId, relation.getCompanyId());
|
||||
}
|
||||
return toAjax(deleted);
|
||||
}
|
||||
|
||||
@ApiOperation("新增户外招聘会岗位")
|
||||
@@ -1088,9 +1232,17 @@ public class OutdoorFairController extends BaseController
|
||||
List<Long> fairIds = list.stream().map(OutdoorFair::getId).collect(Collectors.toList());
|
||||
Map<Long, FairCompany> relationMap = fairCompanyMapper.selectList(new LambdaQueryWrapper<FairCompany>()
|
||||
.in(FairCompany::getJobFairId, fairIds)
|
||||
.eq(FairCompany::getCompanyId, company.getCompanyId()))
|
||||
.eq(FairCompany::getCompanyId, company.getCompanyId())
|
||||
.eq(FairCompany::getDelFlag, "0"))
|
||||
.stream()
|
||||
.collect(Collectors.toMap(FairCompany::getJobFairId, item -> item, (a, b) -> a));
|
||||
Map<Long, OutdoorFairCompanyAttendance> attendanceMap = outdoorFairCompanyAttendanceMapper.selectList(
|
||||
new LambdaQueryWrapper<OutdoorFairCompanyAttendance>()
|
||||
.in(OutdoorFairCompanyAttendance::getFairId, fairIds)
|
||||
.eq(OutdoorFairCompanyAttendance::getCompanyId, company.getCompanyId())
|
||||
.eq(OutdoorFairCompanyAttendance::getDelFlag, "0"))
|
||||
.stream()
|
||||
.collect(Collectors.toMap(OutdoorFairCompanyAttendance::getFairId, item -> item, (a, b) -> a));
|
||||
for (OutdoorFair fair : list) {
|
||||
FairCompany relation = relationMap.get(fair.getId());
|
||||
boolean signedUp = relation != null;
|
||||
@@ -1099,6 +1251,12 @@ public class OutdoorFairController extends BaseController
|
||||
fair.setSignedUp(signedUp);
|
||||
fair.setReviewStatus(relation == null ? null : relation.getReviewStatus());
|
||||
fair.setReviewRemark(relation == null ? null : relation.getReviewRemark());
|
||||
OutdoorFairCompanyAttendance attendance = attendanceMap.get(fair.getId());
|
||||
fair.setCompanyCheckInStatus(attendance != null && "1".equals(attendance.getAttendanceStatus())
|
||||
? "checked_in" : "not_checked_in");
|
||||
fair.setCompanyCheckInTime(attendance == null ? null : attendance.getCheckInTime());
|
||||
fair.setCompanyCheckInAllowed(signedUp && "1".equals(fair.getReviewStatus())
|
||||
&& isCompanyCheckInAllowed(fair, new Date()));
|
||||
if (signedUp) {
|
||||
String h5Url = buildOutdoorFairCompanyH5Url(request, fair.getId(), company.getCompanyId());
|
||||
fair.setH5Url(h5Url);
|
||||
@@ -1141,6 +1299,48 @@ public class OutdoorFairController extends BaseController
|
||||
return fairCompany;
|
||||
}
|
||||
|
||||
/** 为审核通过的报名关系建立企业签到状态记录。 */
|
||||
private void ensureCompanyAttendanceRecord(Long fairId, Company company)
|
||||
{
|
||||
if (fairId == null || company == null || company.getCompanyId() == null) {
|
||||
return;
|
||||
}
|
||||
OutdoorFairCompanyAttendance existing = outdoorFairCompanyAttendanceMapper.selectOne(
|
||||
new LambdaQueryWrapper<OutdoorFairCompanyAttendance>()
|
||||
.eq(OutdoorFairCompanyAttendance::getFairId, fairId)
|
||||
.eq(OutdoorFairCompanyAttendance::getCompanyId, company.getCompanyId())
|
||||
.eq(OutdoorFairCompanyAttendance::getDelFlag, "0")
|
||||
.last("LIMIT 1"));
|
||||
if (existing != null) {
|
||||
return;
|
||||
}
|
||||
OutdoorFairCompanyAttendance attendance = new OutdoorFairCompanyAttendance();
|
||||
attendance.setFairId(fairId);
|
||||
attendance.setCompanyId(company.getCompanyId());
|
||||
attendance.setCompanyName(company.getName());
|
||||
attendance.setContactPerson(company.getContactPerson());
|
||||
attendance.setContactPhone(company.getContactPersonPhone());
|
||||
attendance.setAttendanceStatus("0");
|
||||
attendance.setCreateBy(getUsername());
|
||||
attendance.setCreateTime(new Date());
|
||||
outdoorFairCompanyAttendanceMapper.insert(attendance);
|
||||
}
|
||||
|
||||
/** 报名被移除或退订后作废旧签到记录,避免重新报名沿用上一次签到状态。 */
|
||||
private void invalidateCompanyAttendanceRecord(Long fairId, Long companyId)
|
||||
{
|
||||
if (fairId == null || companyId == null) {
|
||||
return;
|
||||
}
|
||||
outdoorFairCompanyAttendanceMapper.update(null, new UpdateWrapper<OutdoorFairCompanyAttendance>()
|
||||
.eq("fair_id", fairId)
|
||||
.eq("company_id", companyId)
|
||||
.eq("del_flag", "0")
|
||||
.set("del_flag", "2")
|
||||
.set("update_by", getUsername())
|
||||
.set("update_time", new Date()));
|
||||
}
|
||||
|
||||
private void validateReviewStatus(String reviewStatus)
|
||||
{
|
||||
if (!"0".equals(reviewStatus) && !"1".equals(reviewStatus) && !"2".equals(reviewStatus)) {
|
||||
@@ -1203,6 +1403,25 @@ public class OutdoorFairController extends BaseController
|
||||
return null;
|
||||
}
|
||||
|
||||
static String validateCompanyCheckInTime(OutdoorFair fair, Date currentTime)
|
||||
{
|
||||
if (fair == null || fair.getHoldTime() == null || fair.getEndTime() == null || currentTime == null) {
|
||||
return "招聘会举办时间不完整,暂不能签到";
|
||||
}
|
||||
if (currentTime.before(fair.getHoldTime())) {
|
||||
return "招聘会还没有开始,暂不能签到";
|
||||
}
|
||||
if (currentTime.after(fair.getEndTime())) {
|
||||
return "招聘会已结束,不能签到";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isCompanyCheckInAllowed(OutdoorFair fair, Date currentTime)
|
||||
{
|
||||
return validateCompanyCheckInTime(fair, currentTime) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前场地模板克隆为招聘会自己的展位图。模板与副本只在这里发生单向复制,之后互不影响。
|
||||
*/
|
||||
|
||||
@@ -148,4 +148,17 @@ public class OutdoorFair extends BaseEntity
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("当前企业报名审核备注")
|
||||
private String reviewRemark;
|
||||
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("当前企业签到状态:not_checked_in/checked_in")
|
||||
private String companyCheckInStatus;
|
||||
|
||||
@TableField(exist = false)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("当前企业签到时间")
|
||||
private Date companyCheckInTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
@ApiModelProperty("当前企业当前是否允许签到")
|
||||
private Boolean companyCheckInAllowed;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
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.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 户外招聘会企业签到记录。
|
||||
*
|
||||
* <p>每个审核通过的企业报名对应一条记录:0 表示尚未签到,1 表示已签到。
|
||||
* 招聘会结束后仍为 0 的记录即为企业未参会记录。</p>
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("户外招聘会企业签到记录")
|
||||
@TableName("shz.cms_outdoor_fair_company_attendance")
|
||||
public class OutdoorFairCompanyAttendance extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("招聘会ID")
|
||||
private Long fairId;
|
||||
|
||||
@ApiModelProperty("企业ID")
|
||||
private Long companyId;
|
||||
|
||||
@ApiModelProperty("企业名称快照")
|
||||
private String companyName;
|
||||
|
||||
@ApiModelProperty("联系人快照")
|
||||
private String contactPerson;
|
||||
|
||||
@ApiModelProperty("联系电话快照")
|
||||
private String contactPhone;
|
||||
|
||||
@ApiModelProperty("签到状态:0未签到,1已签到")
|
||||
private String attendanceStatus;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("签到时间")
|
||||
private Date checkInTime;
|
||||
}
|
||||
@@ -15,4 +15,7 @@ public class CompanySearch extends Company {
|
||||
private String startDate;
|
||||
//查询结束时间
|
||||
private String endDate;
|
||||
|
||||
/** 只查询存在未参加已结束户外招聘会记录的企业。 */
|
||||
private Boolean missedOutdoorFairOnly;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.cms.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/** 企业未参加户外招聘会明细。 */
|
||||
@Data
|
||||
@ApiModel("企业未参加户外招聘会明细")
|
||||
public class CompanyMissedOutdoorFairVO
|
||||
{
|
||||
@ApiModelProperty("招聘会ID")
|
||||
private Long fairId;
|
||||
|
||||
@ApiModelProperty("招聘会标题")
|
||||
private String title;
|
||||
|
||||
@ApiModelProperty("举办单位")
|
||||
private String hostUnit;
|
||||
|
||||
@ApiModelProperty("举办地址")
|
||||
private String address;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("举办开始时间")
|
||||
private Date holdTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("举办结束时间")
|
||||
private Date endTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("企业报名时间")
|
||||
private Date registrationTime;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.cms.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/** 招聘会企业签到列表项。 */
|
||||
@Data
|
||||
@ApiModel("招聘会企业签到列表项")
|
||||
public class OutdoorFairCompanyAttendanceVO
|
||||
{
|
||||
@ApiModelProperty("报名关系ID")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("招聘会ID")
|
||||
private Long fairId;
|
||||
|
||||
@ApiModelProperty("企业ID")
|
||||
private Long companyId;
|
||||
|
||||
@ApiModelProperty("企业名称")
|
||||
private String companyName;
|
||||
|
||||
@ApiModelProperty("企业行业")
|
||||
private String industry;
|
||||
|
||||
@ApiModelProperty("企业规模")
|
||||
private String scale;
|
||||
|
||||
@ApiModelProperty("联系人")
|
||||
private String contactPerson;
|
||||
|
||||
@ApiModelProperty("联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@ApiModelProperty("报名审核时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date reviewTime;
|
||||
|
||||
@ApiModelProperty("报名时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date registrationTime;
|
||||
|
||||
@ApiModelProperty("签到状态:0未签到,1已签到")
|
||||
private String attendanceStatus;
|
||||
|
||||
@ApiModelProperty("签到时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date checkInTime;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.cms.domain.query.CompanySearch;
|
||||
import com.ruoyi.cms.domain.vo.CompanyMissedOutdoorFairVO;
|
||||
import com.ruoyi.common.core.domain.entity.Company;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@@ -36,5 +37,8 @@ public interface CompanyMapper extends BaseMapper<Company>
|
||||
|
||||
int updateLcToLocalStatus(Company company);
|
||||
|
||||
List<Company> selectAdminCompanyList(Company company);
|
||||
List<Company> selectAdminCompanyList(CompanySearch company);
|
||||
|
||||
/** 查询企业未参加的已结束户外招聘会。 */
|
||||
List<CompanyMissedOutdoorFairVO> selectMissedOutdoorFairList(@Param("companyId") Long companyId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.OutdoorFairCompanyAttendance;
|
||||
import com.ruoyi.cms.domain.vo.OutdoorFairCompanyAttendanceVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** 户外招聘会企业签到记录 Mapper。 */
|
||||
public interface OutdoorFairCompanyAttendanceMapper extends BaseMapper<OutdoorFairCompanyAttendance>
|
||||
{
|
||||
/** 查询一场招聘会的企业签到列表。 */
|
||||
List<OutdoorFairCompanyAttendanceVO> selectCompanyAttendanceList(
|
||||
@Param("fairId") Long fairId,
|
||||
@Param("companyId") Long companyId,
|
||||
@Param("companyName") String companyName,
|
||||
@Param("checkedIn") Boolean checkedIn);
|
||||
}
|
||||
@@ -86,5 +86,5 @@ public interface ICompanyService
|
||||
|
||||
int companyUp(Long companyId);
|
||||
|
||||
List<Company> selectAdminCompanyList(Company company);
|
||||
List<Company> selectAdminCompanyList(CompanySearch company);
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Company> selectAdminCompanyList(Company company) {
|
||||
public List<Company> selectAdminCompanyList(CompanySearch company) {
|
||||
return companyMapper.selectAdminCompanyList(company);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="companyStatus" column="company_status" />
|
||||
<result property="isHrs" column="is_hrs" />
|
||||
<result property="lcUserid" column="lc_userid" />
|
||||
<result property="missedOutdoorFairCount" column="missed_outdoor_fair_count" />
|
||||
|
||||
<collection property="companyContactList" ofType="com.ruoyi.common.core.domain.entity.CompanyContact"
|
||||
resultMap="CompanyContactResult"/>
|
||||
@@ -53,7 +54,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectCompanyVo">
|
||||
select company_id, name, location, industry, scale, del_flag, create_by, create_time, update_by, update_time, remark,code,description,nature,company_nature,total_recruitment,registered_address,contact_person,contact_person_phone,is_abnormal,not_pass_reason,status,case when status='2' then update_time else null end reject_time,is_imp_company,imp_company_type,enterprise_type,legal_person,legal_id_card,legal_phone,is_hrs from company
|
||||
select company_id, name, location, industry, scale, del_flag, create_by, create_time, update_by, update_time, remark,code,description,nature,company_nature,total_recruitment,registered_address,contact_person,contact_person_phone,is_abnormal,not_pass_reason,status,case when status='2' then update_time else null end reject_time,is_imp_company,imp_company_type,enterprise_type,legal_person,legal_id_card,legal_phone,is_hrs,
|
||||
(select count(1)
|
||||
from shz.fair_company fc
|
||||
join shz.cms_outdoor_fair f on f.id = fc.job_fair_id and f.del_flag = '0'
|
||||
left join shz.cms_outdoor_fair_company_attendance a
|
||||
on a.fair_id = fc.job_fair_id and a.company_id = fc.company_id and a.del_flag = '0'
|
||||
where fc.company_id = c.company_id
|
||||
and fc.del_flag = '0'
|
||||
and fc.review_status = '1'
|
||||
and f.end_time < CURRENT_TIMESTAMP
|
||||
and coalesce(a.attendance_status, '0') <> '1') as missed_outdoor_fair_count
|
||||
from company c
|
||||
</sql>
|
||||
|
||||
<sql id="companyIndustryFilter">
|
||||
@@ -148,6 +160,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="endDate != null and endDate != ''">
|
||||
and create_time <= #{endDate}
|
||||
</if>
|
||||
<if test="missedOutdoorFairOnly == true">
|
||||
and exists (
|
||||
select 1
|
||||
from shz.fair_company fc
|
||||
join shz.cms_outdoor_fair f on f.id = fc.job_fair_id and f.del_flag = '0'
|
||||
left join shz.cms_outdoor_fair_company_attendance a
|
||||
on a.fair_id = fc.job_fair_id and a.company_id = fc.company_id and a.del_flag = '0'
|
||||
where fc.company_id = c.company_id
|
||||
and fc.del_flag = '0'
|
||||
and fc.review_status = '1'
|
||||
and f.end_time < CURRENT_TIMESTAMP
|
||||
and coalesce(a.attendance_status, '0') <> '1'
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
<select id="label" resultMap="CompanyResult">
|
||||
@@ -197,6 +223,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select t.company_id, t.name, t.location, t.industry, t.scale, t.del_flag, t.create_by, t.create_time, t.update_by, t.update_time, t.remark,t.code,t.description,
|
||||
t.nature,t.company_nature,t.total_recruitment,t.registered_address,t.contact_person,t.contact_person_phone,t.is_abnormal,t.not_pass_reason,t.status,case when t.status='2'
|
||||
then t.update_time else null end reject_time,t.is_imp_company,t.imp_company_type,t.enterprise_type,t.legal_person,t.legal_id_card,t.legal_phone,t.is_hrs,
|
||||
(select count(1)
|
||||
from shz.fair_company fc
|
||||
join shz.cms_outdoor_fair f on f.id = fc.job_fair_id and f.del_flag = '0'
|
||||
left join shz.cms_outdoor_fair_company_attendance a
|
||||
on a.fair_id = fc.job_fair_id and a.company_id = fc.company_id and a.del_flag = '0'
|
||||
where fc.company_id = t.company_id
|
||||
and fc.del_flag = '0'
|
||||
and fc.review_status = '1'
|
||||
and f.end_time < CURRENT_TIMESTAMP
|
||||
and coalesce(a.attendance_status, '0') <> '1') as missed_outdoor_fair_count,
|
||||
su.lc_userid,su.user_id,cct.contact_person as con_contact_person,cct.contact_person_phone as con_contact_person_phone,cct.company_id as con_company_id from company t
|
||||
left join sys_user su on t.code=su.id_card and su.del_flag='0'
|
||||
left join company_contact cct on t.company_id=cct.company_id and cct.del_flag='0'
|
||||
@@ -232,7 +268,47 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="endDate != null and endDate != ''">
|
||||
and t.create_time <= #{endDate}
|
||||
</if>
|
||||
<if test="missedOutdoorFairOnly == true">
|
||||
and exists (
|
||||
select 1
|
||||
from shz.fair_company fc
|
||||
join shz.cms_outdoor_fair f on f.id = fc.job_fair_id and f.del_flag = '0'
|
||||
left join shz.cms_outdoor_fair_company_attendance a
|
||||
on a.fair_id = fc.job_fair_id and a.company_id = fc.company_id and a.del_flag = '0'
|
||||
where fc.company_id = t.company_id
|
||||
and fc.del_flag = '0'
|
||||
and fc.review_status = '1'
|
||||
and f.end_time < CURRENT_TIMESTAMP
|
||||
and coalesce(a.attendance_status, '0') <> '1'
|
||||
)
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="selectMissedOutdoorFairList"
|
||||
parameterType="long"
|
||||
resultType="com.ruoyi.cms.domain.vo.CompanyMissedOutdoorFairVO">
|
||||
SELECT f.id AS fair_id,
|
||||
f.title,
|
||||
f.host_unit,
|
||||
f.address,
|
||||
f.hold_time,
|
||||
f.end_time,
|
||||
fc.create_time AS registration_time
|
||||
FROM shz.fair_company fc
|
||||
JOIN shz.cms_outdoor_fair f
|
||||
ON f.id = fc.job_fair_id
|
||||
AND f.del_flag = '0'
|
||||
LEFT JOIN shz.cms_outdoor_fair_company_attendance a
|
||||
ON a.fair_id = fc.job_fair_id
|
||||
AND a.company_id = fc.company_id
|
||||
AND a.del_flag = '0'
|
||||
WHERE fc.company_id = #{companyId}
|
||||
AND fc.del_flag = '0'
|
||||
AND fc.review_status = '1'
|
||||
AND f.end_time < CURRENT_TIMESTAMP
|
||||
AND COALESCE(a.attendance_status, '0') <> '1'
|
||||
ORDER BY f.end_time DESC, f.id DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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.OutdoorFairCompanyAttendanceMapper">
|
||||
|
||||
<resultMap id="OutdoorFairCompanyAttendanceResult"
|
||||
type="com.ruoyi.cms.domain.vo.OutdoorFairCompanyAttendanceVO">
|
||||
<id property="id" column="registration_id"/>
|
||||
<result property="fairId" column="fair_id"/>
|
||||
<result property="companyId" column="company_id"/>
|
||||
<result property="companyName" column="company_name"/>
|
||||
<result property="industry" column="industry"/>
|
||||
<result property="scale" column="scale"/>
|
||||
<result property="contactPerson" column="contact_person"/>
|
||||
<result property="contactPhone" column="contact_phone"/>
|
||||
<result property="reviewTime" column="review_time"/>
|
||||
<result property="registrationTime" column="registration_time"/>
|
||||
<result property="attendanceStatus" column="attendance_status"/>
|
||||
<result property="checkInTime" column="check_in_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectCompanyAttendanceList"
|
||||
resultMap="OutdoorFairCompanyAttendanceResult">
|
||||
SELECT fc.id AS registration_id,
|
||||
fc.job_fair_id AS fair_id,
|
||||
fc.company_id,
|
||||
c.name AS company_name,
|
||||
c.industry,
|
||||
c.scale,
|
||||
c.contact_person,
|
||||
c.contact_person_phone AS contact_phone,
|
||||
fc.review_time,
|
||||
fc.create_time AS registration_time,
|
||||
COALESCE(a.attendance_status, '0') AS attendance_status,
|
||||
a.check_in_time
|
||||
FROM shz.fair_company fc
|
||||
JOIN shz.company c ON c.company_id = fc.company_id AND c.del_flag = '0'
|
||||
LEFT JOIN shz.cms_outdoor_fair_company_attendance a
|
||||
ON a.fair_id = fc.job_fair_id
|
||||
AND a.company_id = fc.company_id
|
||||
AND a.del_flag = '0'
|
||||
WHERE fc.del_flag = '0'
|
||||
AND fc.job_fair_id = #{fairId}
|
||||
AND fc.review_status = '1'
|
||||
<if test="companyId != null">
|
||||
AND fc.company_id = #{companyId}
|
||||
</if>
|
||||
<if test="companyName != null and companyName != ''">
|
||||
AND c.name LIKE CONCAT('%', CAST(#{companyName} AS VARCHAR), '%')
|
||||
</if>
|
||||
<if test="checkedIn != null">
|
||||
<choose>
|
||||
<when test="checkedIn">
|
||||
AND COALESCE(a.attendance_status, '0') = '1'
|
||||
</when>
|
||||
<otherwise>
|
||||
AND COALESCE(a.attendance_status, '0') <> '1'
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
ORDER BY a.check_in_time DESC NULLS LAST, fc.id DESC
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -3,10 +3,12 @@ package com.ruoyi.cms.controller.app;
|
||||
import com.ruoyi.cms.domain.FairCompany;
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import com.ruoyi.cms.domain.OutdoorFairAttendee;
|
||||
import com.ruoyi.cms.domain.OutdoorFairCompanyAttendance;
|
||||
import com.ruoyi.cms.mapper.CompanyMapper;
|
||||
import com.ruoyi.cms.mapper.FairCompanyMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairCompanyAttendanceMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairJobMapper;
|
||||
import com.ruoyi.cms.service.IOutdoorFairAttendeeService;
|
||||
import com.ruoyi.cms.service.IAppUserService;
|
||||
@@ -158,6 +160,70 @@ class AppOutdoorFairControllerTest
|
||||
verify(attendeeService, never()).save(any(OutdoorFairAttendee.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void appCompanyCheckInRequiresCompanyUser() throws Exception
|
||||
{
|
||||
IOutdoorFairService fairService = mock(IOutdoorFairService.class);
|
||||
IOutdoorFairAttendeeService attendeeService = mock(IOutdoorFairAttendeeService.class);
|
||||
AppOutdoorFairController controller = controllerWith(fairService, attendeeService);
|
||||
AppUser appUser = appUser();
|
||||
|
||||
AjaxResult result = controller.companyCheckIn(12L, appUser);
|
||||
|
||||
assertEquals(500, result.get(AjaxResult.CODE_TAG));
|
||||
assertEquals("仅移动端企业可以签到", result.get(AjaxResult.MSG_TAG));
|
||||
verify(fairService, never()).getById(12L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void appCompanyCheckInCreatesAttendanceForApprovedCompany() throws Exception
|
||||
{
|
||||
IOutdoorFairService fairService = mock(IOutdoorFairService.class);
|
||||
IOutdoorFairAttendeeService attendeeService = mock(IOutdoorFairAttendeeService.class);
|
||||
CompanyMapper companyMapper = mock(CompanyMapper.class);
|
||||
FairCompanyMapper fairCompanyMapper = mock(FairCompanyMapper.class);
|
||||
OutdoorFairCompanyAttendanceMapper attendanceMapper = mock(OutdoorFairCompanyAttendanceMapper.class);
|
||||
OutdoorFair fair = fairWithTimes(
|
||||
new Date(System.currentTimeMillis() - 1_000L),
|
||||
new Date(System.currentTimeMillis() + 60_000L));
|
||||
Company company = new Company();
|
||||
company.setCompanyId(31L);
|
||||
company.setCode("CODE-31");
|
||||
company.setName("测试企业");
|
||||
company.setContactPerson("联系人");
|
||||
company.setContactPersonPhone("13800000000");
|
||||
FairCompany relation = new FairCompany();
|
||||
relation.setJobFairId(12L);
|
||||
relation.setCompanyId(31L);
|
||||
relation.setReviewStatus("1");
|
||||
AppUser appUser = appUser();
|
||||
appUser.setIsCompanyUser("0");
|
||||
appUser.setIdCard("CODE-31");
|
||||
|
||||
when(companyMapper.selectOne(any())).thenReturn(company);
|
||||
when(fairService.getById(12L)).thenReturn(fair);
|
||||
when(fairCompanyMapper.selectOne(any())).thenReturn(relation);
|
||||
when(attendanceMapper.selectOne(any())).thenReturn(null);
|
||||
when(attendanceMapper.insert(any(OutdoorFairCompanyAttendance.class))).thenReturn(1);
|
||||
|
||||
AppOutdoorFairController controller = controllerWith(fairService, attendeeService);
|
||||
setField(controller, "companyMapper", companyMapper);
|
||||
setField(controller, "fairCompanyMapper", fairCompanyMapper);
|
||||
setField(controller, "outdoorFairCompanyAttendanceMapper", attendanceMapper);
|
||||
|
||||
AjaxResult result = controller.companyCheckIn(12L, appUser);
|
||||
|
||||
assertEquals(200, result.get(AjaxResult.CODE_TAG));
|
||||
ArgumentCaptor<OutdoorFairCompanyAttendance> captor =
|
||||
ArgumentCaptor.forClass(OutdoorFairCompanyAttendance.class);
|
||||
verify(attendanceMapper).insert(captor.capture());
|
||||
OutdoorFairCompanyAttendance attendance = captor.getValue();
|
||||
assertEquals(12L, attendance.getFairId());
|
||||
assertEquals(31L, attendance.getCompanyId());
|
||||
assertEquals("1", attendance.getAttendanceStatus());
|
||||
assertTrue(attendance.getCheckInTime() != null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void publicDetailIncludesOnlySafeCompanyCardFields() throws Exception
|
||||
@@ -257,4 +323,11 @@ class AppOutdoorFairControllerTest
|
||||
fair.setHoldTime(holdTime);
|
||||
return fair;
|
||||
}
|
||||
|
||||
private OutdoorFair fairWithTimes(Date holdTime, Date endTime)
|
||||
{
|
||||
OutdoorFair fair = fairAt(holdTime);
|
||||
fair.setEndTime(endTime);
|
||||
return fair;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,31 @@ class OutdoorFairControllerTest
|
||||
assertEquals("@ss.hasPermi('cms:outdoorFair:unsubscribe')", annotation.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void companyCheckInEndpointRequiresDedicatedPermission() throws Exception
|
||||
{
|
||||
Method method = OutdoorFairController.class.getDeclaredMethod("checkInCompany", Long.class);
|
||||
org.springframework.security.access.prepost.PreAuthorize annotation =
|
||||
method.getAnnotation(org.springframework.security.access.prepost.PreAuthorize.class);
|
||||
|
||||
assertNotNull(annotation);
|
||||
assertEquals("@ss.hasPermi('cms:outdoorFair:companyCheckIn')", annotation.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void companyCheckInIsAllowedOnlyWithinFairTime()
|
||||
{
|
||||
OutdoorFair fair = fairWithTimes(2_000L, 3_000L);
|
||||
fair.setEndTime(new Date(3_000L));
|
||||
|
||||
assertEquals("招聘会还没有开始,暂不能签到",
|
||||
OutdoorFairController.validateCompanyCheckInTime(fair, new Date(1_999L)));
|
||||
assertNull(OutdoorFairController.validateCompanyCheckInTime(fair, new Date(2_000L)));
|
||||
assertNull(OutdoorFairController.validateCompanyCheckInTime(fair, new Date(3_000L)));
|
||||
assertEquals("招聘会已结束,不能签到",
|
||||
OutdoorFairController.validateCompanyCheckInTime(fair, new Date(3_001L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void companyQrCodeUrlUsesPublicForwardedHost() throws Exception
|
||||
{
|
||||
@@ -115,6 +140,7 @@ class OutdoorFairControllerTest
|
||||
OutdoorFair fair = new OutdoorFair();
|
||||
fair.setHoldTime(new Date(holdTime));
|
||||
fair.setApplyEndTime(new Date(applyEndTime));
|
||||
fair.setEndTime(new Date(applyEndTime + 1_000L));
|
||||
return fair;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user