This commit is contained in:
2026-01-05 20:14:33 +08:00
commit 1be18e2ff5
3117 changed files with 255370 additions and 0 deletions

BIN
yudao-module-car/.DS_Store vendored Normal file

Binary file not shown.

25
yudao-module-car/pom.xml Normal file
View File

@@ -0,0 +1,25 @@
<?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>cn.iocoder.boot</groupId>
<artifactId>yudao</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-car</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description> <!-- 4. 新增 description 为该模块的描述 -->
寄存轮胎模块,主要实现 轮胎寄存预约、轮胎取胎、轮胎暂存 等功能。
</description>
<modules>
<module>yudao-module-car-api</module>
<module>yudao-module-car-biz</module>
</modules>
</project>

View File

View File

View File

View File

View File

@@ -0,0 +1,25 @@
<?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>cn.iocoder.boot</groupId>
<artifactId>yudao-module-car</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-car-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description> <!-- 4. 新增 description 为该模块的描述 -->
寄存轮胎模块,主要实现 轮胎寄存预约、轮胎取胎、轮胎暂存 等功能。
</description>
<dependencies> <!-- 5. 新增 yudao-common 依赖 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.car.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* Infra 错误码枚举类
*
* infra 系统,使用 1_001_001_000 段
*/
public interface ErrorCodeConstants {
ErrorCode STORE_NOT_EXISTS = new ErrorCode(1_001_001_001, "门店管理不存在");
ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_001_001_002, "仓库管理不存在");
ErrorCode DEPOSIT_RECORDS_NOT_EXISTS = new ErrorCode(1_001_001_003, "轮胎存单不存在");
ErrorCode DEPOSIT_RECORDS_DETAIL_NOT_EXISTS = new ErrorCode(1_001_001_004, "轮胎存单明细不存在");
ErrorCode RELEASE_RECORDS_NOT_EXISTS = new ErrorCode(1_001_001_005, "轮胎取单不存在");
ErrorCode RELEASE_RECORDS_DETAIL_NOT_EXISTS = new ErrorCode(1_001_001_006, "轮胎取单明细不存在");
ErrorCode RELEASE_RECORDS_NOT_STORAGE_STATUS = new ErrorCode(1_001_001_007, "所选的存单需要为入库状态");
ErrorCode RELEASE_RECORDS_STORAGE_QUANTITY = new ErrorCode(1_001_001_008, "所选的存单中的所有轮胎均已预约取出");
ErrorCode DEPOSIT_RECORDS_NO_TYPE = new ErrorCode(1_001_001_009, "【{}】未存储相关类型数据");
ErrorCode DEPOSIT_RECORDS_QUANTITY_EXCEEDS_AVAILABLE = new ErrorCode(1_001_001_010, "【{}】取出数量大于剩余数量");
ErrorCode TIRE_NOT_STORE_USER = new ErrorCode(1_001_002_001, "轮胎系统不存在当前门店用户");
ErrorCode TIRE_NOT_WAREHOUSE_USER = new ErrorCode(1_001_002_002, "轮胎系统不存在当前仓库用户");
ErrorCode TIRE_NOT_USER = new ErrorCode(1_001_002_003, "轮胎系统不存在当前用户");
ErrorCode RENEWAL_PRODUCT_NOT_EXISTS = new ErrorCode(1_001_002_004, "车辆续保产品信息不存在");
ErrorCode RENEWAL_ORDER_NOT_EXISTS = new ErrorCode(1_001_002_005, "车辆续保订单信息不存在");
}

View File

@@ -0,0 +1,72 @@
<?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>cn.iocoder.boot</groupId>
<artifactId>yudao-module-car</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-car-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name> <!-- 3. 新增 name 为 ${project.artifactId} -->
<description> <!-- 4. 新增 description 为该模块的描述 -->
demo 模块,主要实现 食堂线上支付 等功能。
</description>
<dependencies> <!-- 5. 新增依赖,这里引入的都是比较常用的业务组件、技术组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-car-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-product-biz</artifactId>
<version>${revision}</version>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel-core</artifactId>
<version>3.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!--操作日志-->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-biz</artifactId>
<version>2.2.0-jdk8-snapshot</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

Binary file not shown.

View File

@@ -0,0 +1,155 @@
package cn.iocoder.yudao.module.car.controller.admin.login;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.controller.admin.login.vo.TireLoginRespVO;
import cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO;
import cn.iocoder.yudao.module.car.service.tireuser.TireUserService;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.TIRE_NOT_STORE_USER;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.TIRE_NOT_WAREHOUSE_USER;
@Tag(name = "轮胎寄存小程序 - 登录")
@RestController
@RequestMapping("/tire/auth")
@Validated
@Slf4j
public class TireLogin {
@Resource
private AdminAuthService authService;
@Resource
private TireUserService tireUserService;
/**
* 轮胎商店用户登录接口,通过账号和密码进行登录。
*
* @param reqVO 登录请求参数
* @return 登录成功后的响应对象
*/
@PostMapping("/store-login")
@PermitAll
@Operation(summary = "轮胎商店用户-使用账号密码登录")
public CommonResult<TireLoginRespVO> storeLogin(@RequestBody @Valid AuthLoginReqVO reqVO) {
return login(reqVO, true);
}
/**
* 轮胎仓库用户登录接口,通过账号和密码进行登录。
*
* @param reqVO 登录请求参数
* @return 登录成功后的响应对象
*/
@PostMapping("/warehouse-login")
@PermitAll
@Operation(summary = "轮胎仓库用户-使用账号密码登录")
public CommonResult<TireLoginRespVO> warehouseLogin(@RequestBody @Valid AuthLoginReqVO reqVO) {
return login(reqVO, false);
}
/**
* 处理轮胎用户登录的业务逻辑,区分商店用户和仓库用户。
*
* @param reqVO 登录请求参数
* @param isStoreUser 是否为商店用户
* @return 登录成功后的响应对象
*/
private CommonResult<TireLoginRespVO> login(AuthLoginReqVO reqVO, boolean isStoreUser) {
// 调用认证服务登录
AuthLoginRespVO loginResp = authService.login(reqVO);
// 查询并校验用户信息
TireUserDO tireUser = tireUserService.findByUserId(loginResp.getUserId());
validateTireUser(tireUser, isStoreUser);
// 构建响应对象
TireLoginRespVO response = BeanUtils.toBean(loginResp, TireLoginRespVO.class);
response.setStoreId(tireUser.getStoreId());
response.setWarehouseId(tireUser.getWarehouseId());
return success(response);
}
/**
* 门店端刷新令牌接口,使用旧的刷新令牌获取新的令牌。
*
* @param refreshToken 刷新令牌
* @return 刷新后的登录响应对象
*/
@PostMapping("/store-refresh-token")
@PermitAll
@Operation(summary = "门店端刷新令牌")
@Parameter(name = "refreshToken", description = "刷新令牌", required = true)
public CommonResult<TireLoginRespVO> storeRefreshToken(@RequestParam("refreshToken") String refreshToken) {
return refreshToken(refreshToken, true);
}
/**
* 仓库端刷新令牌接口,使用旧的刷新令牌获取新的令牌。
*
* @param refreshToken 刷新令牌
* @return 刷新后的登录响应对象
*/
@PostMapping("/warehouse-refresh-token")
@PermitAll
@Operation(summary = "仓库端刷新令牌")
@Parameter(name = "refreshToken", description = "刷新令牌", required = true)
public CommonResult<TireLoginRespVO> warehouseRefreshToken(@RequestParam("refreshToken") String refreshToken) {
return refreshToken(refreshToken, false);
}
/**
* 刷新令牌的通用逻辑,区分商店用户和仓库用户。
*
* @param refreshToken 刷新令牌
* @param isStoreUser 是否为商店用户
* @return 刷新后的登录响应对象
*/
private CommonResult<TireLoginRespVO> refreshToken(String refreshToken, boolean isStoreUser) {
// 调用认证服务刷新令牌
AuthLoginRespVO loginResp = authService.refreshToken(refreshToken);
// 查询并校验用户信息
TireUserDO tireUser = tireUserService.findByUserId(loginResp.getUserId());
validateTireUser(tireUser, isStoreUser);
// 构建响应对象
TireLoginRespVO response = BeanUtils.toBean(loginResp, TireLoginRespVO.class);
response.setStoreId(tireUser.getStoreId());
response.setWarehouseId(tireUser.getWarehouseId());
return success(response);
}
/**
* 校验轮胎用户是否为有效的商店或仓库用户。
*
* @param tireUser 轮胎用户信息
* @param isStoreUser 是否为商店用户
* @throws ServiceException 如果用户无效,抛出相应异常
*/
private void validateTireUser(TireUserDO tireUser, boolean isStoreUser) {
if (Objects.isNull(tireUser) ||
(isStoreUser && Objects.isNull(tireUser.getStoreId())) ||
(!isStoreUser && Objects.isNull(tireUser.getWarehouseId()))) {
throw exception(isStoreUser ? TIRE_NOT_STORE_USER : TIRE_NOT_WAREHOUSE_USER);
}
}
}

View File

@@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.car.controller.admin.login.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Schema(description = "轮胎管理后台 - 登录 Response VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TireLoginRespVO{
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
@Schema(description = "访问令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "happy")
private String accessToken;
@Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
private String refreshToken;
@Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime expiresTime;
@Schema(description = "门店ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
@ExcelProperty("门店ID")
private Long storeId;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11178")
@ExcelProperty("仓库编号")
private Long warehouseId;
}

View File

@@ -0,0 +1,95 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalorder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalorder.RenewalOrderDO;
import cn.iocoder.yudao.module.car.service.renewalorder.RenewalOrderService;
@Tag(name = "管理后台 - 车辆续保订单")
@RestController
@RequestMapping("/car/renewal-order")
@Validated
public class RenewalOrderController {
@Resource
private RenewalOrderService renewalOrderService;
@PostMapping("/create")
@Operation(summary = "创建车辆续保订单")
@PreAuthorize("@ss.hasPermission('car:renewal-order:create')")
public CommonResult<Long> createRenewalOrder(@Valid @RequestBody RenewalOrderSaveReqVO createReqVO) {
return success(renewalOrderService.createRenewalOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新车辆续保订单")
@PreAuthorize("@ss.hasPermission('car:renewal-order:update')")
public CommonResult<Boolean> updateRenewalOrder(@Valid @RequestBody RenewalOrderSaveReqVO updateReqVO) {
renewalOrderService.updateRenewalOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除车辆续保订单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('car:renewal-order:delete')")
public CommonResult<Boolean> deleteRenewalOrder(@RequestParam("id") Long id) {
renewalOrderService.deleteRenewalOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得车辆续保订单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('car:renewal-order:query')")
public CommonResult<RenewalOrderRespVO> getRenewalOrder(@RequestParam("id") Long id) {
RenewalOrderDO renewalOrder = renewalOrderService.getRenewalOrder(id);
return success(BeanUtils.toBean(renewalOrder, RenewalOrderRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得车辆续保订单分页")
@PreAuthorize("@ss.hasPermission('car:renewal-order:query')")
public CommonResult<PageResult<RenewalOrderRespVO>> getRenewalOrderPage(@Valid RenewalOrderPageReqVO pageReqVO) {
PageResult<RenewalOrderDO> pageResult = renewalOrderService.getRenewalOrderPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RenewalOrderRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出车辆续保订单 Excel")
@PreAuthorize("@ss.hasPermission('car:renewal-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportRenewalOrderExcel(@Valid RenewalOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RenewalOrderDO> list = renewalOrderService.getRenewalOrderPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "车辆续保订单.xls", "数据", RenewalOrderRespVO.class,
BeanUtils.toBean(list, RenewalOrderRespVO.class));
}
}

View File

@@ -0,0 +1,110 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo;
import lombok.*;
import java.time.LocalDate;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 车辆续保订单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RenewalOrderPageReqVO extends PageParam {
@Schema(description = "汽车品牌")
private String carBrand;
@Schema(description = "车型")
private String carModel;
@Schema(description = "车牌号")
private String licensePlate;
@Schema(description = "厂牌型号")
private String factoryModel;
@Schema(description = "发票金额")
private BigDecimal invoiceAmount;
@Schema(description = "购买时公里数")
private Integer purchaseMileage;
@Schema(description = "发动机号")
private String engineNo;
@Schema(description = "车架号")
private String vin;
@Schema(description = "发票日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private String invoiceDate;
@Schema(description = "服务购买方")
private String serviceBuyer;
@Schema(description = "车辆购买方")
private String carBuyer;
@Schema(description = "证件类型", example = "2")
private String certType;
@Schema(description = "联系电话")
private String mobile;
@Schema(description = "证件号码")
private String certNo;
@Schema(description = "联系地址")
private String contactAddress;
@Schema(description = "会员邮箱")
private String memberEmail;
@Schema(description = "续保产品ID关联 car_renewal_product.id", example = "2825")
private Long productId;
@Schema(description = "服务产品")
private String serviceProduct;
@Schema(description = "产品时效")
private String productValidity;
@Schema(description = "原厂质保时长")
private String originalWarrantyYears;
@Schema(description = "原厂质保里程")
private String originalWarrantyMileage;
@Schema(description = "产品费用")
private BigDecimal productFee;
@Schema(description = "结算方式")
private String settlementMethod;
@Schema(description = "备注", example = "你猜")
private String remark;
@Schema(description = "录单人")
private String inputUser;
@Schema(description = "合同备注", example = "你说的对")
private String contractRemark;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
private Long storeId;
private String storeName;
private String invoiceUrl;
}

View File

@@ -0,0 +1,136 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDate;
import java.util.*;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 车辆续保订单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RenewalOrderRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12326")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "汽车品牌")
@ExcelProperty("汽车品牌")
private String carBrand;
@Schema(description = "车型")
@ExcelProperty("车型")
private String carModel;
@Schema(description = "车牌号")
@ExcelProperty("车牌号")
private String licensePlate;
@Schema(description = "厂牌型号")
@ExcelProperty("厂牌型号")
private String factoryModel;
@Schema(description = "发票金额")
@ExcelProperty("发票金额")
private BigDecimal invoiceAmount;
@Schema(description = "购买时公里数")
@ExcelProperty("购买时公里数")
private Integer purchaseMileage;
@Schema(description = "发动机号")
@ExcelProperty("发动机号")
private String engineNo;
@Schema(description = "车架号")
@ExcelProperty("车架号")
private String vin;
@Schema(description = "发票日期")
@ExcelProperty("发票日期")
private String invoiceDate;
@Schema(description = "服务购买方")
@ExcelProperty("服务购买方")
private String serviceBuyer;
@Schema(description = "车辆购买方")
@ExcelProperty("车辆购买方")
private String carBuyer;
@Schema(description = "证件类型", example = "2")
@ExcelProperty("证件类型")
private String certType;
@Schema(description = "联系电话")
@ExcelProperty("联系电话")
private String mobile;
@Schema(description = "证件号码")
@ExcelProperty("证件号码")
private String certNo;
@Schema(description = "联系地址")
@ExcelProperty("联系地址")
private String contactAddress;
@Schema(description = "会员邮箱")
@ExcelProperty("会员邮箱")
private String memberEmail;
@Schema(description = "续保产品ID关联 car_renewal_product.id", requiredMode = Schema.RequiredMode.REQUIRED, example = "2825")
@ExcelProperty("续保产品ID关联 car_renewal_product.id")
private Long productId;
@Schema(description = "服务产品")
@ExcelProperty("服务产品")
private String serviceProduct;
@Schema(description = "产品时效")
@ExcelProperty("产品时效")
private String productValidity;
@Schema(description = "原厂质保时长")
@ExcelProperty("原厂质保时长")
private String originalWarrantyYears;
@Schema(description = "原厂质保里程")
@ExcelProperty("原厂质保里程")
private String originalWarrantyMileage;
@Schema(description = "产品费用")
@ExcelProperty("产品费用")
private BigDecimal productFee;
@Schema(description = "结算方式")
@ExcelProperty("结算方式")
private String settlementMethod;
@Schema(description = "备注", example = "你猜")
@ExcelProperty("备注")
private String remark;
@Schema(description = "录单人")
@ExcelProperty("录单人")
private String inputUser;
@Schema(description = "合同备注", example = "你说的对")
@ExcelProperty("合同备注")
private String contractRemark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
private Long storeId;
private String storeName;
private String invoiceUrl;
}

View File

@@ -0,0 +1,104 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDate;
import java.util.*;
import javax.validation.constraints.*;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 车辆续保订单新增/修改 Request VO")
@Data
public class RenewalOrderSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12326")
private Long id;
@Schema(description = "汽车品牌")
private String carBrand;
@Schema(description = "车型")
private String carModel;
@Schema(description = "车牌号")
private String licensePlate;
@Schema(description = "厂牌型号")
private String factoryModel;
@Schema(description = "发票金额")
private BigDecimal invoiceAmount;
@Schema(description = "购买时公里数")
private Integer purchaseMileage;
@Schema(description = "发动机号")
private String engineNo;
@Schema(description = "车架号")
private String vin;
@Schema(description = "发票日期")
private String invoiceDate;
@Schema(description = "服务购买方")
private String serviceBuyer;
@Schema(description = "车辆购买方")
private String carBuyer;
@Schema(description = "证件类型", example = "2")
private String certType;
@Schema(description = "联系电话")
private String mobile;
@Schema(description = "证件号码")
private String certNo;
@Schema(description = "联系地址")
private String contactAddress;
@Schema(description = "会员邮箱")
private String memberEmail;
@Schema(description = "续保产品ID关联 car_renewal_product.id", requiredMode = Schema.RequiredMode.REQUIRED, example = "2825")
@NotNull(message = "续保产品ID关联 car_renewal_product.id不能为空")
private Long productId;
@Schema(description = "服务产品")
private String serviceProduct;
@Schema(description = "产品时效")
private String productValidity;
@Schema(description = "原厂质保时长")
private String originalWarrantyYears;
@Schema(description = "原厂质保里程")
private String originalWarrantyMileage;
@Schema(description = "产品费用")
private BigDecimal productFee;
@Schema(description = "结算方式")
private String settlementMethod;
@Schema(description = "备注", example = "你猜")
private String remark;
@Schema(description = "录单人")
private String inputUser;
@Schema(description = "合同备注", example = "你说的对")
private String contractRemark;
private Long storeId;
private String storeName;
private String invoiceUrl;
}

View File

@@ -0,0 +1,95 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalproduct;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct.RenewalProductDO;
import cn.iocoder.yudao.module.car.service.renewalproduct.RenewalProductService;
@Tag(name = "管理后台 - 车辆续保产品信息")
@RestController
@RequestMapping("/car/renewal-product")
@Validated
public class RenewalProductController {
@Resource
private RenewalProductService renewalProductService;
@PostMapping("/create")
@Operation(summary = "创建车辆续保产品信息")
@PreAuthorize("@ss.hasPermission('car:renewal-product:create')")
public CommonResult<Long> createRenewalProduct(@Valid @RequestBody RenewalProductSaveReqVO createReqVO) {
return success(renewalProductService.createRenewalProduct(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新车辆续保产品信息")
@PreAuthorize("@ss.hasPermission('car:renewal-product:update')")
public CommonResult<Boolean> updateRenewalProduct(@Valid @RequestBody RenewalProductSaveReqVO updateReqVO) {
renewalProductService.updateRenewalProduct(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除车辆续保产品信息")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('car:renewal-product:delete')")
public CommonResult<Boolean> deleteRenewalProduct(@RequestParam("id") Long id) {
renewalProductService.deleteRenewalProduct(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得车辆续保产品信息")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('car:renewal-product:query')")
public CommonResult<RenewalProductRespVO> getRenewalProduct(@RequestParam("id") Long id) {
RenewalProductDO renewalProduct = renewalProductService.getRenewalProduct(id);
return success(BeanUtils.toBean(renewalProduct, RenewalProductRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得车辆续保产品信息分页")
@PreAuthorize("@ss.hasPermission('car:renewal-product:query')")
public CommonResult<PageResult<RenewalProductRespVO>> getRenewalProductPage(@Valid RenewalProductPageReqVO pageReqVO) {
PageResult<RenewalProductDO> pageResult = renewalProductService.getRenewalProductPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RenewalProductRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出车辆续保产品信息 Excel")
@PreAuthorize("@ss.hasPermission('car:renewal-product:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportRenewalProductExcel(@Valid RenewalProductPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<RenewalProductDO> list = renewalProductService.getRenewalProductPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "车辆续保产品信息.xls", "数据", RenewalProductRespVO.class,
BeanUtils.toBean(list, RenewalProductRespVO.class));
}
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 车辆续保产品信息分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RenewalProductPageReqVO extends PageParam {
@Schema(description = "服务产品名称", example = "李四")
private String productName;
@Schema(description = "产品内容")
private String productContent;
@Schema(description = "产品类别car_renewal_product_type00 无忧01 延保)", example = "2")
private String productType;
@Schema(description = "备注", example = "随便")
private String remark;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@Schema(description = "管理后台 - 车辆续保产品信息 Response VO")
@Data
@ExcelIgnoreUnannotated
public class RenewalProductRespVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19539")
@ExcelProperty("主键ID")
private Long id;
@Schema(description = "服务产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@ExcelProperty("服务产品名称")
private String productName;
@Schema(description = "产品内容")
@ExcelProperty("产品内容")
private String productContent;
@Schema(description = "产品类别car_renewal_product_type00 无忧01 延保)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@ExcelProperty(value = "产品类别car_renewal_product_type00 无忧01 延保)", converter = DictConvert.class)
@DictFormat("car_renewal_product_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
private String productType;
@Schema(description = "备注", example = "随便")
@ExcelProperty("备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
@Schema(description = "管理后台 - 车辆续保产品信息新增/修改 Request VO")
@Data
public class RenewalProductSaveReqVO {
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19539")
private Long id;
@Schema(description = "服务产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotEmpty(message = "服务产品名称不能为空")
private String productName;
@Schema(description = "产品内容")
private String productContent;
@Schema(description = "产品类别car_renewal_product_type00 无忧01 延保)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotEmpty(message = "产品类别car_renewal_product_type00 无忧01 延保)不能为空")
private String productType;
@Schema(description = "备注", example = "随便")
private String remark;
}

View File

@@ -0,0 +1,103 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.module.car.controller.admin.statistics.vo.*;
import cn.iocoder.yudao.module.car.service.statistics.StatisticsService;
@Tag(name = "管理后台 - 车辆续保统计")
@RestController
@RequestMapping("/car/statistics")
@Validated
public class StatisticsController {
@Resource
private StatisticsService statisticsService;
@GetMapping("/store-sales")
@Operation(summary = "获取门店销售统计")
public CommonResult<List<StoreSalesStatisticsRespVO>> getStoreSalesStatistics(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getStoreSalesStatistics(startTime, endTime, storeId));
}
@GetMapping("/salesperson-sales")
@Operation(summary = "获取业务员销售统计")
public CommonResult<List<SalespersonStatisticsRespVO>> getSalespersonStatistics(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getSalespersonStatistics(startTime, endTime, storeId));
}
@GetMapping("/salesperson-rank")
@Operation(summary = "获取业务员销售排行")
public CommonResult<List<SalespersonStatisticsRespVO>> getSalespersonRank(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getSalespersonRank(startTime, endTime, storeId));
}
@GetMapping("/store-sales-trend")
@Operation(summary = "获取门店销售趋势")
public CommonResult<List<StoreSalesTrendRespVO>> getStoreSalesTrend(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getStoreSalesTrend(startTime, endTime, storeId));
}
@GetMapping("/salesperson-sales-trend")
@Operation(summary = "获取业务员销售趋势")
public CommonResult<List<SalespersonSalesTrendRespVO>> getSalespersonSalesTrend(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getSalespersonSalesTrend(startTime, endTime, storeId));
}
@GetMapping("/salesperson-order-rate")
@Operation(summary = "获取业务员开单率分析")
public CommonResult<List<SalespersonStatisticsRespVO>> getSalespersonOrderRate(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getSalespersonOrderRate(startTime, endTime, storeId));
}
@GetMapping("/store-order-rate")
@Operation(summary = "获取门店开单率分析")
public CommonResult<List<StoreSalesStatisticsRespVO>> getStoreOrderRate(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getStoreOrderRate(startTime, endTime, storeId));
}
@GetMapping("/summary")
@Operation(summary = "获取汇总统计")
public CommonResult<SummaryStatisticsRespVO> getSummaryStatistics(
@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "storeId", required = false) Long storeId) {
return success(statisticsService.getSummaryStatistics(startTime, endTime, storeId));
}
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 业务员销售趋势 Response VO")
@Data
public class SalespersonSalesTrendRespVO {
@Schema(description = "日期", example = "2024-01-01")
private String date;
@Schema(description = "业务员名称", example = "张三")
private String salespersonName;
@Schema(description = "金额", example = "5000.00")
private BigDecimal amount;
}

View File

@@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 业务员销售统计 Response VO")
@Data
public class SalespersonStatisticsRespVO {
@Schema(description = "业务员ID用户名", example = "admin")
private String salespersonId;
@Schema(description = "业务员名称", example = "张三")
private String salespersonName;
@Schema(description = "所属门店ID", example = "1")
private Long storeId;
@Schema(description = "所属门店名称", example = "总店")
private String storeName;
@Schema(description = "销售订单总金额", example = "50000.00")
private BigDecimal totalAmount;
@Schema(description = "订单数量", example = "50")
private Integer orderCount;
@Schema(description = "平均订单金额", example = "1000.00")
private BigDecimal averageOrderAmount;
@Schema(description = "距离上一次开单天数", example = "5")
private Integer lastOrderDays;
@Schema(description = "最近30天开单率", example = "0.85")
private BigDecimal orderRate30Days;
@Schema(description = "平均开单天数(几天一单)", example = "3")
private Integer averageOrderDays;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 门店销售统计 Response VO")
@Data
public class StoreSalesStatisticsRespVO {
@Schema(description = "门店ID", example = "1")
private Long storeId;
@Schema(description = "门店名称", example = "总店")
private String storeName;
@Schema(description = "销售订单总金额", example = "100000.00")
private BigDecimal totalAmount;
@Schema(description = "订单数量", example = "100")
private Integer orderCount;
@Schema(description = "平均订单金额", example = "1000.00")
private BigDecimal averageOrderAmount;
@Schema(description = "距离上一次开单天数", example = "5")
private Integer lastOrderDays;
@Schema(description = "最近30天开单率", example = "0.85")
private BigDecimal orderRate30Days;
@Schema(description = "平均开单天数(几天一单)", example = "3")
private Integer averageOrderDays;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 门店销售趋势 Response VO")
@Data
public class StoreSalesTrendRespVO {
@Schema(description = "日期", example = "2024-01-01")
private String date;
@Schema(description = "门店名称", example = "总店")
private String storeName;
@Schema(description = "金额", example = "10000.00")
private BigDecimal amount;
}

View File

@@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.car.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 汇总统计 Response VO")
@Data
public class SummaryStatisticsRespVO {
@Schema(description = "总订单金额", example = "100000.00")
private BigDecimal totalAmount;
@Schema(description = "总订单数", example = "100")
private Integer totalOrderCount;
@Schema(description = "平均订单金额", example = "1000.00")
private BigDecimal averageOrderAmount;
@Schema(description = "活跃门店数", example = "10")
private Integer activeStoreCount;
}

View File

@@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.car.controller.admin.store;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StorePageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StoreRespVO;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StoreSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import cn.iocoder.yudao.module.car.service.store.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 门店管理")
@RestController
@RequestMapping("/tire/store")
@Validated
public class StoreController {
@Resource
private StoreService storeService;
@PostMapping("/create")
@Operation(summary = "创建门店管理")
public CommonResult<Integer> createStore(@Valid @RequestBody StoreSaveReqVO createReqVO) {
return success(storeService.createStore(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新门店管理")
public CommonResult<Boolean> updateStore(@Valid @RequestBody StoreSaveReqVO updateReqVO) {
storeService.updateStore(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除门店管理")
@Parameter(name = "id", description = "编号", required = true)
public CommonResult<Boolean> deleteStore(@RequestParam("id") Integer id) {
storeService.deleteStore(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得门店管理")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<StoreRespVO> getStore(@RequestParam("id") Integer id) {
StoreDO store = storeService.getStore(id);
return success(BeanUtils.toBean(store, StoreRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得门店管理分页")
public CommonResult<PageResult<StoreRespVO>> getStorePage(@Valid StorePageReqVO pageReqVO) {
PageResult<StoreDO> pageResult = storeService.getStorePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, StoreRespVO.class));
}
@GetMapping("/pageAll")
@Operation(summary = "获得门店管理分页-全部")
public CommonResult<PageResult<StoreRespVO>> getStorePageAll(@Valid StorePageReqVO pageReqVO) {
pageReqVO.setPageSize(-1);
return getStorePage(pageReqVO);
}
@GetMapping("/export-excel")
@Operation(summary = "导出门店管理 Excel")
@ApiAccessLog(operateType = EXPORT)
public void exportStoreExcel(@Valid StorePageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<StoreDO> list = storeService.getStorePage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "门店管理.xls", "数据", StoreRespVO.class,
BeanUtils.toBean(list, StoreRespVO.class));
}
}

View File

@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.car.controller.admin.store.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 门店管理分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StorePageReqVO extends PageParam {
@Schema(description = "门店名称", example = "赵六")
private String storeName;
@Schema(description = "位置ID关联位置表", example = "27998")
private Integer areaId;
@Schema(description = "详细位置")
private String detailedLocation;
@Schema(description = "纬度")
private BigDecimal latitude;
@Schema(description = "经度")
private BigDecimal longitude;
@Schema(description = "邮政编码")
private String postalCode;
@Schema(description = "联系电话")
private String phoneNumber;
@Schema(description = "电子邮件")
private String email;
@Schema(description = "店长姓名", example = "李四")
private String managerName;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "帐号状态0正常 1停用", example = "2")
private Integer status;
}

View File

@@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.car.controller.admin.store.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 门店管理 Response VO")
@Data
@ExcelIgnoreUnannotated
public class StoreRespVO {
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@ExcelProperty("门店名称")
private String storeName;
@Schema(description = "位置ID关联位置表", requiredMode = Schema.RequiredMode.REQUIRED, example = "27998")
@ExcelProperty("位置ID关联位置表")
private Integer areaId;
@Schema(description = "详细位置")
@ExcelProperty("详细位置")
private String detailedLocation;
@Schema(description = "纬度")
@ExcelProperty("纬度")
private BigDecimal latitude;
@Schema(description = "经度")
@ExcelProperty("经度")
private BigDecimal longitude;
@Schema(description = "邮政编码")
@ExcelProperty("邮政编码")
private String postalCode;
@Schema(description = "联系电话")
@ExcelProperty("联系电话")
private String phoneNumber;
@Schema(description = "电子邮件")
@ExcelProperty("电子邮件")
private String email;
@Schema(description = "店长姓名", example = "李四")
@ExcelProperty("店长姓名")
private String managerName;
@Schema(description = "门店ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
@ExcelProperty("门店ID")
private Integer id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "帐号状态0正常 1停用", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@ExcelProperty("帐号状态0正常 1停用")
private Integer status;
}

View File

@@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.car.controller.admin.store.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 门店管理新增/修改 Request VO")
@Data
public class StoreSaveReqVO {
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotEmpty(message = "门店名称不能为空")
private String storeName;
@Schema(description = "位置ID关联位置表", requiredMode = Schema.RequiredMode.REQUIRED, example = "27998")
@NotNull(message = "位置ID关联位置表不能为空")
private Integer areaId;
@Schema(description = "详细位置")
private String detailedLocation;
@Schema(description = "纬度")
private BigDecimal latitude;
@Schema(description = "经度")
private BigDecimal longitude;
@Schema(description = "邮政编码")
private String postalCode;
@Schema(description = "联系电话")
private String phoneNumber;
@Schema(description = "电子邮件")
private String email;
@Schema(description = "店长姓名", example = "李四")
private String managerName;
@Schema(description = "门店ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
private Integer id;
@Schema(description = "帐号状态0正常 1停用", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "帐号状态0正常 1停用不能为空")
private Integer status;
}

View File

@@ -0,0 +1,114 @@
package cn.iocoder.yudao.module.car.controller.admin.tireuser;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserPageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserRespVO;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO;
import cn.iocoder.yudao.module.car.service.tireuser.TireUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* 轮胎用户管理 Controller
*
* 提供创建、更新、删除、查询轮胎用户的接口
*/
@Tag(name = "后台 - 轮胎用户")
@RestController
@RequestMapping("/tire/tireuser")
@Validated
public class TireUserController {
@Resource
private TireUserService tireUserService;
/**
* 创建轮胎用户
*
* @param createReqVO 轮胎用户创建请求参数
* @return 返回创建的用户 ID
*/
@PostMapping("/create")
@Operation(summary = "创建轮胎用户")
public CommonResult<Integer> createTireUser(@Valid @RequestBody TireUserSaveReqVO createReqVO) {
return success(tireUserService.createTireUser(createReqVO));
}
/**
* 更新轮胎用户信息
*
* @param updateReqVO 轮胎用户更新请求参数
* @return 是否更新成功
*/
@PutMapping("/update")
@Operation(summary = "更新轮胎用户")
public CommonResult<Boolean> updateTireUser(@Valid @RequestBody TireUserSaveReqVO updateReqVO) {
tireUserService.updateTireUser(updateReqVO);
return success(true);
}
/**
* 删除轮胎用户
*
* @param id 轮胎用户 ID
* @return 是否删除成功
*/
@DeleteMapping("/delete")
@Operation(summary = "删除轮胎用户")
@Parameter(name = "id", description = "编号", required = true)
public CommonResult<Boolean> deleteTireUser(@RequestParam("id") Integer id) {
tireUserService.deleteTireUser(id);
return success(true);
}
/**
* 获取轮胎用户详细信息
*
* @param id 轮胎用户 ID
* @return 轮胎用户详情
*/
@GetMapping("/get")
@Operation(summary = "获得轮胎用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<TireUserRespVO> getTireUser(@RequestParam("id") Integer id) {
TireUserDO tireUser = tireUserService.getTireUser(id);
return success(BeanUtils.toBean(tireUser, TireUserRespVO.class));
}
/**
* 获取门店用户的分页数据
*
* @param pageReqVO 分页请求参数
* @return 门店用户的分页列表
*/
@GetMapping("/getTireStoreUserPage")
@Operation(summary = "获得门店用户分页")
public CommonResult<PageResult<TireUserRespVO>> getTireStoreUserPage(@Valid TireUserPageReqVO pageReqVO) {
PageResult<TireUserDO> pageResult = tireUserService.getTireStoreUserPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, TireUserRespVO.class));
}
/**
* 获取仓库用户的分页数据
*
* @param pageReqVO 分页请求参数
* @return 仓库用户的分页列表
*/
@GetMapping("/getTireWarehouseUserPage")
@Operation(summary = "获得仓库用户分页")
public CommonResult<PageResult<TireUserRespVO>> getTireWarehouseUserPage(@Valid TireUserPageReqVO pageReqVO) {
PageResult<TireUserDO> pageResult = tireUserService.getTireWarehouseUserPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, TireUserRespVO.class));
}
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.car.controller.admin.tireuser.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 门店管理分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TireUserPageReqVO extends PageParam {
@Schema(description = "查询类型()", example = "27998")
private String queryType;
@Schema(description = "门店ID关联门店表", example = "27998")
private Long storeId;
@Schema(description = "仓库ID关联仓库表", example = "27998")
private Long warehouseId;
@Schema(description = "用户ID关联用户表", example = "27998")
private Long userId;
@Schema(description = "用户表")
private UserPageReqVO user;
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.car.controller.admin.tireuser.vo;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 门店管理 Response VO")
@Data
@ExcelIgnoreUnannotated
public class TireUserRespVO {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
@ExcelProperty("ID")
private Integer id;
@Schema(description = "门店ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
@ExcelProperty("门店ID")
private Long storeId;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
@ExcelProperty("仓库编号")
private Long warehouseId;
@Schema(description = "用户ID关联用户表", requiredMode = Schema.RequiredMode.REQUIRED, example = "27998")
@ExcelProperty("用户关联用户表")
private Long userId;
@Schema(description = "用户表")
@ExcelProperty("用户关联用户表")
private UserRespVO user;
}

View File

@@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.car.controller.admin.tireuser.vo;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "轮胎系统 - 门店用户 - 用户创建/修改 Request VO")
@Data
public class TireUserSaveReqVO {
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11176")
private Integer id;
@Schema(description = "门店编号", example = "我是一个用户")
private Long storeId;
@Schema(description = "仓库编号", example = "我是一个用户")
private Long warehouseId;
@Schema(description = "用户编号", example = "我是一个用户")
private Long userId;
@Schema(description = "用户表")
private UserSaveReqVO user;
}

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.car.controller.app.store;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StorePageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StoreRespVO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import cn.iocoder.yudao.module.car.service.store.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "APP - 门店管理")
@RestController
@RequestMapping("/tire/store")
public class AppStoreControl {
@Resource
private StoreService storeService;
@GetMapping("/page")
@Operation(summary = "获得门店管理分页")
public CommonResult<PageResult<StoreRespVO>> getStorePage(@Valid StorePageReqVO pageReqVO) {
PageResult<StoreDO> pageResult = storeService.getStorePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, StoreRespVO.class));
}
}

View File

@@ -0,0 +1,147 @@
package cn.iocoder.yudao.module.car.dal.dataobject.renewalorder;
import lombok.*;
import java.time.LocalDate;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 车辆续保订单 DO
*
* @author 芋道源码
*/
@TableName("car_renewal_order")
@KeySequence("car_renewal_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RenewalOrderDO extends BaseDO {
/**
* 主键ID
*/
@TableId
private Long id;
/**
* 汽车品牌
*/
private String carBrand;
/**
* 车型
*/
private String carModel;
/**
* 车牌号
*/
private String licensePlate;
/**
* 厂牌型号
*/
private String factoryModel;
/**
* 发票金额
*/
private BigDecimal invoiceAmount;
/**
* 购买时公里数
*/
private Integer purchaseMileage;
/**
* 发动机号
*/
private String engineNo;
/**
* 车架号
*/
private String vin;
/**
* 发票日期
*/
private String invoiceDate;
/**
* 服务购买方
*/
private String serviceBuyer;
/**
* 车辆购买方
*/
private String carBuyer;
/**
* 证件类型
*/
private String certType;
/**
* 联系电话
*/
private String mobile;
/**
* 证件号码
*/
private String certNo;
/**
* 联系地址
*/
private String contactAddress;
/**
* 会员邮箱
*/
private String memberEmail;
/**
* 续保产品ID关联 car_renewal_product.id
*/
private Long productId;
/**
* 服务产品
*/
private String serviceProduct;
/**
* 产品时效
*/
private String productValidity;
/**
* 原厂质保时长
*/
private String originalWarrantyYears;
/**
* 原厂质保里程
*/
private String originalWarrantyMileage;
/**
* 产品费用
*/
private BigDecimal productFee;
/**
* 结算方式
*/
private String settlementMethod;
/**
* 备注
*/
private String remark;
/**
* 录单人
*/
private String inputUser;
/**
* 合同备注
*/
private String contractRemark;
private Long storeId;
@TableField(exist = false)
private String storeName;
private String invoiceUrl;
}

View File

@@ -0,0 +1,49 @@
package cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
/**
* 车辆续保产品信息 DO
*
* @author 芋道源码
*/
@TableName("car_renewal_product")
@KeySequence("car_renewal_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RenewalProductDO extends BaseDO {
/**
* 主键ID
*/
@TableId
private Long id;
/**
* 服务产品名称
*/
private String productName;
/**
* 产品内容
*/
private String productContent;
/**
* 产品类别car_renewal_product_type00 无忧01 延保)
*
* 枚举 {@link TODO car_renewal_product_type 对应的类}
*/
private String productType;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,72 @@
package cn.iocoder.yudao.module.car.dal.dataobject.store;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
/**
* 门店管理 DO
*
* @author 芋道源码
*/
@TableName("tire_store")
@KeySequence("tire_store_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StoreDO extends BaseDO {
/**
* 门店名称
*/
private String storeName;
/**
* 位置ID关联位置表
*/
private Integer areaId;
/**
* 详细位置
*/
private String detailedLocation;
/**
* 纬度
*/
private BigDecimal latitude;
/**
* 经度
*/
private BigDecimal longitude;
/**
* 邮政编码
*/
private String postalCode;
/**
* 联系电话
*/
private String phoneNumber;
/**
* 电子邮件
*/
private String email;
/**
* 店长姓名
*/
private String managerName;
/**
* 门店ID
*/
@TableId
private Integer id;
/**
* 帐号状态0正常 1停用
*/
private Integer status;
}

View File

@@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.car.dal.dataobject.tireuser;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 门店管理 DO
*
* @author 芋道源码
*/
@TableName("tire_user")
@KeySequence("tire_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TireUserDO extends BaseDO{
/**
* id
*/
@TableId
private Long id;
/**
* 门店ID
*/
private Long storeId;
/**
* 仓库ID
*/
private Long warehouseId;
/**
* 用户ID
*/
private Long userId;
/**
* 用户信息(非数据库字段)
*/
@TableField(exist = false)
private AdminUserDO user;
}

View File

@@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.car.dal.mysql.renewalorder;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo.RenewalOrderPageReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalorder.RenewalOrderDO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
/**
* 车辆续保订单 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface RenewalOrderMapper extends BaseMapperX<RenewalOrderDO> {
default PageResult<RenewalOrderDO> selectPage(RenewalOrderPageReqVO reqVO) {
// 1. 分页对象
Page<RenewalOrderDO> page = new Page<>(reqVO.getPageNo(), reqVO.getPageSize());
// 2. MPJ LambdaWrapperJOIN + 条件)
MPJLambdaWrapper<RenewalOrderDO> wrapper = new MPJLambdaWrapper<RenewalOrderDO>()
.selectAll(RenewalOrderDO.class)
.selectAs(StoreDO::getStoreName, RenewalOrderDO::getStoreName)
.leftJoin(StoreDO.class, StoreDO::getId, RenewalOrderDO::getStoreId)
// ===== 原 LambdaQueryWrapperX 条件全部搬过来 =====
.like(reqVO.getCarBrand() != null, RenewalOrderDO::getCarBrand, reqVO.getCarBrand())
.like(reqVO.getCarModel() != null, RenewalOrderDO::getCarModel, reqVO.getCarModel())
.like(reqVO.getLicensePlate() != null, RenewalOrderDO::getLicensePlate, reqVO.getLicensePlate())
.like(reqVO.getFactoryModel() != null, RenewalOrderDO::getFactoryModel, reqVO.getFactoryModel())
.eq(reqVO.getInvoiceAmount() != null, RenewalOrderDO::getInvoiceAmount, reqVO.getInvoiceAmount())
.eq(reqVO.getPurchaseMileage() != null, RenewalOrderDO::getPurchaseMileage, reqVO.getPurchaseMileage())
.like(reqVO.getEngineNo() != null, RenewalOrderDO::getEngineNo, reqVO.getEngineNo())
.like(reqVO.getVin() != null, RenewalOrderDO::getVin, reqVO.getVin())
.eq(reqVO.getServiceBuyer() != null, RenewalOrderDO::getServiceBuyer, reqVO.getServiceBuyer())
.eq(reqVO.getCarBuyer() != null, RenewalOrderDO::getCarBuyer, reqVO.getCarBuyer())
.eq(reqVO.getCertType() != null, RenewalOrderDO::getCertType, reqVO.getCertType())
.eq(reqVO.getMobile() != null, RenewalOrderDO::getMobile, reqVO.getMobile())
.eq(reqVO.getCertNo() != null, RenewalOrderDO::getCertNo, reqVO.getCertNo())
.eq(reqVO.getContactAddress() != null, RenewalOrderDO::getContactAddress, reqVO.getContactAddress())
.eq(reqVO.getMemberEmail() != null, RenewalOrderDO::getMemberEmail, reqVO.getMemberEmail())
.eq(reqVO.getProductId() != null, RenewalOrderDO::getProductId, reqVO.getProductId())
.eq(reqVO.getServiceProduct() != null, RenewalOrderDO::getServiceProduct, reqVO.getServiceProduct())
.eq(reqVO.getProductValidity() != null, RenewalOrderDO::getProductValidity, reqVO.getProductValidity())
.eq(reqVO.getOriginalWarrantyYears() != null, RenewalOrderDO::getOriginalWarrantyYears, reqVO.getOriginalWarrantyYears())
.eq(reqVO.getOriginalWarrantyMileage() != null, RenewalOrderDO::getOriginalWarrantyMileage, reqVO.getOriginalWarrantyMileage())
.eq(reqVO.getProductFee() != null, RenewalOrderDO::getProductFee, reqVO.getProductFee())
.eq(reqVO.getSettlementMethod() != null, RenewalOrderDO::getSettlementMethod, reqVO.getSettlementMethod())
.eq(reqVO.getRemark() != null, RenewalOrderDO::getRemark, reqVO.getRemark())
.eq(reqVO.getInputUser() != null, RenewalOrderDO::getInputUser, reqVO.getInputUser())
.eq(reqVO.getContractRemark() != null, RenewalOrderDO::getContractRemark, reqVO.getContractRemark())
.orderByDesc(RenewalOrderDO::getId);
// 3. createTime 范围处理
if (reqVO.getCreateTime() != null && reqVO.getCreateTime().length == 2) {
wrapper.between(RenewalOrderDO::getCreateTime, reqVO.getCreateTime()[0], reqVO.getCreateTime()[1]);
}
// 4. 执行分页查询
IPage<RenewalOrderDO> result = selectJoinPage(page, RenewalOrderDO.class, wrapper);
// 5. 返回 PageResult
return new PageResult<>(result.getRecords(), result.getTotal());
}
/**
* 详情查询(后台)
*/
@Override
default RenewalOrderDO selectById(Serializable id) {
MPJLambdaWrapper<RenewalOrderDO> wrapper = new MPJLambdaWrapper<RenewalOrderDO>()
.selectAll(RenewalOrderDO.class)
.selectAs(StoreDO::getStoreName, RenewalOrderDO::getStoreName)
.leftJoin(StoreDO.class, StoreDO::getId, RenewalOrderDO::getStoreId)
.eq(Objects.nonNull(id), RenewalOrderDO::getId, id);
List<RenewalOrderDO> list = selectJoinList(RenewalOrderDO.class, wrapper);
return list.isEmpty() ? null : list.get(0);
}
}

View File

@@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.car.dal.mysql.renewalproduct;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo.RenewalProductPageReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct.RenewalProductDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 车辆续保产品信息 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface RenewalProductMapper extends BaseMapperX<RenewalProductDO> {
default PageResult<RenewalProductDO> selectPage(RenewalProductPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<RenewalProductDO>()
.likeIfPresent(RenewalProductDO::getProductName, reqVO.getProductName())
.eqIfPresent(RenewalProductDO::getProductContent, reqVO.getProductContent())
.eqIfPresent(RenewalProductDO::getProductType, reqVO.getProductType())
.likeIfPresent(RenewalProductDO::getRemark, reqVO.getRemark())
.betweenIfPresent(RenewalProductDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(RenewalProductDO::getId));
}
}

View File

@@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.car.dal.mysql.statistics;
import cn.iocoder.yudao.module.car.controller.admin.statistics.vo.*;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Mapper
public interface StatisticsMapper{
List<StoreSalesStatisticsRespVO> selectStoreSalesStatistics(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
@Param("storeId") Long storeId);
List<SalespersonStatisticsRespVO> selectSalespersonStatistics(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
@Param("storeId") Long storeId);
List<StoreSalesTrendRespVO> selectStoreSalesTrend(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
@Param("storeId") Long storeId);
List<SalespersonSalesTrendRespVO> selectSalespersonSalesTrend(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
@Param("storeId") Long storeId);
Integer calculateAverageOrderDaysForStore(
@Param("storeId") Long storeId,
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end);
Integer calculateAverageOrderDaysForSalesperson(
@Param("salespersonId") String salespersonId,
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end);
BigDecimal calculateOrderRate30DaysForStore(@Param("storeId") Long storeId);
BigDecimal calculateOrderRate30DaysForSalesperson(@Param("salespersonId") String salespersonId);
Integer calculateLastOrderDaysForStore(@Param("storeId") Long storeId);
Integer calculateLastOrderDaysForSalesperson(@Param("salespersonId") String salespersonId);
SummaryStatisticsRespVO selectSummaryStatistics(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
@Param("storeId") Long storeId);
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.car.dal.mysql.store;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StorePageReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 门店管理 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface StoreMapper extends BaseMapperX<StoreDO> {
default PageResult<StoreDO> selectPage(StorePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<StoreDO>()
.likeIfPresent(StoreDO::getStoreName, reqVO.getStoreName())
.eqIfPresent(StoreDO::getAreaId, reqVO.getAreaId())
.eqIfPresent(StoreDO::getDetailedLocation, reqVO.getDetailedLocation())
.eqIfPresent(StoreDO::getLatitude, reqVO.getLatitude())
.eqIfPresent(StoreDO::getLongitude, reqVO.getLongitude())
.eqIfPresent(StoreDO::getPostalCode, reqVO.getPostalCode())
.eqIfPresent(StoreDO::getPhoneNumber, reqVO.getPhoneNumber())
.eqIfPresent(StoreDO::getEmail, reqVO.getEmail())
.likeIfPresent(StoreDO::getManagerName, reqVO.getManagerName())
.betweenIfPresent(StoreDO::getCreateTime, reqVO.getCreateTime())
.eqIfPresent(StoreDO::getStatus, reqVO.getStatus())
.orderByDesc(StoreDO::getId));
}
}

View File

@@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.car.dal.mysql.tireuser;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserPageReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 门店管理 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface TireUserMapper extends BaseMapperX<TireUserDO> {
List<TireUserDO> selectPage(@Param("reqVO") TireUserPageReqVO reqVO);
TireUserDO findByUserId(@Param("userId") Long userId);
// default PageResult<TireUserDO> selectPage(TireUserPageReqVO reqVO) {
// return selectPage(reqVO, new LambdaQueryWrapperX<TireUserDO>()
// .eqIfPresent(TireUserDO::getUserId, reqVO.getUserId()) // 修正字段方法
// .eqIfPresent(TireUserDO::getStoreId, reqVO.getStoreId())
// .eqIfPresent(TireUserDO::getWarehouseId, reqVO.getWarehouseId())
// .inIfPresent(TireUserDO::getUserId, userIds) // 修正 inIfPresent 的字段
// .orderByDesc(TireUserDO::getId)); // 确保排序逻辑无误
// }
}

View File

@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.car.service.renewalorder;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalorder.RenewalOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 车辆续保订单 Service 接口
*
* @author 芋道源码
*/
public interface RenewalOrderService {
/**
* 创建车辆续保订单
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createRenewalOrder(@Valid RenewalOrderSaveReqVO createReqVO);
/**
* 更新车辆续保订单
*
* @param updateReqVO 更新信息
*/
void updateRenewalOrder(@Valid RenewalOrderSaveReqVO updateReqVO);
/**
* 删除车辆续保订单
*
* @param id 编号
*/
void deleteRenewalOrder(Long id);
/**
* 获得车辆续保订单
*
* @param id 编号
* @return 车辆续保订单
*/
RenewalOrderDO getRenewalOrder(Long id);
/**
* 获得车辆续保订单分页
*
* @param pageReqVO 分页查询
* @return 车辆续保订单分页
*/
PageResult<RenewalOrderDO> getRenewalOrderPage(RenewalOrderPageReqVO pageReqVO);
}

View File

@@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.car.service.renewalorder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalorder.RenewalOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.dal.mysql.renewalorder.RenewalOrderMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.*;
/**
* 车辆续保订单 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class RenewalOrderServiceImpl implements RenewalOrderService {
@Resource
private RenewalOrderMapper renewalOrderMapper;
@Override
public Long createRenewalOrder(RenewalOrderSaveReqVO createReqVO) {
// 插入
RenewalOrderDO renewalOrder = BeanUtils.toBean(createReqVO, RenewalOrderDO.class);
renewalOrderMapper.insert(renewalOrder);
// 返回
return renewalOrder.getId();
}
@Override
public void updateRenewalOrder(RenewalOrderSaveReqVO updateReqVO) {
// 校验存在
validateRenewalOrderExists(updateReqVO.getId());
// 更新
RenewalOrderDO updateObj = BeanUtils.toBean(updateReqVO, RenewalOrderDO.class);
renewalOrderMapper.updateById(updateObj);
}
@Override
public void deleteRenewalOrder(Long id) {
// 校验存在
validateRenewalOrderExists(id);
// 删除
renewalOrderMapper.deleteById(id);
}
private void validateRenewalOrderExists(Long id) {
if (renewalOrderMapper.selectById(id) == null) {
throw exception(RENEWAL_ORDER_NOT_EXISTS);
}
}
@Override
public RenewalOrderDO getRenewalOrder(Long id) {
return renewalOrderMapper.selectById(id);
}
@Override
public PageResult<RenewalOrderDO> getRenewalOrderPage(RenewalOrderPageReqVO pageReqVO) {
return renewalOrderMapper.selectPage(pageReqVO);
}
}

View File

@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.car.service.renewalproduct;
import java.util.*;
import javax.validation.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct.RenewalProductDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
/**
* 车辆续保产品信息 Service 接口
*
* @author 芋道源码
*/
public interface RenewalProductService {
/**
* 创建车辆续保产品信息
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createRenewalProduct(@Valid RenewalProductSaveReqVO createReqVO);
/**
* 更新车辆续保产品信息
*
* @param updateReqVO 更新信息
*/
void updateRenewalProduct(@Valid RenewalProductSaveReqVO updateReqVO);
/**
* 删除车辆续保产品信息
*
* @param id 编号
*/
void deleteRenewalProduct(Long id);
/**
* 获得车辆续保产品信息
*
* @param id 编号
* @return 车辆续保产品信息
*/
RenewalProductDO getRenewalProduct(Long id);
/**
* 获得车辆续保产品信息分页
*
* @param pageReqVO 分页查询
* @return 车辆续保产品信息分页
*/
PageResult<RenewalProductDO> getRenewalProductPage(RenewalProductPageReqVO pageReqVO);
}

View File

@@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.car.service.renewalproduct;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct.RenewalProductDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.dal.mysql.renewalproduct.RenewalProductMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.*;
/**
* 车辆续保产品信息 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class RenewalProductServiceImpl implements RenewalProductService {
@Resource
private RenewalProductMapper renewalProductMapper;
@Override
public Long createRenewalProduct(RenewalProductSaveReqVO createReqVO) {
// 插入
RenewalProductDO renewalProduct = BeanUtils.toBean(createReqVO, RenewalProductDO.class);
renewalProductMapper.insert(renewalProduct);
// 返回
return renewalProduct.getId();
}
@Override
public void updateRenewalProduct(RenewalProductSaveReqVO updateReqVO) {
// 校验存在
validateRenewalProductExists(updateReqVO.getId());
// 更新
RenewalProductDO updateObj = BeanUtils.toBean(updateReqVO, RenewalProductDO.class);
renewalProductMapper.updateById(updateObj);
}
@Override
public void deleteRenewalProduct(Long id) {
// 校验存在
validateRenewalProductExists(id);
// 删除
renewalProductMapper.deleteById(id);
}
private void validateRenewalProductExists(Long id) {
if (renewalProductMapper.selectById(id) == null) {
throw exception(RENEWAL_PRODUCT_NOT_EXISTS);
}
}
@Override
public RenewalProductDO getRenewalProduct(Long id) {
return renewalProductMapper.selectById(id);
}
@Override
public PageResult<RenewalProductDO> getRenewalProductPage(RenewalProductPageReqVO pageReqVO) {
return renewalProductMapper.selectPage(pageReqVO);
}
}

View File

@@ -0,0 +1,93 @@
package cn.iocoder.yudao.module.car.service.statistics;
import cn.iocoder.yudao.module.car.controller.admin.statistics.vo.*;
import java.util.List;
/**
* 车辆续保统计 Service 接口
*
* @author 芋道源码
*/
public interface StatisticsService {
/**
* 获取门店销售统计
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 门店销售统计列表
*/
List<StoreSalesStatisticsRespVO> getStoreSalesStatistics(String startTime, String endTime, Long storeId);
/**
* 获取业务员销售统计
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 业务员销售统计列表
*/
List<SalespersonStatisticsRespVO> getSalespersonStatistics(String startTime, String endTime, Long storeId);
/**
* 获取业务员销售排行
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 业务员销售排行列表
*/
List<SalespersonStatisticsRespVO> getSalespersonRank(String startTime, String endTime, Long storeId);
/**
* 获取门店销售趋势
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 门店销售趋势列表
*/
List<StoreSalesTrendRespVO> getStoreSalesTrend(String startTime, String endTime, Long storeId);
/**
* 获取业务员销售趋势
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 业务员销售趋势列表
*/
List<SalespersonSalesTrendRespVO> getSalespersonSalesTrend(String startTime, String endTime, Long storeId);
/**
* 获取业务员开单率分析
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 业务员开单率分析列表
*/
List<SalespersonStatisticsRespVO> getSalespersonOrderRate(String startTime, String endTime, Long storeId);
/**
* 获取门店开单率分析
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 门店开单率分析列表
*/
List<StoreSalesStatisticsRespVO> getStoreOrderRate(String startTime, String endTime, Long storeId);
/**
* 获取汇总统计
*
* @param startTime 开始时间
* @param endTime 结束时间
* @param storeId 门店ID可选
* @return 汇总统计数据
*/
SummaryStatisticsRespVO getSummaryStatistics(String startTime, String endTime, Long storeId);
}

View File

@@ -0,0 +1,202 @@
package cn.iocoder.yudao.module.car.service.statistics;
import cn.iocoder.yudao.module.car.controller.admin.statistics.vo.*;
import cn.iocoder.yudao.module.car.dal.mysql.statistics.StatisticsMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* 车辆续保统计 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class StatisticsServiceImpl implements StatisticsService {
@Resource
private StatisticsMapper statisticsMapper;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public List<StoreSalesStatisticsRespVO> getStoreSalesStatistics(String startTime, String endTime, Long storeId) {
LocalDateTime start = startTime != null ? LocalDateTime.parse(startTime, DATETIME_FORMATTER) : null;
LocalDateTime end = endTime != null ? LocalDateTime.parse(endTime, DATETIME_FORMATTER) : null;
// 获取门店销售统计数据
List<StoreSalesStatisticsRespVO> list = statisticsMapper.selectStoreSalesStatistics(start, end, storeId);
// 计算平均订单金额、开单率等指标
for (StoreSalesStatisticsRespVO vo : list) {
if (vo.getOrderCount() != null && vo.getOrderCount() > 0 && vo.getTotalAmount() != null) {
vo.setAverageOrderAmount(vo.getTotalAmount()
.divide(BigDecimal.valueOf(vo.getOrderCount()), 2, RoundingMode.HALF_UP));
}
// 计算平均开单天数(需要根据实际业务逻辑计算)
vo.setAverageOrderDays(calculateAverageOrderDays(vo.getStoreId(), start, end));
// 计算30天开单率
vo.setOrderRate30Days(calculateOrderRate30Days(vo.getStoreId()));
// 计算距上次开单天数
vo.setLastOrderDays(calculateLastOrderDays(vo.getStoreId()));
}
return list;
}
@Override
public List<SalespersonStatisticsRespVO> getSalespersonStatistics(String startTime, String endTime, Long storeId) {
LocalDateTime start = startTime != null ? LocalDateTime.parse(startTime, DATETIME_FORMATTER) : null;
LocalDateTime end = endTime != null ? LocalDateTime.parse(endTime, DATETIME_FORMATTER) : null;
// 获取业务员销售统计数据
List<SalespersonStatisticsRespVO> list = statisticsMapper.selectSalespersonStatistics(start, end, storeId);
// 计算平均订单金额、开单率等指标
for (SalespersonStatisticsRespVO vo : list) {
if (vo.getOrderCount() != null && vo.getOrderCount() > 0 && vo.getTotalAmount() != null) {
vo.setAverageOrderAmount(vo.getTotalAmount()
.divide(BigDecimal.valueOf(vo.getOrderCount()), 2, RoundingMode.HALF_UP));
}
// 计算平均开单天数
vo.setAverageOrderDays(calculateAverageOrderDaysForSalesperson(vo.getSalespersonId(), start, end));
// 计算30天开单率
vo.setOrderRate30Days(calculateOrderRate30DaysForSalesperson(vo.getSalespersonId()));
// 计算距上次开单天数
vo.setLastOrderDays(calculateLastOrderDaysForSalesperson(vo.getSalespersonId()));
}
return list;
}
@Override
public List<SalespersonStatisticsRespVO> getSalespersonRank(String startTime, String endTime, Long storeId) {
List<SalespersonStatisticsRespVO> list = getSalespersonStatistics(startTime, endTime, storeId);
// 按销售金额降序排序
return list.stream()
.sorted((a, b) -> {
if (a.getTotalAmount() == null) return 1;
if (b.getTotalAmount() == null) return -1;
return b.getTotalAmount().compareTo(a.getTotalAmount());
})
.collect(Collectors.toList());
}
@Override
public List<StoreSalesTrendRespVO> getStoreSalesTrend(String startTime, String endTime, Long storeId) {
LocalDateTime start = startTime != null ? LocalDateTime.parse(startTime, DATETIME_FORMATTER) : null;
LocalDateTime end = endTime != null ? LocalDateTime.parse(endTime, DATETIME_FORMATTER) : null;
return statisticsMapper.selectStoreSalesTrend(start, end, storeId);
}
@Override
public List<SalespersonSalesTrendRespVO> getSalespersonSalesTrend(String startTime, String endTime, Long storeId) {
LocalDateTime start = startTime != null ? LocalDateTime.parse(startTime, DATETIME_FORMATTER) : null;
LocalDateTime end = endTime != null ? LocalDateTime.parse(endTime, DATETIME_FORMATTER) : null;
return statisticsMapper.selectSalespersonSalesTrend(start, end, storeId);
}
@Override
public List<SalespersonStatisticsRespVO> getSalespersonOrderRate(String startTime, String endTime, Long storeId) {
return getSalespersonStatistics(startTime, endTime, storeId);
}
@Override
public List<StoreSalesStatisticsRespVO> getStoreOrderRate(String startTime, String endTime, Long storeId) {
return getStoreSalesStatistics(startTime, endTime, storeId);
}
/**
* 计算门店平均开单天数
*/
private Integer calculateAverageOrderDays(Long storeId, LocalDateTime start, LocalDateTime end) {
// TODO: 根据实际业务逻辑实现
// 这里需要查询该门店的所有订单,计算平均间隔天数
return statisticsMapper.calculateAverageOrderDaysForStore(storeId, start, end);
}
/**
* 计算业务员平均开单天数
*/
private Integer calculateAverageOrderDaysForSalesperson(String salespersonId, LocalDateTime start, LocalDateTime end) {
// TODO: 根据实际业务逻辑实现
return statisticsMapper.calculateAverageOrderDaysForSalesperson(salespersonId, start, end);
}
/**
* 计算门店30天开单率
*/
private BigDecimal calculateOrderRate30Days(Long storeId) {
// TODO: 计算最近30天内有订单的天数 / 30
return statisticsMapper.calculateOrderRate30DaysForStore(storeId);
}
/**
* 计算业务员30天开单率
*/
private BigDecimal calculateOrderRate30DaysForSalesperson(String salespersonId) {
// TODO: 计算最近30天内有订单的天数 / 30
return statisticsMapper.calculateOrderRate30DaysForSalesperson(salespersonId);
}
/**
* 计算门店距上次开单天数
*/
private Integer calculateLastOrderDays(Long storeId) {
// TODO: 查询该门店最后一次订单的日期,计算距今天数
return statisticsMapper.calculateLastOrderDaysForStore(storeId);
}
/**
* 计算业务员距上次开单天数
*/
private Integer calculateLastOrderDaysForSalesperson(String salespersonId) {
// TODO: 查询该业务员最后一次订单的日期,计算距今天数
return statisticsMapper.calculateLastOrderDaysForSalesperson(salespersonId);
}
@Override
public SummaryStatisticsRespVO getSummaryStatistics(String startTime, String endTime, Long storeId) {
LocalDateTime start = startTime != null ? LocalDateTime.parse(startTime, DATETIME_FORMATTER) : null;
LocalDateTime end = endTime != null ? LocalDateTime.parse(endTime, DATETIME_FORMATTER) : null;
SummaryStatisticsRespVO result = statisticsMapper.selectSummaryStatistics(start, end, storeId);
// 如果查询结果为空,返回默认值
if (result == null) {
result = new SummaryStatisticsRespVO();
result.setTotalAmount(BigDecimal.ZERO);
result.setTotalOrderCount(0);
result.setAverageOrderAmount(BigDecimal.ZERO);
result.setActiveStoreCount(0);
} else {
// 确保平均订单金额正确计算保留2位小数
if (result.getTotalOrderCount() != null && result.getTotalOrderCount() > 0
&& result.getTotalAmount() != null) {
result.setAverageOrderAmount(
result.getTotalAmount()
.divide(BigDecimal.valueOf(result.getTotalOrderCount()), 2, RoundingMode.HALF_UP)
);
} else {
result.setAverageOrderAmount(BigDecimal.ZERO);
}
}
return result;
}
}

View File

@@ -0,0 +1,55 @@
package cn.iocoder.yudao.module.car.service.store;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StorePageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StoreSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import javax.validation.Valid;
/**
* 门店管理 Service 接口
*
* @author 芋道源码
*/
public interface StoreService {
/**
* 创建门店管理
*
* @param createReqVO 创建信息
* @return 编号
*/
Integer createStore(@Valid StoreSaveReqVO createReqVO);
/**
* 更新门店管理
*
* @param updateReqVO 更新信息
*/
void updateStore(@Valid StoreSaveReqVO updateReqVO);
/**
* 删除门店管理
*
* @param id 编号
*/
void deleteStore(Integer id);
/**
* 获得门店管理
*
* @param id 编号
* @return 门店管理
*/
StoreDO getStore(Integer id);
/**
* 获得门店管理分页
*
* @param pageReqVO 分页查询
* @return 门店管理分页
*/
PageResult<StoreDO> getStorePage(StorePageReqVO pageReqVO);
}

View File

@@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.car.service.store;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StorePageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.store.vo.StoreSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.store.StoreDO;
import cn.iocoder.yudao.module.car.dal.mysql.store.StoreMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.STORE_NOT_EXISTS;
/**
* 门店管理 Service 实现类
*
* @author 芋道源码
*/
@Service
@Validated
public class StoreServiceImpl implements StoreService {
@Resource
private StoreMapper storeMapper;
@Override
public Integer createStore(StoreSaveReqVO createReqVO) {
// 插入
StoreDO store = BeanUtils.toBean(createReqVO, StoreDO.class);
storeMapper.insert(store);
// 返回
return store.getId();
}
@Override
public void updateStore(StoreSaveReqVO updateReqVO) {
// 校验存在
validateStoreExists(updateReqVO.getId());
// 更新
StoreDO updateObj = BeanUtils.toBean(updateReqVO, StoreDO.class);
storeMapper.updateById(updateObj);
}
@Override
public void deleteStore(Integer id) {
// 校验存在
validateStoreExists(id);
// 删除
storeMapper.deleteById(id);
}
private void validateStoreExists(Integer id) {
if (storeMapper.selectById(id) == null) {
throw exception(STORE_NOT_EXISTS);
}
}
@Override
public StoreDO getStore(Integer id) {
return storeMapper.selectById(id);
}
@Override
public PageResult<StoreDO> getStorePage(StorePageReqVO pageReqVO) {
return storeMapper.selectPage(pageReqVO);
}
}

View File

@@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.car.service.tireuser;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserPageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO;
/**
* 门店用户管理 Service 接口
*
* 提供对门店用户的增删改查功能,包括分页查询。
*
* @author 欧浩蓝
*/
public interface TireUserService {
/**
* 创建门店用户
*
* @param createReqVO 包含用户信息的请求对象
* @return 创建的用户 ID
*/
Integer createTireUser(TireUserSaveReqVO createReqVO);
/**
* 分页查询轮胎仓库用户
*
* @param pageReqVO 包含分页参数的请求对象
* @return 轮胎仓库用户的分页结果
*/
PageResult<TireUserDO> getTireWarehouseUserPage(TireUserPageReqVO pageReqVO);
/**
* 分页查询门店用户
*
* @param pageReqVO 包含分页参数的请求对象
* @return 门店用户的分页结果
*/
PageResult<TireUserDO> getTireStoreUserPage(TireUserPageReqVO pageReqVO);
/**
* 更新门店用户信息
*
* @param updateReqVO 包含更新信息的请求对象
*/
void updateTireUser(TireUserSaveReqVO updateReqVO);
/**
* 删除门店用户
*
* @param id 需要删除的用户 ID
*/
void deleteTireUser(Integer id);
/**
* 根据 ID 获取门店用户信息
*
* @param id 用户 ID
* @return 轮胎门店用户对象
*/
TireUserDO getTireUser(Integer id);
/**
* 根据用户 ID 查询门店用户
*
* @param userId 用户 ID
* @return 轮胎门店用户对象
*/
TireUserDO findByUserId(Long userId);
}

View File

@@ -0,0 +1,166 @@
package cn.iocoder.yudao.module.car.service.tireuser;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserPageReqVO;
import cn.iocoder.yudao.module.car.controller.admin.tireuser.vo.TireUserSaveReqVO;
import cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO;
import cn.iocoder.yudao.module.car.dal.mysql.tireuser.TireUserMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.TIRE_NOT_USER;
/**
* 门店用户管理 Service 实现类
*/
@Service
@Validated
public class TireUserServiceImpl implements TireUserService {
@Resource
private TireUserMapper tireUserMapper;
@Resource
private AdminUserService adminUserService;
/**
* 创建轮胎用户
*
* @param createReqVO 创建请求参数包含用户信息、门店ID、仓库ID
* @return 新创建的用户ID
*/
@Override
@Transactional
public Integer createTireUser(TireUserSaveReqVO createReqVO) {
Long userId = adminUserService.createUser(createReqVO.getUser());
Long storeId = createReqVO.getStoreId();
Long warehouseId = createReqVO.getWarehouseId();
TireUserDO entity = new TireUserDO();
entity.setStoreId(storeId);
entity.setWarehouseId(warehouseId);
entity.setUserId(userId);
return tireUserMapper.insert(entity);
}
/**
* 获取轮胎用户的分页数据
*
* @param pageReqVO 分页请求参数
* @param isWarehouse 是否查询仓库用户true: 仓库用户, false: 门店用户)
* @return 轮胎用户分页数据
*/
private PageResult<TireUserDO> getTireUserPage(TireUserPageReqVO pageReqVO, boolean isWarehouse) {
List<TireUserDO> tireUserList = tireUserMapper.selectPage(pageReqVO);
if (CollectionUtils.isEmpty(tireUserList)) {
return new PageResult<>(Collections.emptyList(), tireUserMapper.selectCount());
}
tireUserList = tireUserList.stream()
.filter(item -> Objects.nonNull(isWarehouse ? item.getWarehouseId() : item.getStoreId()))
.collect(Collectors.toList());
List<Long> userIds = tireUserList.stream()
.map(TireUserDO::getUserId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
Map<Long, AdminUserDO> userMap = adminUserService.getUserMap(userIds);
tireUserList.forEach(tireUser -> tireUser.setUser(userMap.get(tireUser.getUserId())));
return new PageResult<>(tireUserList, tireUserMapper.selectCount());
}
/**
* 获取仓库用户分页数据
*
* @param pageReqVO 分页请求参数
* @return 仓库用户分页数据
*/
@Override
public PageResult<TireUserDO> getTireWarehouseUserPage(TireUserPageReqVO pageReqVO) {
return getTireUserPage(pageReqVO, true);
}
/**
* 获取门店用户分页数据
*
* @param pageReqVO 分页请求参数
* @return 门店用户分页数据
*/
@Override
public PageResult<TireUserDO> getTireStoreUserPage(TireUserPageReqVO pageReqVO) {
return getTireUserPage(pageReqVO, false);
}
/**
* 更新轮胎用户信息
*
* @param updateReqVO 更新请求参数,包含用户信息
*/
@Override
@Transactional
public void updateTireUser(TireUserSaveReqVO updateReqVO) {
adminUserService.updateUser(updateReqVO.getUser());
TireUserDO tireUserDO = BeanUtils.toBean(updateReqVO, TireUserDO.class);
tireUserMapper.updateById(tireUserDO);
}
/**
* 删除轮胎用户
*
* @param id 用户ID
*/
@Override
@Transactional
public void deleteTireUser(Integer id) {
TireUserDO tireUserDO = tireUserMapper.selectById(id);
adminUserService.deleteUser(tireUserDO.getUserId());
tireUserMapper.deleteById(id);
}
/**
* 获取轮胎用户详情
*
* @param id 用户ID
* @return 轮胎用户详情
*/
@Override
@Transactional
public TireUserDO getTireUser(Integer id) {
TireUserDO tireUserDO = tireUserMapper.selectById(id);
AdminUserDO user = adminUserService.getUser(tireUserDO.getUserId());
tireUserDO.setUser(user);
return tireUserDO;
}
/**
* 根据用户ID查找轮胎用户
*
* @param userId 用户ID
* @return 轮胎用户对象
* @throws ServiceException 如果用户不存在,则抛出异常
*/
@Override
public TireUserDO findByUserId(Long userId) {
TireUserDO tireUserDO = tireUserMapper.findByUserId(userId);
if (Objects.isNull(tireUserDO)) {
throw exception(TIRE_NOT_USER);
}
return tireUserDO;
}
}

Binary file not shown.

View File

@@ -0,0 +1,12 @@
<?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="cn.iocoder.yudao.module.car.dal.mysql.renewalorder.RenewalOrderMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@@ -0,0 +1,12 @@
<?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="cn.iocoder.yudao.module.car.dal.mysql.renewalproduct.RenewalProductMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@@ -0,0 +1,201 @@
<?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="cn.iocoder.yudao.module.car.dal.mysql.statistics.StatisticsMapper">
<!-- ==================== 公共 SQL 片段 ==================== -->
<!-- 时间范围 -->
<sql id="timeRange">
<if test="start != null">
AND o.create_time <![CDATA[>=]]> #{start}
</if>
<if test="end != null">
AND o.create_time <![CDATA[<=]]> #{end}
</if>
</sql>
<!-- ==================== 门店销售统计 ==================== -->
<select id="selectStoreSalesStatistics"
resultType="cn.iocoder.yudao.module.car.controller.admin.statistics.vo.StoreSalesStatisticsRespVO">
SELECT
s.id AS storeId,
s.store_name AS storeName,
COALESCE(SUM(o.product_fee), 0) AS totalAmount,
COUNT(o.id) AS orderCount
FROM tire_store s
LEFT JOIN car_renewal_order o ON s.id = o.store_id
<where>
<include refid="timeRange"/>
<if test="storeId != null">
AND s.id = #{storeId}
</if>
</where>
GROUP BY s.id, s.store_name
ORDER BY totalAmount DESC
</select>
<!-- ==================== 业务员销售统计 ==================== -->
<select id="selectSalespersonStatistics"
resultType="cn.iocoder.yudao.module.car.controller.admin.statistics.vo.SalespersonStatisticsRespVO">
SELECT
o.input_user AS salespersonId,
o.input_user AS salespersonName,
s.id AS storeId,
s.store_name AS storeName,
COALESCE(SUM(o.product_fee), 0) AS totalAmount,
COUNT(o.id) AS orderCount
FROM car_renewal_order o
LEFT JOIN tire_store s ON o.store_id = s.id
<where>
<include refid="timeRange"/>
<if test="storeId != null">
AND o.store_id = #{storeId}
</if>
AND o.input_user IS NOT NULL
</where>
GROUP BY o.input_user, s.id, s.store_name
ORDER BY totalAmount DESC
</select>
<!-- ==================== 门店销售趋势 ==================== -->
<select id="selectStoreSalesTrend"
resultType="cn.iocoder.yudao.module.car.controller.admin.statistics.vo.StoreSalesTrendRespVO">
SELECT
DATE_FORMAT(o.create_time, '%Y-%m-%d') AS date,
s.store_name AS storeName,
COALESCE(SUM(o.product_fee), 0) AS amount
FROM car_renewal_order o
LEFT JOIN tire_store s ON o.store_id = s.id
<where>
<include refid="timeRange"/>
<if test="storeId != null">
AND o.store_id = #{storeId}
</if>
</where>
GROUP BY DATE_FORMAT(o.create_time, '%Y-%m-%d'), s.store_name
ORDER BY date ASC
</select>
<!-- ==================== 业务员销售趋势 ==================== -->
<select id="selectSalespersonSalesTrend"
resultType="cn.iocoder.yudao.module.car.controller.admin.statistics.vo.SalespersonSalesTrendRespVO">
SELECT
DATE_FORMAT(o.create_time, '%Y-%m-%d') AS date,
o.input_user AS salespersonName,
COALESCE(SUM(o.product_fee), 0) AS amount
FROM car_renewal_order o
<where>
<include refid="timeRange"/>
<if test="storeId != null">
AND o.store_id = #{storeId}
</if>
AND o.input_user IS NOT NULL
</where>
GROUP BY DATE_FORMAT(o.create_time, '%Y-%m-%d'), o.input_user
ORDER BY date ASC
</select>
<!-- ==================== 门店平均开单天数 ==================== -->
<select id="calculateAverageOrderDaysForStore" resultType="java.lang.Integer">
SELECT
CASE
WHEN COUNT(DISTINCT DATE(create_time)) > 1
THEN DATEDIFF(MAX(create_time), MIN(create_time))
/ (COUNT(DISTINCT DATE(create_time)) - 1)
ELSE NULL
END
FROM car_renewal_order
WHERE store_id = #{storeId}
<if test="start != null">
AND create_time <![CDATA[>=]]> #{start}
</if>
<if test="end != null">
AND create_time <![CDATA[<=]]> #{end}
</if>
</select>
<!-- ==================== 业务员平均开单天数 ==================== -->
<select id="calculateAverageOrderDaysForSalesperson" resultType="java.lang.Integer">
SELECT
CASE
WHEN COUNT(DISTINCT DATE(create_time)) > 1
THEN DATEDIFF(MAX(create_time), MIN(create_time))
/ (COUNT(DISTINCT DATE(create_time)) - 1)
ELSE NULL
END
FROM car_renewal_order
WHERE input_user = #{salespersonId}
<if test="start != null">
AND create_time <![CDATA[>=]]> #{start}
</if>
<if test="end != null">
AND create_time <![CDATA[<=]]> #{end}
</if>
</select>
<!-- ==================== 门店 30 天开单率 ==================== -->
<select id="calculateOrderRate30DaysForStore" resultType="java.math.BigDecimal">
SELECT
COUNT(DISTINCT DATE(create_time)) / 30.0
FROM car_renewal_order
WHERE store_id = #{storeId}
AND create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
</select>
<!-- ==================== 业务员 30 天开单率 ==================== -->
<select id="calculateOrderRate30DaysForSalesperson" resultType="java.math.BigDecimal">
SELECT
COUNT(DISTINCT DATE(create_time)) / 30.0
FROM car_renewal_order
WHERE input_user = #{salespersonId}
AND create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
</select>
<!-- ==================== 门店距上次开单天数 ==================== -->
<select id="calculateLastOrderDaysForStore" resultType="java.lang.Integer">
SELECT
DATEDIFF(NOW(), MAX(create_time))
FROM car_renewal_order
WHERE store_id = #{storeId}
</select>
<!-- ==================== 业务员距上次开单天数 ==================== -->
<select id="calculateLastOrderDaysForSalesperson" resultType="java.lang.Integer">
SELECT
DATEDIFF(NOW(), MAX(create_time))
FROM car_renewal_order
WHERE input_user = #{salespersonId}
</select>
<!-- ==================== 汇总统计 ==================== -->
<select id="selectSummaryStatistics"
resultType="cn.iocoder.yudao.module.car.controller.admin.statistics.vo.SummaryStatisticsRespVO">
SELECT
COALESCE(SUM(o.product_fee), 0) AS totalAmount,
COUNT(o.id) AS totalOrderCount,
CASE
WHEN COUNT(o.id) > 0 THEN COALESCE(SUM(o.product_fee), 0) / COUNT(o.id)
ELSE 0
END AS averageOrderAmount,
COUNT(DISTINCT o.store_id) AS activeStoreCount
FROM car_renewal_order o
<where>
<include refid="timeRange"/>
<if test="storeId != null">
AND o.store_id = #{storeId}
</if>
</where>
</select>
</mapper>

View File

@@ -0,0 +1,12 @@
<?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="cn.iocoder.yudao.module.car.dal.mysql.store.StoreMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>

View File

@@ -0,0 +1,48 @@
<?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="cn.iocoder.yudao.module.car.dal.mysql.tireuser.TireUserMapper">
<select id="selectPage" resultType="cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO">
SELECT t1.*
FROM tire_user t1
LEFT JOIN system_users t2 on t2.id = t1.user_id
WHERE t1.deleted = false and t2.id != '0'
<if test="reqVO.userId != null">
AND t1.user_id = #{reqVO.userId}
</if>
<if test="reqVO.storeId != null">
AND t1.store_id = #{reqVO.storeId}
</if>
<if test="reqVO.warehouseId != null">
AND t1.warehouse_id = #{reqVO.warehouseId}
</if>
<if test="reqVO.user != null">
<if test="reqVO.user.username != null and !reqVO.user.username.isEmpty()">
AND t2.username = #{reqVO.user.username}
</if>
<if test="reqVO.user.mobile != null and !reqVO.user.mobile.isEmpty()">
AND t2.mobile = #{reqVO.user.mobile}
</if>
<if test="reqVO.user.status != null">
AND t2.status = #{reqVO.user.status}
</if>
<if test="reqVO.user.createTime != null and reqVO.user.createTime[0] != null">
AND t2.create_time &gt;= #{reqVO.user.createTime[0]}
</if>
<if test="reqVO.user.createTime != null and reqVO.user.createTime[1] != null">
AND t2.create_time &lt;= #{reqVO.user.createTime[1]}
</if>
</if>
ORDER BY id DESC
</select>
<select id="findByUserId" resultType="cn.iocoder.yudao.module.car.dal.dataobject.tireuser.TireUserDO">
SELECT t1.*
FROM tire_user t1
LEFT JOIN system_users t2 on t2.id = t1.user_id
WHERE t1.deleted = false and t2.id != '0'
<if test="userId != null">
AND t1.user_id = #{userId}
</if>
ORDER BY id DESC
</select>
</mapper>

View File

@@ -0,0 +1,234 @@
package cn.iocoder.yudao.module.car.service.renewalorder;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.car.controller.admin.renewalorder.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalorder.RenewalOrderDO;
import cn.iocoder.yudao.module.car.dal.mysql.renewalorder.RenewalOrderMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link RenewalOrderServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(RenewalOrderServiceImpl.class)
public class RenewalOrderServiceImplTest extends BaseDbUnitTest {
@Resource
private RenewalOrderServiceImpl renewalOrderService;
@Resource
private RenewalOrderMapper renewalOrderMapper;
@Test
public void testCreateRenewalOrder_success() {
// 准备参数
RenewalOrderSaveReqVO createReqVO = randomPojo(RenewalOrderSaveReqVO.class).setId(null);
// 调用
Long renewalOrderId = renewalOrderService.createRenewalOrder(createReqVO);
// 断言
assertNotNull(renewalOrderId);
// 校验记录的属性是否正确
RenewalOrderDO renewalOrder = renewalOrderMapper.selectById(renewalOrderId);
assertPojoEquals(createReqVO, renewalOrder, "id");
}
@Test
public void testUpdateRenewalOrder_success() {
// mock 数据
RenewalOrderDO dbRenewalOrder = randomPojo(RenewalOrderDO.class);
renewalOrderMapper.insert(dbRenewalOrder);// @Sql: 先插入出一条存在的数据
// 准备参数
RenewalOrderSaveReqVO updateReqVO = randomPojo(RenewalOrderSaveReqVO.class, o -> {
o.setId(dbRenewalOrder.getId()); // 设置更新的 ID
});
// 调用
renewalOrderService.updateRenewalOrder(updateReqVO);
// 校验是否更新正确
RenewalOrderDO renewalOrder = renewalOrderMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, renewalOrder);
}
@Test
public void testUpdateRenewalOrder_notExists() {
// 准备参数
RenewalOrderSaveReqVO updateReqVO = randomPojo(RenewalOrderSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> renewalOrderService.updateRenewalOrder(updateReqVO), RENEWAL_ORDER_NOT_EXISTS);
}
@Test
public void testDeleteRenewalOrder_success() {
// mock 数据
RenewalOrderDO dbRenewalOrder = randomPojo(RenewalOrderDO.class);
renewalOrderMapper.insert(dbRenewalOrder);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbRenewalOrder.getId();
// 调用
renewalOrderService.deleteRenewalOrder(id);
// 校验数据不存在了
assertNull(renewalOrderMapper.selectById(id));
}
@Test
public void testDeleteRenewalOrder_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> renewalOrderService.deleteRenewalOrder(id), RENEWAL_ORDER_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetRenewalOrderPage() {
// mock 数据
RenewalOrderDO dbRenewalOrder = randomPojo(RenewalOrderDO.class, o -> { // 等会查询到
o.setCarBrand(null);
o.setCarModel(null);
o.setLicensePlate(null);
o.setFactoryModel(null);
o.setInvoiceAmount(null);
o.setPurchaseMileage(null);
o.setEngineNo(null);
o.setVin(null);
o.setInvoiceDate(null);
o.setServiceBuyer(null);
o.setCarBuyer(null);
o.setCertType(null);
o.setMobile(null);
o.setCertNo(null);
o.setContactAddress(null);
o.setMemberEmail(null);
o.setProductId(null);
o.setServiceProduct(null);
o.setProductValidity(null);
o.setOriginalWarrantyYears(null);
o.setOriginalWarrantyMileage(null);
o.setProductFee(null);
o.setSettlementMethod(null);
o.setRemark(null);
o.setInputUser(null);
o.setContractRemark(null);
o.setCreateTime(null);
});
renewalOrderMapper.insert(dbRenewalOrder);
// 测试 carBrand 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCarBrand(null)));
// 测试 carModel 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCarModel(null)));
// 测试 licensePlate 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setLicensePlate(null)));
// 测试 factoryModel 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setFactoryModel(null)));
// 测试 invoiceAmount 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setInvoiceAmount(null)));
// 测试 purchaseMileage 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setPurchaseMileage(null)));
// 测试 engineNo 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setEngineNo(null)));
// 测试 vin 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setVin(null)));
// 测试 invoiceDate 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setInvoiceDate(null)));
// 测试 serviceBuyer 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setServiceBuyer(null)));
// 测试 carBuyer 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCarBuyer(null)));
// 测试 certType 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCertType(null)));
// 测试 mobile 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setMobile(null)));
// 测试 certNo 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCertNo(null)));
// 测试 contactAddress 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setContactAddress(null)));
// 测试 memberEmail 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setMemberEmail(null)));
// 测试 productId 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setProductId(null)));
// 测试 serviceProduct 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setServiceProduct(null)));
// 测试 productValidity 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setProductValidity(null)));
// 测试 originalWarrantyYears 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setOriginalWarrantyYears(null)));
// 测试 originalWarrantyMileage 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setOriginalWarrantyMileage(null)));
// 测试 productFee 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setProductFee(null)));
// 测试 settlementMethod 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setSettlementMethod(null)));
// 测试 remark 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setRemark(null)));
// 测试 inputUser 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setInputUser(null)));
// 测试 contractRemark 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setContractRemark(null)));
// 测试 createTime 不匹配
renewalOrderMapper.insert(cloneIgnoreId(dbRenewalOrder, o -> o.setCreateTime(null)));
// 准备参数
RenewalOrderPageReqVO reqVO = new RenewalOrderPageReqVO();
reqVO.setCarBrand(null);
reqVO.setCarModel(null);
reqVO.setLicensePlate(null);
reqVO.setFactoryModel(null);
reqVO.setInvoiceAmount(null);
reqVO.setPurchaseMileage(null);
reqVO.setEngineNo(null);
reqVO.setVin(null);
// reqVO.setInvoiceDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
reqVO.setServiceBuyer(null);
reqVO.setCarBuyer(null);
reqVO.setCertType(null);
reqVO.setMobile(null);
reqVO.setCertNo(null);
reqVO.setContactAddress(null);
reqVO.setMemberEmail(null);
reqVO.setProductId(null);
reqVO.setServiceProduct(null);
reqVO.setProductValidity(null);
reqVO.setOriginalWarrantyYears(null);
reqVO.setOriginalWarrantyMileage(null);
reqVO.setProductFee(null);
reqVO.setSettlementMethod(null);
reqVO.setRemark(null);
reqVO.setInputUser(null);
reqVO.setContractRemark(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<RenewalOrderDO> pageResult = renewalOrderService.getRenewalOrderPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbRenewalOrder, pageResult.getList().get(0));
}
}

View File

@@ -0,0 +1,146 @@
package cn.iocoder.yudao.module.car.service.renewalproduct;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.car.controller.admin.renewalproduct.vo.*;
import cn.iocoder.yudao.module.car.dal.dataobject.renewalproduct.RenewalProductDO;
import cn.iocoder.yudao.module.car.dal.mysql.renewalproduct.RenewalProductMapper;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.module.car.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link RenewalProductServiceImpl} 的单元测试类
*
* @author 芋道源码
*/
@Import(RenewalProductServiceImpl.class)
public class RenewalProductServiceImplTest extends BaseDbUnitTest {
@Resource
private RenewalProductServiceImpl renewalProductService;
@Resource
private RenewalProductMapper renewalProductMapper;
@Test
public void testCreateRenewalProduct_success() {
// 准备参数
RenewalProductSaveReqVO createReqVO = randomPojo(RenewalProductSaveReqVO.class).setId(null);
// 调用
Long renewalProductId = renewalProductService.createRenewalProduct(createReqVO);
// 断言
assertNotNull(renewalProductId);
// 校验记录的属性是否正确
RenewalProductDO renewalProduct = renewalProductMapper.selectById(renewalProductId);
assertPojoEquals(createReqVO, renewalProduct, "id");
}
@Test
public void testUpdateRenewalProduct_success() {
// mock 数据
RenewalProductDO dbRenewalProduct = randomPojo(RenewalProductDO.class);
renewalProductMapper.insert(dbRenewalProduct);// @Sql: 先插入出一条存在的数据
// 准备参数
RenewalProductSaveReqVO updateReqVO = randomPojo(RenewalProductSaveReqVO.class, o -> {
o.setId(dbRenewalProduct.getId()); // 设置更新的 ID
});
// 调用
renewalProductService.updateRenewalProduct(updateReqVO);
// 校验是否更新正确
RenewalProductDO renewalProduct = renewalProductMapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, renewalProduct);
}
@Test
public void testUpdateRenewalProduct_notExists() {
// 准备参数
RenewalProductSaveReqVO updateReqVO = randomPojo(RenewalProductSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> renewalProductService.updateRenewalProduct(updateReqVO), RENEWAL_PRODUCT_NOT_EXISTS);
}
@Test
public void testDeleteRenewalProduct_success() {
// mock 数据
RenewalProductDO dbRenewalProduct = randomPojo(RenewalProductDO.class);
renewalProductMapper.insert(dbRenewalProduct);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbRenewalProduct.getId();
// 调用
renewalProductService.deleteRenewalProduct(id);
// 校验数据不存在了
assertNull(renewalProductMapper.selectById(id));
}
@Test
public void testDeleteRenewalProduct_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> renewalProductService.deleteRenewalProduct(id), RENEWAL_PRODUCT_NOT_EXISTS);
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGetRenewalProductPage() {
// mock 数据
RenewalProductDO dbRenewalProduct = randomPojo(RenewalProductDO.class, o -> { // 等会查询到
o.setProductName(null);
o.setProductContent(null);
o.setProductType(null);
o.setRemark(null);
o.setCreateTime(null);
});
renewalProductMapper.insert(dbRenewalProduct);
// 测试 productName 不匹配
renewalProductMapper.insert(cloneIgnoreId(dbRenewalProduct, o -> o.setProductName(null)));
// 测试 productContent 不匹配
renewalProductMapper.insert(cloneIgnoreId(dbRenewalProduct, o -> o.setProductContent(null)));
// 测试 productType 不匹配
renewalProductMapper.insert(cloneIgnoreId(dbRenewalProduct, o -> o.setProductType(null)));
// 测试 remark 不匹配
renewalProductMapper.insert(cloneIgnoreId(dbRenewalProduct, o -> o.setRemark(null)));
// 测试 createTime 不匹配
renewalProductMapper.insert(cloneIgnoreId(dbRenewalProduct, o -> o.setCreateTime(null)));
// 准备参数
RenewalProductPageReqVO reqVO = new RenewalProductPageReqVO();
reqVO.setProductName(null);
reqVO.setProductContent(null);
reqVO.setProductType(null);
reqVO.setRemark(null);
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
// 调用
PageResult<RenewalProductDO> pageResult = renewalProductService.getRenewalProductPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbRenewalProduct, pageResult.getList().get(0));
}
}