看房预约管理
看房预约管理共有两个接口,分别是**根据条件分页查询预约信息**、**根据ID更新预约状态**,下面逐一实现
根据条件分页查询预约信息
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "预约看房管理")
@RequestMapping("/admin/appointment")
@RestController
public class ViewAppointmentController {
@Autowired
private ViewAppointmentService viewAppointmentService;
@Operation(summary = "分页查询预约信息")
@GetMapping("page")
public Result<IPage<AppointmentVo>> page(@RequestParam long current, @RequestParam long size, AppointmentQueryVo queryVo) {
IPage<AppointmentVo> page = new Page<>(current, size);
IPage<AppointmentVo> list = viewAppointmentService.pageAppointmentByQuery(page, queryVo);
return Result.ok(list);
}
}
package com.atguigu.lease.web.admin.service.impl;
/**
* @author liubo
* @description 针对表【view_appointment(预约看房信息表)】的数据库操作Service实现
* @createDate 2023-07-24 15:48:00
*/
@Service
public class ViewAppointmentServiceImpl extends ServiceImpl<ViewAppointmentMapper, ViewAppointment>
implements ViewAppointmentService {
@Autowired
private ViewAppointmentMapper viewAppointmentMapper;
@Override
public IPage<AppointmentVo> pageAppointmentByQuery(IPage<AppointmentVo> page, AppointmentQueryVo queryVo) {
return viewAppointmentMapper.pageAppointmentByQuery(page, queryVo);
}
}
<?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.atguigu.lease.web.admin.mapper.ViewAppointmentMapper">
<resultMap id="AppointmentVoMap" type="com.atguigu.lease.web.admin.vo.appointment.AppointmentVo" autoMapping="true">
<id property="id" column="id"/>
<association property="apartmentInfo" javaType="com.atguigu.lease.model.entity.ApartmentInfo" autoMapping="true">
<id property="id" column="apartment_id"/>
<result property="name" column="apartment_name"/>
<result property="phone" column="apartment_phone"/>
</association>
</resultMap>
<select id="pageAppointmentByQuery" resultMap="AppointmentVoMap">
select va.id,
va.user_id,
va.phone,
va.apartment_id,
va.appointment_time,
va.additional_info,
va.appointment_status,
ai.id as apartment_id,
ai.name as apartment_name,
ai.introduction,
ai.district_id,
ai.district_name,
ai.city_id,
ai.city_name,
ai.province_id,
ai.province_name,
ai.address_detail,
ai.latitude,
ai.longitude,
ai.phone as apartment_phone,
ai.is_release
from view_appointment va
left join apartment_info ai on va.apartment_id = ai.id and ai.is_deleted = 0
<where>
va.is_deleted = 0
<if test="queryVo.provinceId != null">
and ai.provinceId = #{queryVo.provinceId}
</if>
<if test="queryVo.cityId != null">
and ai.cityId = #{queryVo.cityId}
</if>
<if test="queryVo.districtId != null">
and ai.districtId = #{queryVo.districtId}
</if>
<if test="queryVo.apartmentId != null">
and va.apartmentId = #{queryVo.apartmentId}
</if>
<if test="queryVo.name != null and queryVo.name != ''">
and va.name like concat('%',#{queryVo.name},'%')
</if>
<if test="queryVo.phone != null and queryVo.phone != ''">
and va.phone like concat('%',#{queryVo.phone},'%')
</if>
</where>
</select>
</mapper>
接口测试: 日期存在问题, 格式需要调整, 且时区不正确
`ViewAppointment`实体类中的`appointmentTime`字段为`Date`类型,`Date`类型的字段在序列化成JSON字符串时,需要考虑两个点,分别是**格式**和**时区**。本项目使用JSON序列化框架为Jackson,具体配置如下
- 格式可按照字段单独配置,也可全局配置,下面分别介绍
- 单独配置
在指定字段增加`@JsonFormat`注解,如下
```java
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date appointmentTime;
```
- 全局配置
在`application.yml`中增加如下内容
```yml
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
```
- 时区同样可按照字段单独配置,也可全局配置,下面分别介绍
- 单独配置
在指定字段增加`@JsonFormat`注解,如下
```java
@JsonFormat(timezone = "GMT+8")
private Date appointmentTime;
```
- 全局配置
```yml
spring:
jackson:
time-zone: GMT+8
```
根据ID更新预约状态
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "预约看房管理")
@RequestMapping("/admin/appointment")
@RestController
public class ViewAppointmentController {
@Autowired
private ViewAppointmentService viewAppointmentService;
@Operation(summary = "根据id更新预约状态")
@PostMapping("updateStatusById")
public Result updateStatusById(@RequestParam Long id, @RequestParam AppointmentStatus status) {
LambdaUpdateWrapper<ViewAppointment> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(ViewAppointment::getId, id);
wrapper.set(ViewAppointment::getAppointmentStatus, status);
viewAppointmentService.update(wrapper);
return Result.ok();
}
}
租约管理
租约管理共有五个接口需要实现,除此之外,还需实现一个定时任务,用于检查租约是否到期以及修改到期状态。下面逐一实现
保存获更新租约信息
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "租约管理")
@RestController
@RequestMapping("/admin/agreement")
public class LeaseAgreementController {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Operation(summary = "保存或修改租约信息")
@PostMapping("saveOrUpdate")
public Result saveOrUpdate(@RequestBody LeaseAgreement leaseAgreement) {
leaseAgreementService.saveOrUpdate(leaseAgreement);
return Result.ok();
}
}
根据条件分页查询租约列表
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "租约管理")
@RestController
@RequestMapping("/admin/agreement")
public class LeaseAgreementController {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Operation(summary = "根据条件分页查询租约列表")
@GetMapping("page")
public Result<IPage<AgreementVo>> page(@RequestParam long current, @RequestParam long size, AgreementQueryVo queryVo) {
IPage<AgreementVo> page = new Page<>();
IPage<AgreementVo> result = leaseAgreementService.pageAgreementByQuery(page, queryVo);
return Result.ok(result);
}
}
package com.atguigu.lease.web.admin.service.impl;
/**
* @author liubo
* @description 针对表【lease_agreement(租约信息表)】的数据库操作Service实现
* @createDate 2023-07-24 15:48:00
*/
@Service
public class LeaseAgreementServiceImpl extends ServiceImpl<LeaseAgreementMapper, LeaseAgreement>
implements LeaseAgreementService {
@Autowired
private LeaseAgreementMapper leaseAgreementMapper;
@Override
public IPage<AgreementVo> pageAgreementByQuery(IPage<AgreementVo> page, AgreementQueryVo queryVo) {
return leaseAgreementMapper.pageAgreementByQuery(page, queryVo);
}
}
<?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.atguigu.lease.web.admin.mapper.LeaseAgreementMapper">
<resultMap id="AgreementVoMap" type="com.atguigu.lease.web.admin.vo.agreement.AgreementVo" autoMapping="true">
<association property="apartmentInfo" javaType="com.atguigu.lease.model.entity.ApartmentInfo"
autoMapping="true">
<id property="id" column="apartment_info_id"></id>
<result property="name" column="apartment_info_name"></result>
<result property="phone" column="apartment_info_phone"></result>
</association>
<association property="roomInfo" javaType="com.atguigu.lease.model.entity.RoomInfo"
autoMapping="true">
<id property="id" column="room_info_id"></id>
<result property="rent" column="room_info_rent"></result>
<result property="apartmentId" column="room_info_apartment_id"></result>
<result property="isRelease" column="room_info_is_release"></result>
</association>
<association property="paymentType" javaType="com.atguigu.lease.model.entity.PaymentType"
autoMapping="true">
<id property="id" column="payment_type_id"></id>
<result property="name" column="payment_type_name"></result>
<result property="additionalInfo" column="payment_type_additional_info"></result>
</association>
<association property="leaseTerm" javaType="com.atguigu.lease.model.entity.LeaseTerm"
autoMapping="true">
<id property="id" column="lease_term_id"></id>
<result property="monthCount" column="lease_term_month_count"></result>
</association>
</resultMap>
<select id="pageAgreementByQuery" resultMap="AgreementVoMap">
select la.id,
la.phone,
la.name,
la.identification_number,
la.apartment_id,
la.room_id,
la.lease_start_date,
la.lease_end_date,
la.lease_term_id,
la.rent,
la.deposit,
la.payment_type_id,
la.status,
la.source_type,
la.additional_info,
ai.id as apartment_info_id,
ai.name as apartment_info_name,
ai.introduction,
ai.district_id,
ai.district_name,
ai.city_name,
ai.city_id,
ai.province_name,
ai.province_id,
ai.address_detail,
ai.latitude,
ai.phone apartment_info_phone,
ai.is_release,
ri.id as room_info_id,
ri.room_number,
ri.rent as room_info_rent,
ri.apartment_id as room_info_apartment_id,
ri.is_release as room_info_is_release,
pt.id as payment_type_id,
pt.name as payment_type_name,
pt.pay_month_count,
pt.additional_info as payment_type_additional_info,
lt.id as lease_term_id,
lt.month_count as lease_term_month_count,
lt.unit
from lease_agreement la
left join apartment_info ai on ai.id = la.apartment_id and ai.is_deleted = 0
left join room_info ri on ri.id = la.room_id and ri.is_deleted = 0
left join payment_type pt on pt.id = la.payment_type_id and pt.is_deleted = 0
left join lease_term lt on lt.id = la.lease_term_id and lt.is_deleted = 0
<where>
la.is_deleted = 0
<if test="queryVo.provinceId != null">
and ai.province_id = #{queryVo.provinceId}
</if>
<if test="queryVo.cityId != null">
and ai.city_id = #{queryVo.cityId}
</if>
<if test="queryVo.districtId != null">
and ai.district_id = #{queryVo.districtId}
</if>
<if test="queryVo.apartmentId != null">
and la.apartment_id = #{queryVo.apartmentId}
</if>
<if test="queryVo.roomNumber != null">
and ri.room_number = #{queryVo.roomNumber}
</if>
<if test="queryVo.name != null and queryVo.name != ''">
and la.name = #{queryVo.name}
</if>
<if test="queryVo.phone != null and queryVo.phone != ''">
and la.phone = #{queryVo.phone}
</if>
</where>
</select>
</mapper>
根据ID查询租约信息
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "租约管理")
@RestController
@RequestMapping("/admin/agreement")
public class LeaseAgreementController {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Operation(summary = "根据id查询租约信息")
@GetMapping(name = "getById")
public Result<AgreementVo> getById(@RequestParam Long id) {
AgreementVo res = leaseAgreementService.getAgreementById(id);
return Result.ok(res);
}
}
package com.atguigu.lease.web.admin.service.impl;
/**
* @author liubo
* @description 针对表【lease_agreement(租约信息表)】的数据库操作Service实现
* @createDate 2023-07-24 15:48:00
*/
@Service
public class LeaseAgreementServiceImpl extends ServiceImpl<LeaseAgreementMapper, LeaseAgreement>
implements LeaseAgreementService {
@Autowired
private LeaseAgreementMapper leaseAgreementMapper;
@Autowired
ApartmentInfoService apartmentInfoService;
@Autowired
RoomInfoService roomInfoService;
@Autowired
PaymentTypeService paymentTypeService;
@Autowired
LeaseTermService leaseTermService;
@Override
public AgreementVo getAgreementById(Long id) {
LeaseAgreement leaseAgreement = leaseAgreementMapper.selectById(id);
ApartmentInfo apartmentInfo = apartmentInfoService.getById(leaseAgreement.getApartmentId());
RoomInfo roomInfo = roomInfoService.getById(leaseAgreement.getRoomId());
PaymentType paymentType = paymentTypeService.getById(leaseAgreement.getPaymentTypeId());
LeaseTerm leaseTerm = leaseTermService.getById(leaseAgreement.getLeaseTermId());
AgreementVo agreementVo = new AgreementVo();
BeanUtils.copyProperties(leaseAgreement, agreementVo);
agreementVo.setApartmentInfo(apartmentInfo);
agreementVo.setRoomInfo(roomInfo);
agreementVo.setPaymentType(paymentType);
agreementVo.setLeaseTerm(leaseTerm);
return agreementVo;
}
}
根据ID删除租约信息
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "租约管理")
@RestController
@RequestMapping("/admin/agreement")
public class LeaseAgreementController {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Operation(summary = "根据id删除租约信息")
@DeleteMapping("removeById")
public Result removeById(@RequestParam Long id) {
leaseAgreementService.removeById(id);
return Result.ok();
}
}
根据ID更新租约状态
package com.atguigu.lease.web.admin.controller.lease;
@Tag(name = "租约管理")
@RestController
@RequestMapping("/admin/agreement")
public class LeaseAgreementController {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Operation(summary = "根据id更新租约状态")
@PostMapping("updateStatusById")
public Result updateStatusById(@RequestParam Long id, @RequestParam LeaseStatus status) {
LambdaUpdateWrapper<LeaseAgreement> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(LeaseAgreement::getId, id);
wrapper.set(LeaseAgreement::getStatus, status);
leaseAgreementService.update(wrapper);
return Result.ok();
}
}
定时检查租约状态
本节内容是通过定时任务定时检查租约是否到期。SpringBoot内置了定时任务,具体实现如下。
- 启用Spring Boot定时任务
在SpringBoot启动类上增加`@EnableScheduling`注解,如下
@SpringBootApplication
@EnableScheduling
public class AdminWebApplication {
public static void main(String[] args) {
SpringApplication.run(AdminWebApplication.class, args);
}
}
- 编写定时逻辑
在**web-admin模块**下创建`com.atguigu.lease.web.admin.schedule.ScheduledTasks`类,内容如下
package com.atguigu.lease.web.admin.schedule;
@Component
public class ScheduledTasks {
@Autowired
private LeaseAgreementService leaseAgreementService;
@Scheduled(cron = "0 0 0 * * *") // 0秒0分0时每天每周每月执行
public void checkLeaseStatus() {
// 到期时间小于等于当前时间的租约状态改为到期
LambdaUpdateWrapper<LeaseAgreement> wrapper = new LambdaUpdateWrapper<>();
wrapper.le(LeaseAgreement::getLeaseEndDate, new Date());
wrapper.in(LeaseAgreement::getStatus, LeaseStatus.SIGNED, LeaseStatus.WITHDRAWING);
wrapper.set(LeaseAgreement::getStatus, LeaseStatus.EXPIRED);
leaseAgreementService.update(wrapper);
}
}
SpringBoot中的cron表达式语法如下
- 任务测试
package com.atguigu.lease.web.admin.schedule;
@SpringBootTest
class ScheduledTasksTest {
@Autowired
private ScheduledTasks scheduledTasks;
@Test
void checkLeaseStatus() {
scheduledTasks.checkLeaseStatus();
}
}