Commit 0b15fcd7 authored by 164003836@qq.con's avatar 164003836@qq.con

增加车辆管理项目

parent ba0ad127
HELP.md
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
/build/
### VS Code ###
.vscode/
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.wxiaoqi</groupId>
<artifactId>ace-security</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>vehicle</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>vehicle</name>
<description>车辆管理</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<!-- MyBatis Generator -->
<!-- Java接口和实体类 -->
<targetJavaProject>${basedir}/src/main/java</targetJavaProject>
<targetMapperPackage>com.xinxincaravan.caravan.vehicle.mapper
</targetMapperPackage>
<targetModelPackage>com.xinxincaravan.caravan.vehicle.entity
</targetModelPackage>
<!-- XML生成路径 -->
<targetResourcesProject>${basedir}/src/main/resources
</targetResourcesProject>
<targetXMLPackage>mapper</targetXMLPackage>
<!-- 依赖版本 -->
<mapper.version>3.4.0</mapper.version>
<mybatis.version>3.3.1</mybatis.version>
<mybatis.spring.version>1.2.4</mybatis.spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos相关配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<!--引入开源后台项目的公共包-->
<dependency>
<groupId>com.github.wxiaoqi</groupId>
<artifactId>ace-common</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.wxiaoqi</groupId>
<artifactId>ace-interface</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.wxiaoqi</groupId>
<artifactId>ace-auth-client</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<!-- 持久层 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 加入batis通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
<!-- 加入mybatis通用分页组件支持-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 此插件用来生成通用mapper的代码 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>
${basedir}/src/main/resources/builder/generatorConfig.xml
</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>${mapper.version}</version>
</dependency>
</dependencies>
</plugin>
<!--<plugin>-->
<!--<groupId>org.asciidoctor</groupId>-->
<!--<artifactId>asciidoctor-maven-plugin</artifactId>-->
<!--<version>1.5.3</version>-->
<!--<executions>-->
<!--<execution>-->
<!--<id>generate-docs</id>-->
<!--<phase>prepare-package</phase>-->
<!--<goals>-->
<!--<goal>process-asciidoc</goal>-->
<!--</goals>-->
<!--<configuration>-->
<!--<backend>html</backend>-->
<!--<doctype>book</doctype>-->
<!--</configuration>-->
<!--</execution>-->
<!--</executions>-->
<!--<dependencies>-->
<!--<dependency>-->
<!--<groupId>org.springframework.restdocs</groupId>-->
<!--<artifactId>spring-restdocs-asciidoctor</artifactId>-->
<!--</dependency>-->
<!--</dependencies>-->
<!--</plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.xinxincaravan.caravan.vehicle;
import com.github.wxiaoqi.security.auth.client.EnableAceAuthClient;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableDiscoveryClient
@EnableScheduling
@EnableAceAuthClient
@EnableFeignClients({"com.github.wxiaoqi.security.auth.client.feign"})
@MapperScan("com.xinxincaravan.caravan.vehicle.mapper")
public class VehicleApplication {
public static void main(String[] args) {
SpringApplication.run(VehicleApplication.class, args);
}
}
package com.xinxincaravan.caravan.vehicle.biz;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Lists;
import com.xinxincaravan.caravan.vehicle.entity.BranchCompany;
import com.xinxincaravan.caravan.vehicle.mapper.BranchCompanyMapper;
import com.xinxincaravan.caravan.vehicle.vo.BranchCompanyVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class BranchCompanyBiz extends BaseBiz<BranchCompanyMapper, BranchCompany> {
/**
* 按主键获取公司
* @param id
* @return
*/
public BranchCompany getById(Integer id){
return mapper.selectByPrimaryKey(id);
}
public Boolean exits(Integer id){
BranchCompany param = new BranchCompany();
param.setId(id);
return mapper.selectCount(param)>0;
}
/**
* 转换为vo类
* @param branchCompanies
* @returns
*/
private List<BranchCompanyVo> branchCompany2VO(List<BranchCompany> branchCompanies){
List<BranchCompanyVo> branchCompanyVoList = Lists.newArrayList();
if(CollectionUtils.isNotEmpty(branchCompanies)){
for(BranchCompany branchCompany:branchCompanies){
BranchCompanyVo branchCompanyVo = new BranchCompanyVo();
BeanUtils.copyProperties(branchCompany,branchCompanyVo);
branchCompanyVoList.add(branchCompanyVo);
}
}
return branchCompanyVoList;
}
public List<BranchCompany> getAll(){
return mapper.selectAll();
}
/**
* 增加公司,返回id
* @param branchCompanyVo
* @return
*/
public Integer add(BranchCompanyVo branchCompanyVo){
BranchCompany branchCompany = new BranchCompany();
BeanUtils.copyProperties(branchCompanyVo,branchCompany);
mapper.insertSelective(branchCompany);
return branchCompany.getId();
}
public void del(Integer id){
mapper.deleteByPrimaryKey(id);
}
/**
* 更新公司信息
* @param branchCompany
* @return
*/
public Integer update(BranchCompany branchCompany){
return mapper.updateByPrimaryKeySelective(branchCompany);
}
}
package com.xinxincaravan.caravan.vehicle.biz;
import com.alibaba.fastjson.JSON;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xinxincaravan.caravan.vehicle.common.CustomIllegalParamException;
import com.xinxincaravan.caravan.vehicle.constant.ConstantType;
import com.xinxincaravan.caravan.vehicle.constant.RedisKey;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import com.xinxincaravan.caravan.vehicle.mapper.ConstantMapper;
import com.xinxincaravan.caravan.vehicle.vo.ConstantVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class ConstantBiz extends BaseBiz<ConstantMapper,Constant> {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private TaskExecutor customTaskExecutor;
/**
* 每批次最大更新常量条目数
*/
public static final Integer MAX_BATCH_SIZE_CONSTANT_UPDATE = 1000;
/**
* 转换实体类为VO
* @param constant
* @return
*/
private ConstantVo constant2VO(Constant constant){
ConstantVo constantVo = new ConstantVo();
constantVo.setType(constant.getType());
constantVo.setCode(constant.getCode());
constantVo.setVal(constant.getVal());
return constantVo;
}
/**
* 获取对应redis中的hash的key
* @param type
* @return
*/
private String getConstantRedisKey(Integer type){
return RedisKey.CONSTANT_CACHE_PREFIX +type;
}
/**
* 查询所有类型下的常量数据,先从缓存读
* @param type
* @return
*/
public List<ConstantVo> getAllConstantByType(Integer type) {
String cacheConstantsJsonStr = String.valueOf(redisTemplate.opsForValue().get(getConstantRedisKey(type)));
Map<String,Object> constantMap = new HashMap<>();
if(StringUtils.isNotBlank(cacheConstantsJsonStr)){
constantMap = JSON.parseObject(cacheConstantsJsonStr);
}
List<ConstantVo> constantVoList = Lists.newArrayList();
//尝试从缓存中查询
if(MapUtils.isNotEmpty(constantMap)){
for(Map.Entry<String,Object> constantEntry:constantMap.entrySet()){
ConstantVo constant = new ConstantVo();
constant.setType(type);
constant.setCode(Integer.valueOf(constantEntry.getKey()));
constant.setVal(String.valueOf(constantEntry.getValue()));
constantVoList.add(constant);
}
return constantVoList;
}
//刷新缓存
refreshCacheAsync();
//缓存中不存在则从bd中查询
return getAllConstantByTypeNoCache(type);
}
/**
* 获取db中所有类型下的常量数据
* @param type
* @return
*/
public List<ConstantVo> getAllConstantByTypeNoCache(Integer type) {
List<ConstantVo> constantVoList = Lists.newArrayList();
Constant param = new Constant();
param.setType(type);
List<Constant> constantListFromDb= mapper.select(param);
if(CollectionUtils.isNotEmpty(constantListFromDb)){
for(Constant constant:constantListFromDb){
constantVoList.add(constant2VO(constant));
}
}
return constantVoList;
}
public void refreshCacheAsync(){
customTaskExecutor.execute(new Runnable() {
@Override
public void run() {
refreshCache();
}
});
}
/**
* 5分钟内刷新数据到缓存
*/
@Scheduled(cron = "0 */5 * * * *")//每5分钟刷新一次数据
public void refreshCache(){
log.info("刷新常量数据任务开始");
List<Integer> types = mapper.getAllConstantTypes();
for(Integer type : types){
log.info("刷新类型【"+type+"】常量数据任务开始");
//redis方式实现乐观锁
String redisLockKey = RedisKey.CONSTANT_REFRESH_LOCK_PREFIX +type+":"+(DateTime.now().getMinuteOfDay()/5);//同一日每5分钟只刷新一次
Boolean suc = redisTemplate.opsForValue().setIfAbsent(redisLockKey, String.valueOf(DateTime.now().getMillis()));
if(!suc){
continue;
}
redisTemplate.expire(redisLockKey,5, TimeUnit.MINUTES);//5分钟内过期
List<ConstantVo> constantVoList = getAllConstantByTypeNoCache(type);
if(CollectionUtils.isNotEmpty(constantVoList)){
Map<String,String> constantMap = new HashMap<>();
for(ConstantVo constantVo:constantVoList){
constantMap.put(String.valueOf(constantVo.getCode()),constantVo.getVal());
}
redisTemplate.opsForValue().set(getConstantRedisKey(type), JSON.toJSONString(constantMap));
}
log.info("刷新类型【"+type+"】常量数据任务完成");
}
log.info("刷新常量数据任务成功");
}
/**
* 检查批量操作批次大小是否合法
* @param constants
* @return
*/
private Boolean checkBatchSize(List<Constant> constants){
if(CollectionUtils.isEmpty(constants)){
return Boolean.FALSE;
}
if(constants.size()>MAX_BATCH_SIZE_CONSTANT_UPDATE){
throw new IllegalArgumentException(" exceed max batch size");
}
return Boolean.TRUE;
}
/**
* 批量更新常量
* @param type
* @param constants
*/
@Transactional
public Integer updateConstants(Integer type, List<Constant> constants) {
if(!checkBatchSize(constants)){
return 0;
}
Map<Integer,String> codeAndVal = Maps.newHashMap();
for(Constant constant:constants){
constant.setType(type);
Integer affected = mapper.updateByTypeAndCode(constant);
if(affected>0){
codeAndVal.put(constant.getCode(),constant.getVal());
}
}
return codeAndVal.size();
}
/**
* 删除常量
* @param type
* @param codes
*/
@Transactional
public Integer delConstant(Integer type, List<Integer> codes){
if(codes ==null||codes.size()==0){
return 0;
}
if(codes.size()>MAX_BATCH_SIZE_CONSTANT_UPDATE){
throw new IllegalArgumentException(" exceed max batch size");
}
List<String> delCodes = Lists.newArrayList();
for(Integer code:codes){
Constant param = new Constant();
param.setType(type);
param.setCode(code);
Integer affected = mapper.delByTypeAndCode(param);
if(affected>0){
delCodes.add(String.valueOf(code));
}
}
return delCodes.size();
}
/**
* 增加常量
* @param type
* @param constants
*/
public Integer addConstants(Integer type, List<Constant> constants){
if(!checkBatchSize(constants)){
return 0;
}
Map<String,String> codeAndVal = Maps.newHashMap();
for(Constant constant:constants){
constant.setType(type);
Integer affected = mapper.insertIgnoreOnDuplicate(constant);
if(affected>0){
codeAndVal.put(constant.getCode().toString(),constant.getVal());
}
}
return codeAndVal.size();
}
/**
* 检查常量是否已存在
* @param type
* @param code
* @return
*/
public Boolean checkIfExists(Integer type,Integer code){
if(!ConstantType.exists(type)){
throw new CustomIllegalParamException(" no such type of constant");
}
List<ConstantVo> constantVoList = getAllConstantByType(type);
if(CollectionUtils.isEmpty(constantVoList)){
throw new CustomIllegalParamException(" no such code of constant in relative type");
}
for(ConstantVo constantVo:constantVoList){
if(NumberUtils.compare(code,constantVo.getCode())==0){
return Boolean.TRUE;
}
}
throw new CustomIllegalParamException(" no such code of constant in relative type");
}
}
package com.xinxincaravan.caravan.vehicle.biz;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Lists;
import com.xinxincaravan.caravan.vehicle.common.CustomIllegalParamException;
import com.xinxincaravan.caravan.vehicle.constant.RedisKey;
import com.xinxincaravan.caravan.vehicle.constant.RegionType;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import com.xinxincaravan.caravan.vehicle.entity.SysRegion;
import com.xinxincaravan.caravan.vehicle.mapper.SysRegionMapper;
import com.xinxincaravan.caravan.vehicle.vo.ConstantVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class SysRegionBiz extends BaseBiz<SysRegionMapper, SysRegion> {
@Autowired
private RedisTemplate redisTemplate;//todo redis需要改为多实例
@Autowired
private TaskExecutor customTaskExecutor;
/**
* 国家没有父地区,其parentId为0
*/
private static final Long PARENT_ID_NONE = 0l;
//获取相应地区类型对应在id的位数,作为对应parent查找其下地区的redis key组成部分
private String getPrefixOfAgencyId(Integer type,Long parentId){
switch(type){
case -1:
return String.valueOf(-1);
case 0:
return String.valueOf(0);
case 1:
return String.valueOf(parentId).substring(0,2);
case 2:
return String.valueOf(parentId).substring(0,4);
default:
throw new CustomIllegalParamException("not valid region");
}
}
//获取相应地区类型对应在id的位数,作为对应parent查找其下地区的redis key组成部分
private String getPrefixOfAgencyId(Long parentId){
Integer type = getTypeFromId(parentId);
return getPrefixOfAgencyId(type,parentId);
}
/**
* 根据id获得所属类型
* @param id
* @return
*/
private Integer getTypeFromId(Long id){
if(id == 0){
return RegionType.ALL.getCode();
}if(id < 10){
return RegionType.COUNTRY.getCode();
}else if(id%100>0){//第1、2非零,即3级地区
return RegionType.TOWN.getCode();
}else if(id%10000>0){//第1、2为零,第3、4位非0,即2级地区
return RegionType.CITY.getCode();
}else{//第1、2、3、4为零,第5、6位非0,即2级地区
return RegionType.PROVINCE.getCode();
}
}
/**
* 获取对应redis中的hash的key
* @param parentId
* @return
*/
private String getCacheRedisKey(Long parentId){
//获取相应地区类型对应在agencyId的位数
return RedisKey.SYS_REGION_CACHE_PREFIX +getPrefixOfAgencyId(parentId);
}
/**
* 查询对应地区之下的地区
* @param id
* @return
*/
public List<SysRegion> getSonRegion(Long id){
//从缓存中查询
String redisKey = getCacheRedisKey(id);
String sysRegionListJson = String.valueOf(redisTemplate.opsForValue().get(redisKey));
List<SysRegion> sysRegions = null;
if(StringUtils.isNotBlank(sysRegionListJson)){
sysRegions = JSONObject.parseArray(sysRegionListJson,SysRegion.class);
}
if(CollectionUtils.isNotEmpty(sysRegions)){
return sysRegions;
}
//不存在则异步开启刷新缓存任务
refreshCacheAsync();
//从db中查询
return getSonRegionNoCache(id);
}
public List<SysRegion> getSonRegionNoCache(Long id){
//从db中查询
SysRegion param = new SysRegion();
param.setParentId(id);
return mapper.select(param);
}
public void refreshCacheAsync(){
customTaskExecutor.execute(new Runnable() {
@Override
public void run() {
refreshCache();
}
});
}
/**
* 刷新其孩子节点到缓存,并对其孩子迭代执行此操作
* @param id
*/
private void refreshCacheRegionAndSon(Long id){
List<SysRegion> sonRegions = getSonRegionNoCache(id);
//把当前节点的子节点数据缓存
String redisKey = getCacheRedisKey(id);
redisTemplate.opsForValue().set(redisKey,JSON.toJSON(sonRegions).toString());
log.info("完成地区【"+id+"】的子地区数据缓存");
if(CollectionUtils.isEmpty(sonRegions) || getTypeFromId(id).equals(RegionType.CITY.getCode())){
return;
}
for(SysRegion sonRegion:sonRegions){
refreshCacheRegionAndSon(sonRegion.getId());
}
}
/**
* 5分钟内刷新数据到缓存
*/
@Scheduled(cron = "0 */5 * * * *")//每5分钟刷新一次数据
public void refreshCache(){
String redisLockKey = RedisKey.SYS_REGION_REFRESH_LOCK +(DateTime.now().getMinuteOfDay()/5);//同一日每5分钟只刷新一次
Boolean suc = redisTemplate.opsForValue().setIfAbsent(redisLockKey, String.valueOf(DateTime.now().getMillis()));
if(!suc){
log.info("刷新地区数据:获取乐观锁失败,不执行任务");
return;
}
log.info("刷新地区数据任务开始");
refreshCacheRegionAndSon(PARENT_ID_NONE);
log.info("刷新常量数据任务成功");
}
}
package com.xinxincaravan.caravan.vehicle.biz;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Maps;
import com.xinxincaravan.caravan.vehicle.constant.RedisKey;
import com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo;
import com.xinxincaravan.caravan.vehicle.mapper.VehicleBookInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class VehicleBookInfoBiz extends BaseBiz<VehicleBookInfoMapper, VehicleBookInfo> {
public static final String TB_NAME_PREFIX = "vehicle_book_info_his_";
public static final DateTimeFormatter YEAR_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy");
public static final DateTimeFormatter YEARMONTH_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM");
public static final Integer DEL_BATCH_SIZE = 1000;
public static final Integer COPY_BATCH_SIZE = 100;
@Autowired
private RedisTemplate redisTemplate;
/**
* 迁移数据到历史表
* 每年一张表
*/
@Scheduled(cron = "0 0 0 1 * ?")//每月1号0点触发
@Transactional
public void transfer2HistoryTb(){
//获取表格名称
String tbName = getTbNameNow();
DateTime now = DateTime.now();//当前获取的时间为标准
log.info("开始预定信息迁移至历史表的定时任务。");
//每月初将上月数据复制到历史表
Boolean needRun= copyDataLastMoth(now,tbName);
if(needRun) {
//每月初将上上月数据从当前信息表中删除
delDataTheMonthBeforeLast(now, tbName);
}
}
/**
* 获取上月数据,并复制到历史表
*/
@Transactional
public Boolean copyDataLastMoth(DateTime now,String tbName){
String lastMonthStr = now.plusMonths(-1).toString(YEARMONTH_DATE_TIME_FORMATTER);
String redisKey = RedisKey.DEL_BOOK_INFO_LOCK_PREFIX +lastMonthStr;
Boolean hasSuc = redisTemplate.opsForValue().setIfAbsent(redisKey,String.valueOf(DateTime.now().getMillis()));
if(hasSuc){//设置1天后过期
redisTemplate.expire(redisKey,1, TimeUnit.DAYS);
}else{
log.info("[预定信息迁移]乐观锁获取失败,该线程不执行任务。");
return Boolean.FALSE;
}
createTbIfNotExists(tbName);
//逐页查出数据
Integer curPageNo = 1;
List<VehicleBookInfo> vehicleBookInfoList = null;
do {
Map<String, Object> params = Maps.newHashMap();
params.put("yearMonth", lastMonthStr);
params.put("pageStart", (curPageNo - 1) * COPY_BATCH_SIZE);
params.put("pageSize", COPY_BATCH_SIZE);
vehicleBookInfoList = mapper.getByPage4YearMonth(params);
if(CollectionUtils.isNotEmpty(vehicleBookInfoList)){
//插入数据到历史表
for(VehicleBookInfo vehicleBookInfo : vehicleBookInfoList){
Map<String, Object> insertHisParams = Maps.newHashMap();
insertHisParams.put("tbName", tbName);
insertHisParams.put("id", vehicleBookInfo.getId());
insertHisParams.put("vehicle", vehicleBookInfo.getVehicle());
insertHisParams.put("yearMonth", vehicleBookInfo.getYearMonth());
insertHisParams.put("bookedDate", vehicleBookInfo.getBookedDate());
mapper.insertHis(insertHisParams);
}
}
curPageNo++;
log.info("【复制上月预定信息至历史表中】,当前复制页【"+curPageNo+"】,页大小【"+COPY_BATCH_SIZE+"】");
}while(CollectionUtils.isNotEmpty(vehicleBookInfoList));
log.info("复制上月预定信息至历史表中完成,总页数【"+(curPageNo-1)+"】");
; return Boolean.TRUE;
}
/**
* 删除上上月数据
*/
@Transactional
public void delDataTheMonthBeforeLast(DateTime now,String tbName){
String theMonthBeforeLastStr = now.plusMonths(-2).toString(YEARMONTH_DATE_TIME_FORMATTER);
Integer effected = 0;
Integer total = 0;
Map<String, Object> params = Maps.newHashMap();
params.put("yearMonth", theMonthBeforeLastStr);
params.put("batchSize", DEL_BATCH_SIZE);
do {
effected = mapper.del4YearMoth(params);
total+=effected;
log.info("开始删除预定信息数据,删除总数【"+total+"】");
}while(effected!=0);
log.info("删除预定信息数据完成");
}
private String getTbNameNow(){
return TB_NAME_PREFIX+ DateTime.now().toString(YEAR_DATE_TIME_FORMATTER);
}
/**
* 创建当年相关表格
*/
private void createTbIfNotExists(String tbName){
mapper.createTbIfNotExists(tbName);
}
}
package com.xinxincaravan.caravan.vehicle.biz;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Maps;
import com.xinxincaravan.caravan.vehicle.constant.RedisKey;
import com.xinxincaravan.caravan.vehicle.entity.VehicleBookRecord;
import com.xinxincaravan.caravan.vehicle.mapper.VehicleBookRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Slf4j
public class VehicleBookRecordBiz extends BaseBiz<VehicleBookRecordMapper, VehicleBookRecord> {
public static final String TB_NAME_PREFIX = "vehicle_book_record_his_";
public static final DateTimeFormatter YEAR_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy");
public static final DateTimeFormatter YEARMONTH_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM");
public static final Integer DEL_BATCH_SIZE = 1000;
public static final Integer COPY_BATCH_SIZE = 100;
@Autowired
private RedisTemplate redisTemplate;
/**
* 迁移数据到历史表
* 每年一张表
*/
@Scheduled(cron = "0 0 1 1 * ?")//每月1号1点触发
@Transactional
public void transfer2HistoryTb(){
//获取表格名称
String tbName = getTbNameNow();
DateTime now = DateTime.now();//当前获取的时间为标准
log.info("开始预定记录迁移至历史表的定时任务。");
Boolean needRun= copyDataLastMoth(now,tbName);
if(needRun) {
//每月初将上上月数据从当前信息表中删除
delDataTheMonthBeforeLast(now, tbName);
}
}
/**
* 获取上月数据,并复制到历史表
*/
@Transactional
public Boolean copyDataLastMoth(DateTime now,String tbName){
String lastMonthStr = now.plusMonths(-1).toString(YEARMONTH_DATE_TIME_FORMATTER);
String redisKey = RedisKey.DEL_BOOK_RECORD_LOCK_PREFIX +lastMonthStr;
Boolean hasSuc = redisTemplate.opsForValue().setIfAbsent(redisKey,String.valueOf(DateTime.now().getMillis()));
if(hasSuc){//设置1天后过期
redisTemplate.expire(redisKey,1, TimeUnit.DAYS);
}else{
log.info("[预定记录迁移]乐观锁获取失败,该线程不执行任务。");
return Boolean.FALSE;
}
createTbIfNotExists(tbName);
//逐页查出数据
Integer curPageNo = 1;
List<VehicleBookRecord> vehicleBookRecords = null;
do {
Map<String, Object> params = Maps.newHashMap();
params.put("startDate", now.plusMonths(-1).withMillisOfDay(0).toDate());
params.put("endDate", now.plusDays(-1).withMillisOfDay(0).toDate());
params.put("pageStart", (curPageNo - 1) * COPY_BATCH_SIZE);
params.put("pageSize", COPY_BATCH_SIZE);
vehicleBookRecords = mapper.getByPage4Month(params);
if(CollectionUtils.isNotEmpty(vehicleBookRecords)){
//插入数据到历史表
for(VehicleBookRecord vehicleBookRecord : vehicleBookRecords){
Map<String, Object> insertHisParams = Maps.newHashMap();
insertHisParams.put("tbName", tbName);
insertHisParams.put("id", vehicleBookRecord.getId());
insertHisParams.put("vehicle", vehicleBookRecord.getVehicle());
insertHisParams.put("status", vehicleBookRecord.getStatus());
insertHisParams.put("bookType", vehicleBookRecord.getBookType());
insertHisParams.put("bookUser", vehicleBookRecord.getBookUser());
insertHisParams.put("contactInfo", vehicleBookRecord.getContactInfo());
insertHisParams.put("bookStartDate", vehicleBookRecord.getBookStartDate());
insertHisParams.put("bookEndDate", vehicleBookRecord.getBookEndDate());
insertHisParams.put("liftLocation", vehicleBookRecord.getLiftLocation());
insertHisParams.put("liftAddr", vehicleBookRecord.getLiftAddr());
insertHisParams.put("remark", vehicleBookRecord.getRemark());
insertHisParams.put("destination", vehicleBookRecord.getDestination());
insertHisParams.put("reviewerApply", vehicleBookRecord.getReviewerApply());
insertHisParams.put("reviewerReturn", vehicleBookRecord.getReviewerReturn());
insertHisParams.put("reviewerCancel", vehicleBookRecord.getReviewerCancel());
insertHisParams.put("actualStartDate", vehicleBookRecord.getActualStartDate());
insertHisParams.put("actualEndDate", vehicleBookRecord.getActualEndDate());
mapper.insertHis(insertHisParams);
}
}
curPageNo++;
log.info("【复制上月预定记录至历史表中】,当前复制页【"+curPageNo+"】,页大小【"+COPY_BATCH_SIZE+"】");
}while(CollectionUtils.isNotEmpty(vehicleBookRecords));
log.info("复制上月预定记录至历史表中完成,总页数【"+(curPageNo-1)+"】");
; return Boolean.TRUE;
}
/**
* 删除上上月数据
*/
@Transactional
public void delDataTheMonthBeforeLast(DateTime now,String tbName){
String theMonthBeforeLastStr = now.plusMonths(-2).toString(YEARMONTH_DATE_TIME_FORMATTER);
Integer effected = 0;
Integer total = 0;
Map<String, Object> params = Maps.newHashMap();
params.put("startDate", now.plusMonths(-2).withMillisOfDay(0).toDate());
params.put("endDate", now.plusMonths(-1).plusDays(-1).withMillisOfDay(0).toDate());
params.put("batchSize", DEL_BATCH_SIZE);
do {
effected = mapper.del4YearMoth(params);
total+=effected;
log.info("开始删除预定记录数据,删除总数【"+total+"】");
}while(effected!=0);
log.info("删除预定记录数据完成");
}
private String getTbNameNow(){
return TB_NAME_PREFIX+ DateTime.now().toString(YEAR_DATE_TIME_FORMATTER);
}
/**
* 创建当年相关表格
*/
private void createTbIfNotExists(String tbName){
mapper.createTbIfNotExists(tbName);
}
}
package com.xinxincaravan.caravan.vehicle.common;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class BaseController<Biz extends BaseBiz> {
@Autowired
protected HttpServletRequest request;
@Autowired
protected Biz baseBiz;
}
package com.xinxincaravan.caravan.vehicle.common;
public class CustomIllegalParamException extends RuntimeException {
public CustomIllegalParamException(String msg){
super(msg);
}
}
package com.xinxincaravan.caravan.vehicle.common;
/**
* 以Integer代表布尔值时使用
*/
public class Int4Boolean {
public static final Integer TRUE = 1;
public static final Integer FALSE = 0;
}
package com.xinxincaravan.caravan.vehicle.common;
import com.github.wxiaoqi.security.common.msg.BaseResponse;
public class RestResponse<T> extends BaseResponse {
public static final Integer SUC_CODE = 1;
T data;
Integer code;
public RestResponse(){
code = SUC_CODE;
}
public static <M> RestResponse<M> sucResponse(){
return new RestResponse<M>();
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public static <M> RestResponse<M> data(M data){
RestResponse<M> restResponse = new RestResponse<M>();
restResponse.setData(data);
return restResponse;
}
public static <M> RestResponse<M> suc(){
return new RestResponse<M>();
}
public static <M> RestResponse<M> code(Integer code){
RestResponse<M> restResponse = new RestResponse<M>();
restResponse.setCode(code);
return restResponse;
}
public static <M> RestResponse<M> codeAndMessage(Integer code,String msg){
RestResponse<M> restResponse = new RestResponse<M>();
restResponse.setCode(code);
restResponse.setMessage(msg);
return restResponse;
}
}
package com.xinxincaravan.caravan.vehicle.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* ${DESCRIPTION}
*
* @author wanghaobin
* @create 2017-06-21 8:39
*/
@Configuration
@Primary
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(stringSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
package com.xinxincaravan.caravan.vehicle.config;
import com.github.wxiaoqi.security.auth.client.interceptor.ServiceAuthRestInterceptor;
import com.github.wxiaoqi.security.auth.client.interceptor.UserAuthRestInterceptor;
import com.github.wxiaoqi.security.common.handler.GlobalExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.Collections;
/**
*
*/
@Configuration("vehicleWebConfig")
@Primary
public class WebConfiguration implements WebMvcConfigurer {
@Bean
GlobalExceptionHandler getGlobalExceptionHandler() {
return new GlobalExceptionHandler();
}
/**
* 加入拦截器,介入相关权限验证(服务+用户)
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getServiceAuthRestInterceptor()).
addPathPatterns(getIncludePathPatterns());
registry.addInterceptor(getUserAuthRestInterceptor()).
addPathPatterns(getIncludePathPatterns());
}
@Bean
ServiceAuthRestInterceptor getServiceAuthRestInterceptor() {
return new ServiceAuthRestInterceptor();
}
@Bean
UserAuthRestInterceptor getUserAuthRestInterceptor() {
return new UserAuthRestInterceptor();
}
/**
* 需要用户和服务认证判断的路径
* @return
*/
private ArrayList<String> getIncludePathPatterns() {
ArrayList<String> list = new ArrayList<>();
String[] urls = {
"/vehicleInfo/**"
};
Collections.addAll(list, urls);
return list;
}
/**
* 增加执行异步任务的自定义线程池执行器
* @return
*/
@Bean(name = "customTaskExecutor")
TaskExecutor getTaskExecutor(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(5);// 线程池维护线程的最少数量
threadPoolTaskExecutor.setMaxPoolSize(10);// 线程池维护线程的最大数量
threadPoolTaskExecutor.setQueueCapacity(50);// 缓存队列
return threadPoolTaskExecutor;
}
}
package com.xinxincaravan.caravan.vehicle.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum BookType {
USER_RENT(1,"用户租赁"),
EMPLOYEE_APPLY(2,"内部员工申请"),
REPAIRING(3,"维修"),
;
/**
* 编码
*/
private Integer code;
/**
* 类型描述
*/
private String desc;
private static Map<Integer,String> codeAndDesc = Maps.newHashMap();
static{
for(BookType constantType : BookType.values()){
codeAndDesc.put(constantType.getCode(),constantType.getDesc());
}
}
BookType(Integer code, String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static Boolean exists(Integer code){
return codeAndDesc.containsKey(code);
}
}
package com.xinxincaravan.caravan.vehicle.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum ConstantType {
VEHICLE_BRAND(1,"车辆品牌"),
VEHICLE_USE(2,"车辆用途"),
;
/**
* 编码
*/
private Integer code;
/**
* 类型描述
*/
private String desc;
private static Map<Integer,String> codeAndDesc = Maps.newHashMap();
static{
for(ConstantType constantType :ConstantType.values()){
codeAndDesc.put(constantType.getCode(),constantType.getDesc());
}
}
ConstantType(Integer code,String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static Boolean exists(Integer code){
return codeAndDesc.containsKey(code);
}
}
package com.xinxincaravan.caravan.vehicle.constant;
public class RedisKey {
/**
* 常量缓存key前缀
*/
public static final String CONSTANT_CACHE_PREFIX ="cache:constant:";
/**
* 地区常量缓存key前缀
*/
public static final String SYS_REGION_CACHE_PREFIX ="cache:sysRegion:";
/**
* 刷新常量缓存乐观锁前缀
*/
public static final String CONSTANT_REFRESH_LOCK_PREFIX ="lock:constant:";
/**
* 地区常量缓存key前缀
*/
public static final String SYS_REGION_REFRESH_LOCK ="lock:sysRegion:";
/**
* 迁移预定信息rediseky
*/
public static final String DEL_BOOK_INFO_LOCK_PREFIX ="lock:del:bookInfo:";
/**
* 迁移预定记录rediseky
*/
public static final String DEL_BOOK_RECORD_LOCK_PREFIX ="lock:del:bookRecord:";
}
package com.xinxincaravan.caravan.vehicle.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum RegionType {
ALL(-1,"全国"),//这一类型不存在db中,只是用于查询所有国家
COUNTRY(0,"国家"),
PROVINCE(1,"省/直辖市"),
CITY(2,"市"),
TOWN(3,"镇/县"),
;
/**
* 编码
*/
private Integer code;
/**
* 类型描述
*/
private String desc;
private static Map<Integer,String> codeAndDesc = Maps.newHashMap();
static{
for(RegionType constantType : RegionType.values()){
codeAndDesc.put(constantType.getCode(),constantType.getDesc());
}
}
RegionType(Integer code, String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static Boolean exists(Integer code){
return codeAndDesc.containsKey(code);
}
}
package com.xinxincaravan.caravan.vehicle.constant.ResCode;
public enum ResCode {
AUTH_FAIL(-1,"权限验证不通过"),
INVALID_REST_REQ_PARAM(100000,"rest请求参数非法"),
//车辆信息相关返回码-预定信息
VEHICLE_BOOKED_INFO_ALREADY_CHANGED(101001,"车辆预定信息已更改,请刷新后继续操作"),
//车辆信息相关返回码-车辆信息
VEHICLE_INFO_SAME_NUM_PLATE_EXISTS(102001,"该车牌车辆已经存在"),
VEHICLE_INFO_BRANCH_NOT_EXIST(102002,"分公司信息非法"),
//车辆信息相关返回码-预定申请信息
VEHICLE_BOOKED_RECORD_ALREADY_CHANGED(103001,"车辆预定申请已被审批,请刷新后继续操作"),
;
/**
* 返回码
*/
private Integer code;
/**
* 描述
*/
private String desc;
ResCode(Integer code, String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.xinxincaravan.caravan.vehicle.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum VehicleBookRecordStatus {
APPLY(1,"申请中"),
APPROVE(2,"已通过"),
RETURNED(3,"已归还"),
REJECTED(4,"拒绝"),
RETURNED_OUT_DATE(5,"逾期归还"),
CANCEL_APPLY(6,"取消预订"),
;
/**
* 编码
*/
private Integer code;
/**
* 类型描述
*/
private String desc;
private static Map<Integer,String> codeAndDesc = Maps.newHashMap();
static{
for(VehicleBookRecordStatus constantType : VehicleBookRecordStatus.values()){
codeAndDesc.put(constantType.getCode(),constantType.getDesc());
}
}
VehicleBookRecordStatus(Integer code, String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static Boolean exists(Integer code){
return codeAndDesc.containsKey(code);
}
}
package com.xinxincaravan.caravan.vehicle.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum VehicleStatus {
NORMAL(1,"正常运行"),
REPAIRING(2,"维修"),
DISCARD(3,"报废"),
;
/**
* 编码
*/
private Integer code;
/**
* 类型描述
*/
private String desc;
private static Map<Integer,String> codeAndDesc = Maps.newHashMap();
static{
for(VehicleStatus constantType : VehicleStatus.values()){
codeAndDesc.put(constantType.getCode(),constantType.getDesc());
}
}
VehicleStatus(Integer code, String desc){
this.code=code;
this.desc=desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public static Boolean exists(Integer code){
return codeAndDesc.containsKey(code);
}
}
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "branch_company")
@Data
public class BranchCompany {
@Id
@GeneratedValue(generator = "JDBC")
private Integer id;
/**
* 分公司名称
*/
private String name;
/**
* 分支机构类型
*/
@Column(name = "branch_type")
private Integer branchType;
/**
* 分支机构所属机构
*/
@Column(name = "subordinate_branch")
private Integer subordinateBranch;
/**
* 分支机构地址:经纬度
*/
private String location;
/**
* 地址-省/直辖市(编码)
*/
@Column(name = "addr_province")
private Integer addrProvince;
/**
* 地址-市(编码)
*/
@Column(name = "addr_city")
private Integer addrCity;
/**
* 地址-镇/县(编码)
*/
@Column(name = "addr_town")
private Integer addrTown;
/**
* 详细地址
*/
@Column(name = "addr_detail")
private String addrDetail;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Data
public class Constant {
@Id
@GeneratedValue(generator = "JDBC")
private Integer id;
/**
* 常量类型
*/
private Integer type;
/**
* 常量编码
*/
private Integer code;
/**
* 值
*/
private String val;
}
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
@Data
public class SysRegion {
private Long id;
/**
* 所属父地区id
*/
private Long parentId;
private String name;
/**
* 地区类型 0-国家 1-省/直辖市 2-市 3 - 镇、县
*/
private Integer type;
/**
* 从左往右,第1,2位代表省代码,3、4为代表市代码,5-6位代表镇或县代码
*/
private Integer agencyId;
}
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
@Data
public class Vehicle {
/**
* 主键(uuid)
*/
@Id
private String id;
/**
* 车辆编号,0-没有
*/
private Integer code;
/**
* 车辆状态: 1-正常运行 2-维修 3-报废
*/
private Integer status;
/**
* 车牌号,空字符串-没有
*/
@Column(name = "number_plate")
private String numberPlate;
/**
* 品牌(编码,对应关系见相关常量),0-未填写
*/
private Integer brand;
/**
* 所属分支机构(id)
*/
@Column(name = "subordinate_branch")
private Integer subordinateBranch;
/**
* 用途类型:租赁房车(1)、展车等,对应关系见车辆常量表
*/
@Column(name = "use_type")
private Integer useType;
/**
* 备注信息
*/
private String remark;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "vehicle_book_info")
@Data
public class VehicleBookInfo {
@Id
private Long id;
/**
* 车辆id
*/
private String vehicle;
/**
* 预定信息所属年月(格式yyyy-MM)
*/
@Column(name = "year_month")
private String yearMonth;
/**
* 预定信息,int格式保存,当作位图使用(从左到右每位代表每个月1-31号)
*/
@Column(name = "booked_date")
private Integer bookedDate;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.entity;
import lombok.Data;
import java.util.Date;
import javax.persistence.*;
@Table(name = "vehicle_book_record")
@Data
public class VehicleBookRecord {
/**
* 主键
*/
@Id
private Long id;
/**
* 车辆id
*/
private String vehicle;
/**
* 申请状态:1-申请中 2-已通过 3-已归还 4-拒绝 5-逾期归还
*/
private Integer status;
/**
* 预定类型,1-用户租赁、2-分公司使用、3-维修
*/
@Column(name = "book_type")
private Integer bookType;
/**
* 预定用户id,对应menberinfo表中的id
*/
@Column(name = "book_user")
private Integer bookUser;
/**
* 联系信息,比如电话、联系人姓名等(json)
*/
@Column(name = "contact_info")
private String contactInfo;
/**
* 申请开始日期
*/
@Column(name = "book_start_date")
private Date bookStartDate;
/**
* 提车地点(经纬度)
*/
@Column(name = "lift_location")
private String liftLocation;
/**
* 提车地址
*/
@Column(name = "lift_addr")
private String liftAddr;
private String remark;
/**
* 目的地
*/
private String destination;
/**
* 申请审核人,-1代表系统
*/
@Column(name = "reviewer_apply")
private Integer reviewerApply;
/**
* 申请审核人,-1代表系统
*/
@Column(name = "reviewer_return")
private Integer reviewerReturn;
/**
* 取消人,-1代表系统
*/
@Column(name = "reviewer_cancel")
private Integer reviewerCancel;
/**
* 申请结束日期
*/
@Column(name = "book_end_date")
private Date bookEndDate;
/**
* 实际开始日期
*/
@Column(name = "actual_start_date")
private Date actualStartDate;
/**
* 实际结束日期
*/
@Column(name = "actual_end_date")
private Date actualEndDate;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.BranchCompany;
import tk.mybatis.mapper.common.Mapper;
public interface BranchCompanyMapper extends Mapper<BranchCompany> {
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
public interface ConstantMapper extends Mapper<Constant> {
public List<Integer> getAllConstantTypes();
public int updateByTypeAndCode(Constant constant);
public int delByTypeAndCode(Constant constant);
/**
* 插入重复时则忽略
* @param constant
* @return
*/
public int insertIgnoreOnDuplicate(Constant constant);
}
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import com.xinxincaravan.caravan.vehicle.entity.SysRegion;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;
public interface SysRegionMapper extends Mapper<SysRegion> {
public List<Integer> getAllByPage(Map<String,Object> params);
}
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;
public interface VehicleBookInfoMapper extends Mapper<VehicleBookInfo> {
/**
* 根据车辆id和对应年月查询预定记录
* @param params
* @return
*/
public List<VehicleBookInfo> getByVehicleIdAndYearMonth(Map<String,Object> params);
/**
* 不存在插入、存在更新
* @param vehicleBookInfo
* @return
*/
public Integer insertIgnore(VehicleBookInfo vehicleBookInfo);
/**
* 更新预定信息,如果位操作正确的话(以此实现未预定才预定,已预定才可取消)
* @param params
* @return
*/
public Integer updateBookedInfo(Map<String,Object> params);
public void createTbIfNotExists(String tbName);
public List<VehicleBookInfo> getByPage4YearMonth(Map<String,Object> params);
public Integer insertHis(Map<String,Object> params);
public Integer del4YearMoth(Map<String,Object> params);
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.VehicleBookRecord;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;
public interface VehicleBookRecordMapper extends Mapper<VehicleBookRecord> {
Integer changeRecordStatus(Map<String,Object> params);
public List<VehicleBookRecord> getByPage4Month(Map<String,Object> params);
public Integer insertHis(Map<String,Object> params);
public Integer del4YearMoth(Map<String,Object> params);
public void createTbIfNotExists(String tbName);
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.mapper;
import com.xinxincaravan.caravan.vehicle.entity.Vehicle;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;
public interface VehicleMapper extends Mapper<Vehicle> {
public List<Vehicle> getByPage(Map<String,Object> params);
public int updateStatusById(Map<String,Object> params);
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.rest;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.xinxincaravan.caravan.vehicle.biz.BranchCompanyBiz;
import com.xinxincaravan.caravan.vehicle.common.BaseController;
import com.xinxincaravan.caravan.vehicle.common.RestResponse;
import com.xinxincaravan.caravan.vehicle.entity.BranchCompany;
import com.xinxincaravan.caravan.vehicle.vo.BranchCompanyVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/branchCompany")
@Slf4j
@IgnoreClientToken
public class BranchCompanyController extends BaseController<BranchCompanyBiz> {
@RequestMapping(value ="",method = RequestMethod.GET)
public RestResponse<List<BranchCompany>> getAll() {
return RestResponse.data(baseBiz.getAll());
}
@RequestMapping(value ="/{id}",method = RequestMethod.GET)
public RestResponse<BranchCompany> get(@PathVariable Integer id) {
return RestResponse.data(baseBiz.getById(id));
}
@RequestMapping(value ="",method = RequestMethod.POST)
public RestResponse<Integer> add(@RequestBody BranchCompanyVo branchCompanyVo) {
return RestResponse.data(baseBiz.add(branchCompanyVo));
}
@RequestMapping(value ="",method = RequestMethod.PUT)
public RestResponse update(@RequestBody BranchCompany branchCompany) {
baseBiz.update(branchCompany);
return RestResponse.sucResponse();
}
@RequestMapping(value ="/{id}",method = RequestMethod.DELETE)
public RestResponse del(@PathVariable Integer id) {
baseBiz.del(id);
return RestResponse.sucResponse();
}
}
package com.xinxincaravan.caravan.vehicle.rest;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.xinxincaravan.caravan.vehicle.biz.ConstantBiz;
import com.xinxincaravan.caravan.vehicle.common.BaseController;
import com.xinxincaravan.caravan.vehicle.common.RestResponse;
import com.xinxincaravan.caravan.vehicle.constant.ConstantType;
import com.xinxincaravan.caravan.vehicle.constant.ResCode.ResCode;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import com.xinxincaravan.caravan.vehicle.vo.ConstantVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/constant")
@Slf4j
@IgnoreClientToken
public class ConstantController extends BaseController<ConstantBiz> {
@RequestMapping(value ="/type/{type}",method = RequestMethod.GET)
public RestResponse<List<ConstantVo>> getAllConstantByType(@PathVariable Integer type){
if(!checkIfTypeValid(type)){
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
return RestResponse.data(baseBiz.getAllConstantByType(type));
}
/**
* 检查类型是否合法
* @param type
* @return
*/
private Boolean checkIfTypeValid(Integer type){
Boolean exists = Boolean.FALSE;
for(ConstantType constantType: ConstantType.values()){
if(constantType.getCode().equals(type)){
exists = Boolean.TRUE;
}
}
return exists;
}
@RequestMapping(value ="/type/{type}",method = RequestMethod.POST)
public RestResponse<Integer> add(@PathVariable Integer type,@RequestBody List<Constant> constants){
if(!checkIfTypeValid(type)){
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
if(CollectionUtils.isEmpty(constants)){
return RestResponse.sucResponse();
}
for(Constant constant:constants){
//编码和值不能为空
if(constant.getCode()==null|| StringUtils.isBlank(constant.getVal())) {
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
}
return RestResponse.data(baseBiz.addConstants(type,constants));
}
@RequestMapping(value ="/type/{type}",method = RequestMethod.PUT)
public RestResponse<Integer> update(@PathVariable Integer type,@RequestBody List<Constant> constants){
if(!checkIfTypeValid(type)){
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
if(CollectionUtils.isEmpty(constants)){
return RestResponse.sucResponse();
}
for(Constant constant:constants){
//编码和值不能为空
if(constant.getCode()==null|| StringUtils.isBlank(constant.getVal())) {
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
}
return RestResponse.data(baseBiz.updateConstants(type,constants));
}
@RequestMapping(value ="/type/{type}",method = RequestMethod.DELETE)
public RestResponse<Integer> del(@PathVariable Integer type,@RequestBody List<Integer> codes){
if(!checkIfTypeValid(type)){
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
if(CollectionUtils.isEmpty(codes)){
return RestResponse.sucResponse();
}
for(Integer code:codes){
//编码和值不能为空
if(code==null) {
return RestResponse.codeAndMessage(ResCode.INVALID_REST_REQ_PARAM.getCode(),
ResCode.INVALID_REST_REQ_PARAM.getDesc());
}
}
return RestResponse.data(baseBiz.delConstant(type,codes));
}
}
package com.xinxincaravan.caravan.vehicle.rest;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.xinxincaravan.caravan.vehicle.biz.SysRegionBiz;
import com.xinxincaravan.caravan.vehicle.common.BaseController;
import com.xinxincaravan.caravan.vehicle.common.RestResponse;
import com.xinxincaravan.caravan.vehicle.constant.ConstantType;
import com.xinxincaravan.caravan.vehicle.constant.ResCode.ResCode;
import com.xinxincaravan.caravan.vehicle.entity.Constant;
import com.xinxincaravan.caravan.vehicle.entity.SysRegion;
import com.xinxincaravan.caravan.vehicle.vo.ConstantVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/sysRegion")
@IgnoreClientToken
@Slf4j
public class SysRegionController extends BaseController<SysRegionBiz> {
@RequestMapping(value ="/sons/{id}",method = RequestMethod.GET)
public RestResponse<List<SysRegion>> getSonRegion(@PathVariable Long id){
return RestResponse.data(baseBiz.getSonRegion(id));
}
}
package com.xinxincaravan.caravan.vehicle.rest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.github.wxiaoqi.security.auth.client.annotation.IgnoreClientToken;
import com.github.wxiaoqi.security.auth.client.config.UserAuthConfig;
import com.github.wxiaoqi.security.auth.common.util.jwt.IJWTInfo;
import com.github.wxiaoqi.security.auth.common.util.jwt.JWTHelper;
import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.msg.auth.TokenForbiddenResponse;
import com.xinxincaravan.caravan.vehicle.biz.VehicleBiz;
import com.xinxincaravan.caravan.vehicle.common.BaseController;
import com.xinxincaravan.caravan.vehicle.common.CustomIllegalParamException;
import com.xinxincaravan.caravan.vehicle.common.RestResponse;
import com.xinxincaravan.caravan.vehicle.constant.ResCode.ResCode;
import com.xinxincaravan.caravan.vehicle.constant.VehicleBookRecordStatus;
import com.xinxincaravan.caravan.vehicle.entity.Vehicle;
import com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo;
import com.xinxincaravan.caravan.vehicle.vo.AddOrUpdateVehicleVo;
import com.xinxincaravan.caravan.vehicle.vo.PageDataVo;
import com.xinxincaravan.caravan.vehicle.vo.BookVehicleVo;
import com.xinxincaravan.caravan.vehicle.vo.VehiclePageQueryVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/vehicleInfo")
@Slf4j
@IgnoreClientToken
public class VehicleController extends BaseController<VehicleBiz> {
@RequestMapping(value ="/{id}",method = RequestMethod.GET)
public RestResponse<Vehicle> get(@PathVariable String id) {
return RestResponse.data(baseBiz.get(id));
}
@RequestMapping(value ="",method = RequestMethod.POST)
public RestResponse add(@RequestBody List<AddOrUpdateVehicleVo> addOrUpdateVehicleVoList) throws Exception{
return baseBiz.add(addOrUpdateVehicleVoList);
}
@RequestMapping(value ="",method = RequestMethod.PUT)
public RestResponse update(@RequestBody List<AddOrUpdateVehicleVo> addOrUpdateVehicleVoList) throws Exception{
return baseBiz.update(addOrUpdateVehicleVoList);
}
@RequestMapping(value ="",method = RequestMethod.DELETE)
public RestResponse discard(@RequestBody List<String> idList) throws Exception{
return baseBiz.discard(idList);
}
@RequestMapping(value ="/page",method = RequestMethod.GET)
public RestResponse<PageDataVo<Vehicle>> getByPage(@RequestParam String vehiclePageQueryVoJson) throws Exception{
VehiclePageQueryVo vehiclePageQueryVo = null;
try {
vehiclePageQueryVo = JSON.parseObject(vehiclePageQueryVoJson,VehiclePageQueryVo.class);
return RestResponse.data(baseBiz.getByPage(vehiclePageQueryVo));
} catch (JSONException ex) {
return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
} catch (CustomIllegalParamException ex){
return RestResponse.code(ResCode.INVALID_REST_REQ_PARAM.getCode());
}
}
@RequestMapping(value ="/bookedInfo/{vehicleId}/{yearMonth}",method = RequestMethod.GET)
public RestResponse<VehicleBookInfo> getBookedInfo(@PathVariable String vehicleId, @PathVariable String yearMonth) {
return RestResponse.data(baseBiz.getByVehicleIdAndYearMonth(vehicleId,yearMonth));
}
/**
* 申请预定车辆
* @param bookVehicleVo
* @return
*/
@RequestMapping(value ="/book/4employee",method = RequestMethod.POST)
public RestResponse<Integer> applyVehicle(@RequestBody BookVehicleVo bookVehicleVo){
Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
return baseBiz.applyVehicle4Employee(operatorId,bookVehicleVo);
}
/**
* 批准预定车辆预定
* @param bookRecordId
* @return
*/
@RequestMapping(value ="/book/4employee/prove/{bookRecordId}",method = RequestMethod.PUT)
public RestResponse<Integer> proveVehicleBooking(@PathVariable Long bookRecordId) throws Exception{
Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
return baseBiz.reviewVehicleBooking(operatorId, bookRecordId, VehicleBookRecordStatus.APPROVE.getCode());
}
/**
* 拒绝预定车辆申请
* @param bookRecordId
* @return
*/
@RequestMapping(value ="/book/4employee/reject/{bookRecordId}",method = RequestMethod.PUT)
public RestResponse<Integer> rejectVehicleBooking(@PathVariable Long bookRecordId) throws Exception{
Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
return baseBiz.reviewVehicleBooking(operatorId, bookRecordId, VehicleBookRecordStatus.REJECTED.getCode());
}
// /**
// * 车辆归还
// * @param bookRecordId
// * @return
// */
// @RequestMapping(value ="/book/4employee/return/{bookRecordId}",method = RequestMethod.PUT)
// public RestResponse<Integer> returnVehicle(@PathVariable String bookRecordId){
// //此处待加入获取当前操作用户id信息以及相关权限验证
// Integer operator = -1;//测试用
// return baseBiz.returnVehicle(operator, bookRecordId);
//
// }
/**
* 取消车辆预订
* @param bookRecordId
* @return
*/
@RequestMapping(value ="/unbook/4employee/{bookRecordId}",method = RequestMethod.DELETE)
public RestResponse<Integer> unbookVehicle(@PathVariable Long bookRecordId) throws Exception{
//此处待加入获取当前操作用户id信息以及相关权限验证
Integer operatorId = Integer.parseInt(BaseContextHandler.getUserID());
return baseBiz.unbookVehicle4Employee(operatorId,bookRecordId);
}
}
package com.xinxincaravan.caravan.vehicle.vo;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
@Data
public class AddOrUpdateVehicleVo {
/**
* 主键(uuid)
*/
private String id;
/**
* 车辆状态: 1-正常运行 2-维修 3-报废
*/
private Integer status;
/**
* 车牌号,空字符串-没有
*/
@Column(name = "number_plate")
private String numberPlate;
/**
* 品牌(编码,对应关系见相关常量),0-未填写
*/
private Integer brand;
/**
* 所属分支机构(id)
*/
@Column(name = "subordinate_branch")
private Integer subordinateBranch;
/**
* 用途类型:租赁房车(1)、展车等,对应关系见车辆常量表
*/
@Column(name = "use_type")
private Integer useType;
/**
* 备注信息
*/
private String remark;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.vo;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
import java.util.List;
@Data
public class BookVehicleVo {
/**
* 车辆id
*/
private String vehicle;
/**
* 预定目标日期(开始)
*/
private String bookStartDate;
/**
* 预定目标日期(结束)
*/
private String bookEndDate;
/**
* 取消预定目标日期(开始)
*/
private String unbookStartDate;
/**
* 取消预定目标日期(结束)
*/
private String unbookEndDate;
/**
* 提车地点
*/
private String liftAddr;
/**
* 目的地
*/
private String destination;
/**
* 备注
*/
private String remark;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.vo;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Data
public class BranchCompanyVo {
/**
* 分公司名称
*/
private String name;
/**
* 分支机构类型
*/
private Integer branchType;
/**
* 分支机构所属机构
*/
private Integer subordinateBranch;
/**
* 分支机构地址:经纬度
*/
private String location;
/**
* 地址-省/直辖市(编码)
*/
private Integer addrProvince;
/**
* 地址-市(编码)
*/
private Integer addrCity;
/**
* 地址-镇/县(编码)
*/
private Integer addrTown;
/**
* 详细地址
*/
private String addrDetail;
}
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle.vo;
import lombok.Data;
@Data
public class ConstantVo {
/**
* 常量类型
*/
private Integer type;
/**
* 常量编码
*/
private Integer code;
/**
* 值
*/
private String val;
}
package com.xinxincaravan.caravan.vehicle.vo;
import com.github.pagehelper.PageInfo;
import lombok.Data;
import java.util.List;
@Data
public class PageDataVo<T> {
/**
* 符合条件记录总数
*/
private Long totalCount;
/**
* 实际数据
*/
private List<T> data;
public static <M> PageDataVo<M> pageInfo(PageInfo<M> pageInfo){
PageDataVo<M> pageDataVo = new PageDataVo<>();
pageDataVo.setTotalCount(pageInfo.getTotal());
pageDataVo.setData(pageInfo.getList());
return pageDataVo;
}
}
package com.xinxincaravan.caravan.vehicle.vo;
import lombok.Data;
@Data
public class VehiclePageQueryVo {
/**
* 车辆编号,0-没有
*/
private Integer code;
/**
* 车辆状态: 1-正常运行 2-维修 3-报废
*/
private Integer status;
/**
* 车牌号,空字符串-没有
*/
private String numberPlate;
/**
* 品牌(编码,对应关系见相关常量),0-未填写
*/
private Integer brand;
/**
* 所属分支机构(id)
*/
private Integer subordinateBranch;
/**
* 用途类型:租赁房车(1)、展车等,对应关系见车辆常量表
*/
private Integer useType;
/**
* 预定目标日期(开始)
*/
private String bookedStartDate;
/**
* 预定目标日期(结束)
*/
private String bookedEndDate;
/**
* 未预定目标日期(开始)
*/
private String notBookedStartDate;
/**
* 未预定目标日期(结束)
*/
private String notBookedEndDate;
private Integer pageNo;
private Integer pageSize;
}
server:
port: 8091
servlet:
context-path: /vehicle
tomcat:
uri-encoding: UTF-8
logging:
level:
com.xinxincaravan.caravan.vehicle.mapper: debug
spring:
application:
name: vehicle
datasource:
name: test
url: jdbc:mysql://${MYSQL_HOST:10.5.52.2}:${MYSQL_PORT:3306}/vehicle?useUnicode=true&characterEncoding=UTF8
username: root
password: xx2019fc
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
cloud:
nacos:
discovery:
server-addr: 10.5.52.2:8848
sentinel:
transport:
dashboard: 10.5.52.2:8080
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
#--------------------以下为redis相关配置----------------------
redis:
database: 2
host: ${REDIS_HOST:10.5.52.2}
port: ${REDIS_PORT:6379}
password: xx2019fc
jedis:
pool:
max-active: 20
#--------------------以下为mybatis相关配置----------------------
mybatis:
type-aliases-package: com.xinxincaravan.caravan.vehicle.entity
mapper-locations: classpath*:mapper/*.xml
basepackage: com.xinxincaravan.caravan.vehicle.mapper
xmlLocation: classpath*:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
spring:
application:
name: vehicle
cloud:
nacos:
config:
server-addr: 10.5.52.2:8848
file-extension: yaml
profiles:
active: dev
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--<properties resource="dev.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="mergeable" value="false"></property>
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
</plugin>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://10.5.52.2:3306/vehicle?useUnicode=true&amp;characterEncoding=UTF8"
userId="root"
password="xx2019fc">
</jdbcConnection>
<javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/>
<sqlMapGenerator targetPackage="${targetXMLPackage}" targetProject="${targetResourcesProject}"/>
<javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}"
type="XMLMAPPER"/>
<table tableName="vehicle" domainObjectName="Vehicle">
</table>
<table tableName="vehicle_book_info" domainObjectName="VehicleBookInfo">
</table>
<table tableName="vehicle_book_record" domainObjectName="VehicleBookRecord">
</table>
<table tableName="branch_company" domainObjectName="BranchCompany">
</table>
</context>
</generatorConfiguration>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.BranchCompanyMapper" >
<resultMap id="BaseResultMap" type="com.xinxincaravan.caravan.vehicle.entity.BranchCompany" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="branch_type" property="branchType" jdbcType="INTEGER" />
<result column="subordinate_branch" property="subordinateBranch" jdbcType="INTEGER" />
<result column="location" property="location" jdbcType="VARCHAR" />
<result column="addr_province" property="addrProvince" jdbcType="INTEGER" />
<result column="addr_city" property="addrCity" jdbcType="INTEGER" />
<result column="addr_town" property="addrTown" jdbcType="INTEGER" />
<result column="addr_detail" property="addrDetail" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
</mapper>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.ConstantMapper">
<select id="getAllConstantTypes" resultType="java.lang.Integer">
select distinct `type` from constant
</select>
<update id="updateByTypeAndCode" parameterType="com.xinxincaravan.caravan.vehicle.entity.Constant" >
update constant set val = #{val} where type = #{type} and code = #{code}
</update>
<delete id="delByTypeAndCode" parameterType="com.xinxincaravan.caravan.vehicle.entity.Constant">
delete from constant where type = #{type} and code = #{code};
</delete>
<insert id="insertIgnoreOnDuplicate" parameterType="com.xinxincaravan.caravan.vehicle.entity.Constant">
insert ignore into constant(type,code,val) values (#{type},#{code},#{val})
</insert>
</mapper>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.SysRegionMapper">
<select id="getAllByPage" parameterType="java.util.Map" resultType="com.xinxincaravan.caravan.vehicle.entity.SysRegion">
select `id`, parent_id, `name`, `type`, agency_id from sys_region limit #{pageStart},${pageSize}
</select>
</mapper>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.VehicleBookInfoMapper" >
<resultMap id="BaseResultMap" type="com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="BIGINT" />
<result column="vehicle" property="vehicle" jdbcType="VARCHAR" />
<result column="year_month" property="yearMonth" jdbcType="VARCHAR" />
<result column="booked_date" property="bookedDate" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
<select id="getByVehicleIdAndYearMonth" resultType="com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo" parameterType="java.util.Map">
select id, vehicle, `year_month`, booked_date from vehicle_book_info where vehicle = #{vehicle} and `year_month`=#{yearMonth}
</select>
<insert id="insertIgnore" parameterType="com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo">
insert ignore into vehicle_book_info ( vehicle, `year_month`, booked_date)
values(#{vehicle},#{yearMonth},#{bookedDate})
</insert>
<update id="updateBookedInfo" parameterType="java.util.Map">
update vehicle_book_info set
<choose>
<when test="orRsOperationFactor!=null">
booked_date = booked_date | #{orRsOperationFactor}
</when>
<when test="andRsOperationFactor!=null">
booked_date = booked_date &amp; #{andRsOperationFactor}
</when>
</choose>
where
vehicle = #{vehicle} and `year_month`=#{yearMonth} and
booked_date &amp; #{andOperationFactor} = #{andOperationRs}
</update>
<select id="getByPage4YearMonth" parameterType="java.util.Map" resultType="com.xinxincaravan.caravan.vehicle.entity.VehicleBookInfo">
select id, vehicle, `year_month`, booked_date, create_time, update_time from vehicle_book_info where `year_month` = #{yearMonth} order by id limit #{pageStart},#{pageSize}
</select>
<delete id="del4YearMoth" parameterType="java.util.Map">
delete from vehicle_book_info where `year_month` = #{yearMonth} limit #{batchSize}
</delete>
<insert id="insertHis" parameterType="java.util.Map">
insert into
${tbName}(
`id`,
vehicle,
`year_month`,
booked_date
)
values(
#{id},
#{vehicle},
#{yearMonth},
#{bookedDate}
);
</insert>
<insert id="createTbIfNotExists" parameterType="java.lang.String">
CREATE TABLE IF NOT EXISTS ${_parameter} (
`id` bigint(10) NOT NULL,
`vehicle` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '车辆id',
`year_month` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '预定信息所属年月(格式yyyy-MM)',
`booked_date` int(10) NOT NULL COMMENT '预定信息,int格式保存,当作位图使用(从小到大每位代表每个月1-31号)',
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`update_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `i_vehicle_year_month`(`vehicle`, `year_month`) USING BTREE,
INDEX `i_year_month`(`year_month`) USING BTREE COMMENT '迁移历史表查询时使用'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '预定信息历史表,按年分表' ROW_FORMAT = Dynamic;
</insert>
</mapper>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.VehicleBookRecordMapper" >
<resultMap id="BaseResultMap" type="com.xinxincaravan.caravan.vehicle.entity.VehicleBookRecord" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="BIGINT" />
<result column="vehicle" property="vehicle" jdbcType="VARCHAR" />
<result column="statu" property="statu" jdbcType="INTEGER" />
<result column="book_type" property="bookType" jdbcType="INTEGER" />
<result column="book_user" property="bookUser" jdbcType="INTEGER" />
<result column="contact_info" property="contactInfo" jdbcType="VARCHAR" />
<result column="book_start_date" property="bookStartDate" jdbcType="TIMESTAMP" />
<result column="
lift_location" property="
liftLocation" jdbcType="VARCHAR" />
<result column="lift_addr" property="liftAddr" jdbcType="VARCHAR" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="destination" property="destination" jdbcType="VARCHAR" />
<result column="book_end_date" property="bookEndDate" jdbcType="TIMESTAMP" />
<result column="actal_start_date" property="actalStartDate" jdbcType="TIMESTAMP" />
<result column="actual_end_date" property="actualEndDate" jdbcType="TIMESTAMP" />
</resultMap>
<update id="changeRecordStatus" parameterType="java.util.Map">
update vehicle_book_record set
<if test="reviewerApply != null">
reviewer_apply =#{reviewerApply},
</if>
<if test="reviewerReturn != null">
reviewer_return =#{reviewerReturn},
</if>
<if test="reviewerCancel != null">
reviewer_cancel =#{reviewerCancel},
</if>
`status` = #{status}
where id = #{id} and `status` = #{statusCondition}
</update>
<delete id="del4YearMoth" parameterType="java.util.Map">
delete from vehicle_book_record where `book_end_date` between #{startDate} and #{endDate} limit #{batchSize}
</delete>
<insert id="insertHis" parameterType="java.util.Map">
insert into ${tbName} (
`id`,
`vehicle`,
`status`,
`book_type`,
`book_user`,
`contact_info`,
`book_start_date`,
`book_end_date`,
`lift_location`,
`lift_addr`,
`remark`,
`destination`,
`reviewer_apply`,
`reviewer_return`,
`reviewer_cancel`,
`actual_start_date`,
`actual_end_date`
)
values(
#{id},
#{vehicle},
#{status},
#{bookType},
#{bookUser},
#{contactInfo},
#{bookStartDate},
#{bookEndDate},
#{liftLocation},
#{liftAddr},
#{remark},
#{destination},
#{reviewerApply},
#{reviewerReturn},
#{reviewerCancel},
#{actualStartDate},
#{actualEndDate}
);
</insert>
<select id="getByPage4Month" parameterType="java.util.Map" resultType="com.xinxincaravan.caravan.vehicle.entity.VehicleBookRecord">
select
`id`,
`vehicle`,
`status`,
`book_type`,
`book_user`,
`contact_info`,
`book_start_date`,
`book_end_date`,
`lift_location`,
`lift_addr`,
`remark`,
`create_time`,
`update_time`,
`destination`,
`reviewer_apply`,
`reviewer_return`,
`reviewer_cancel`,
`actual_start_date`,
`actual_end_date`
from
vehicle_book_record
where
`book_end_date` between #{startDate} and #{endDate}
order by id
limit #{pageStart},#{pageSize}
</select>
<insert id="createTbIfNotExists" parameterType="java.lang.String">
CREATE TABLE IF NOT EXISTS ${_parameter} (
`id` bigint(20) NOT NULL COMMENT '主键',
`vehicle` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '车辆id',
`status` int(255) NULL DEFAULT NULL COMMENT '申请状态:1-申请中 2-已通过 3-已归还 4-拒绝 5-逾期归还 6-已取消',
`book_type` int(11) NOT NULL COMMENT '预定类型,1-用户租赁、2-内部员工申请 3-维修',
`book_user` int(11) NOT NULL COMMENT '预定用户id,对应menberinfo表中的id',
`contact_info` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '联系信息,比如电话、联系人姓名等(json)',
`book_start_date` datetime(0) NOT NULL COMMENT '申请开始日期',
`book_end_date` datetime(0) NOT NULL COMMENT '申请结束日期',
`lift_location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '提车地点(经纬度)',
`lift_addr` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '提车地址',
`remark` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`update_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
`destination` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '目的地',
`reviewer_apply` int(10) NULL DEFAULT NULL COMMENT '申请审核人,-1代表系统',
`reviewer_return` int(10) NULL DEFAULT NULL COMMENT '归还审核人,-1代表系统',
`reviewer_cancel` int(10) NULL DEFAULT NULL COMMENT '取消人,-1代表系统',
`actual_start_date` datetime(0) NULL DEFAULT NULL COMMENT '实际开始日期',
`actual_end_date` datetime(0) NULL DEFAULT NULL COMMENT '实际结束日期',
PRIMARY KEY (`id`) USING BTREE,
INDEX `i_vehicle`(`vehicle`) USING BTREE,
INDEX `i_book_user`(`book_user`) USING BTREE,
INDEX `i_book_end_date`(`book_end_date`) USING BTREE COMMENT '迁移至历史表时查询用到该索引(暂时)'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '汽车预定记录历史表,按年分表' ROW_FORMAT = Dynamic;
</insert>
</mapper>
\ No newline at end of file
<?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.xinxincaravan.caravan.vehicle.mapper.VehicleMapper" >
<resultMap id="BaseResultMap" type="com.xinxincaravan.caravan.vehicle.entity.Vehicle" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="code" property="code" jdbcType="INTEGER" />
<result column="status" property="status" jdbcType="INTEGER" />
<result column="number_plate" property="numberPlate" jdbcType="VARCHAR" />
<result column="brand" property="brand" jdbcType="INTEGER" />
<result column="subordinate_branch" property="subordinateBranch" jdbcType="INTEGER" />
<result column="use_type" property="useType" jdbcType="INTEGER" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
<update id="updateStatusById" parameterType="java.util.Map" >
update vehicle set status = #{status} where id in
<foreach collection="idList" index="i" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</update>
<select id="getByPage" parameterType="java.util.Map" resultType="com.xinxincaravan.caravan.vehicle.entity.Vehicle">
select v.`id`,
v.`code`,
v.`status`,
v.number_plate,
v.brand,
v.subordinate_branch,
v.use_type,
v.remark
<if test=" yearMonthAndParam !=null ">
,vbi.booked_date
</if>
from vehicle v
<if test=" yearMonthAndParam !=null ">
left join
vehicle_book_info vbi on v.`id` = vbi.vehicle
</if>
where
1=1
<if test="subordinateBranch !=null">
and v.subordinate_branch = #{subordinateBranch}
</if>
<if test="code !=null">
and v.code = #{code}
</if>
<if test="status !=null">
and v.status = #{status}
</if>
<if test="numberPlate !=null and numberPlate != ''">
and v.number_plate = #{numberPlate}
</if>
<if test="brand !=null">
and v.brand = #{brand}
</if>
<if test="useType !=null">
and v.use_type = #{useType}
</if>
<!-- 若需根据预定日期条件查询,针对换为位操作 -->
<if test=" yearMonthAndParam !=null ">
<foreach collection="yearMonthAndParam" index="yearMonth" item="andOperation" >
and
( (vbi.`year_month` = #{yearMonth} or vbi.`year_month` is null) and
ifnull(vbi.`booked_date`,0) &amp; #{andOperation.andOperationFactor} = #{andOperation.andOperationRs}
)
</foreach>
</if>
order by v.id
</select>
</mapper>
\ No newline at end of file
package com.xinxincaravan.caravan.vehicle;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class VehicleApplicationTests {
@Test
public void contextLoads() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment