From e4f9152bcacf02be0cb376dcb225eaf444b8951b Mon Sep 17 00:00:00 2001 From: seatonwan9 Date: 星期四, 14 八月 2025 00:21:05 +0800 Subject: [PATCH] 提交源码 --- src/main/java/com/webmanage/controller/ApprovalController.java | 113 src/main/java/com/webmanage/service/impl/ApprovalRecordServiceImpl.java | 170 + src/main/java/com/webmanage/service/ApprovalRecordService.java | 45 src/main/java/com/webmanage/service/PointsRuleDetailService.java | 11 src/main/java/com/webmanage/controller/PointsController.java | 275 + src/main/java/com/webmanage/controller/FileController.java | 156 src/main/java/com/webmanage/entity/Points.java | 73 src/main/java/com/webmanage/mapper/OrderAttachmentMapper.java | 20 src/main/java/com/webmanage/mapper/UserPointsMapper.java | 26 src/main/java/com/webmanage/controller/CartController.java | 214 + src/main/java/com/webmanage/vo/OrderEvaluationVO.java | 63 src/main/resources/application-dev.yml | 128 src/main/resources/mapper/ApprovalRecordMapper.xml | 117 src/main/java/com/webmanage/dto/PointsFlowQueryDTO.java | 48 src/main/java/com/webmanage/service/PointsRuleService.java | 49 src/main/java/com/webmanage/mapper/OrderEvaluationMapper.java | 18 src/main/java/com/webmanage/mapper/PointsMapper.java | 24 src/main/java/com/webmanage/dto/AddPointsFlowDTO.java | 41 src/main/java/com/webmanage/dto/PointsRuleDetailDTO.java | 56 src/main/java/com/webmanage/service/PointsFlowService.java | 56 src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java | 422 ++ src/main/java/com/webmanage/controller/ProductPricingController.java | 164 + src/main/java/com/webmanage/service/OrderInfoService.java | 65 src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java | 401 ++ src/main/java/com/webmanage/mapper/ProductPricingMapper.java | 39 src/main/java/com/webmanage/common/FileUploadException.java | 40 src/main/java/com/webmanage/dto/PointsQueryDTO.java | 50 src/main/java/com/webmanage/entity/PointsFlow.java | 89 pom.xml | 144 src/main/java/com/webmanage/controller/OrderController.java | 182 + src/main/java/com/webmanage/entity/Cart.java | 112 src/main/resources/mapper/PointsFlowMapper.xml | 40 src/main/java/com/webmanage/dto/PointsRuleDTO.java | 54 src/main/java/com/webmanage/mapper/OrderDetailMapper.java | 20 src/main/java/com/webmanage/config/MybatisPlusConfig.java | 50 src/main/resources/mapper/PointsMapper.xml | 54 src/main/java/com/webmanage/common/BusinessException.java | 40 src/main/resources/mapper/CartMapper.xml | 73 src/main/java/com/webmanage/dto/PointsOperateDTO.java | 18 src/main/java/com/webmanage/vo/PointsStatsVO.java | 50 src/main/resources/mapper/OrderEvaluationMapper.xml | 42 src/main/java/com/webmanage/service/impl/PointsRuleServiceImpl.java | 185 + src/main/java/com/webmanage/mapper/PointsRuleMapper.java | 15 src/main/java/com/webmanage/service/MinioService.java | 151 src/main/resources/sql/trade_module.sql | 403 ++ src/main/java/com/webmanage/common/PageResult.java | 64 src/main/java/com/webmanage/common/GlobalExceptionHandler.java | 115 src/main/java/com/webmanage/service/CartService.java | 73 src/main/java/com/webmanage/entity/OrderDetail.java | 105 src/main/java/com/webmanage/dto/PointsDTO.java | 41 src/main/resources/application.yml | 133 src/main/resources/mapper/OrderDetailMapper.xml | 46 src/main/java/com/webmanage/entity/PointsRule.java | 83 src/main/java/com/webmanage/dto/CreateOrderDTO.java | 50 src/main/java/com/webmanage/mapper/PointsFlowMapper.java | 32 src/main/java/com/webmanage/service/impl/PointsRuleDetailServiceImpl.java | 17 src/main/java/com/webmanage/entity/PointsRuleDetail.java | 87 src/main/java/com/webmanage/service/OrderNoService.java | 16 src/main/java/com/webmanage/service/UserPointsService.java | 28 src/main/java/com/webmanage/service/impl/OrderNoServiceImpl.java | 50 src/main/java/com/webmanage/entity/OrderInfo.java | 144 src/main/java/com/webmanage/entity/UserPoints.java | 83 src/main/java/com/webmanage/service/ProductPricingService.java | 48 src/main/java/com/webmanage/service/impl/PointsServiceImpl.java | 38 src/main/java/com/webmanage/WebManageApplication.java | 21 src/main/java/com/webmanage/entity/PointsRuleEntity.java | 66 src/main/java/com/webmanage/service/impl/CartServiceImpl.java | 488 +++ src/main/java/com/webmanage/entity/OrderEvaluation.java | 88 src/main/resources/mapper/UserPointsMapper.xml | 23 src/main/java/com/webmanage/service/impl/UserPointsServiceImpl.java | 127 src/main/resources/mapper/OrderAttachmentMapper.xml | 42 src/main/java/com/webmanage/mapper/ApprovalRecordMapper.java | 51 src/main/java/com/webmanage/mapper/PointsRuleDetailMapper.java | 15 src/main/java/com/webmanage/vo/OrderDetailVO.java | 83 src/main/java/com/webmanage/dto/CreateOrderItemDTO.java | 65 src/main/java/com/webmanage/dto/CartItemDTO.java | 73 src/main/java/com/webmanage/vo/PointsDetailVO.java | 28 src/main/java/com/webmanage/mapper/CartMapper.java | 35 src/main/resources/mapper/OrderInfoMapper.xml | 193 + src/main/java/com/webmanage/dto/PointsMainQueryDTO.java | 51 src/main/resources/mapper/ProductPricingMapper.xml | 81 src/main/java/com/webmanage/util/SnowflakeIdWorker.java | 101 src/main/java/com/webmanage/mapper/OrderInfoMapper.java | 46 src/main/java/com/webmanage/vo/OrderDetailItemVO.java | 66 src/main/java/com/webmanage/dto/ApprovalActionDTO.java | 55 src/main/resources/sql/数据库表说明.md | 142 src/main/java/com/webmanage/config/JacksonConfig.java | 43 src/main/java/com/webmanage/service/PointsService.java | 17 src/main/java/com/webmanage/common/Result.java | 97 src/main/java/com/webmanage/config/MinioConfig.java | 50 src/main/java/com/webmanage/entity/ApprovalRecord.java | 88 src/main/java/com/webmanage/service/impl/ProductPricingServiceImpl.java | 188 + src/main/java/com/webmanage/dto/ApprovalQueryDTO.java | 60 src/main/java/com/webmanage/dto/CartQueryDTO.java | 29 src/main/java/com/webmanage/vo/CartVO.java | 35 src/main/java/com/webmanage/vo/OrderAttachmentVO.java | 63 src/main/java/com/webmanage/config/RedisConfig.java | 47 src/main/java/com/webmanage/entity/ProductPricing.java | 144 src/main/resources/sql/init.sql | 501 +++ src/main/java/com/webmanage/entity/OrderAttachment.java | 88 src/main/java/com/webmanage/vo/CartItemVO.java | 73 src/main/java/com/webmanage/dto/OrderQueryDTO.java | 66 102 files changed, 9,388 insertions(+), 0 deletions(-) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1c94aa9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,144 @@ +<?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>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>2.6.10</version> + <relativePath/> + </parent> + + <groupId>com.webmanage</groupId> + <artifactId>web-manage-back</artifactId> + <version>1.0.0</version> + <name>web-manage-back</name> + <description>绉垎绠$悊绯荤粺鍚庣</description> + + <properties> + <java.version>1.8</java.version> + <mybatis-plus.version>3.5.1</mybatis-plus.version> + <postgresql.version>42.3.3</postgresql.version> + <druid.version>1.2.8</druid.version> + <minio.version>8.4.3</minio.version> + <fastjson.version>2.0.7</fastjson.version> + <hutool.version>5.8.0</hutool.version> + <knife4j.version>3.0.3</knife4j.version> + <okhttp.version>4.10.0</okhttp.version> + </properties> + + <dependencies> + <!-- Spring Boot Starter --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + + <!-- Spring Boot Starter Data Redis --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-redis</artifactId> + </dependency> + + <!-- Spring Boot Starter Validation --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </dependency> + + <!-- MyBatis Plus --> + <dependency> + <groupId>com.baomidou</groupId> + <artifactId>mybatis-plus-boot-starter</artifactId> + <version>${mybatis-plus.version}</version> + </dependency> + + <!-- PostgreSQL Driver --> + <dependency> + <groupId>org.postgresql</groupId> + <artifactId>postgresql</artifactId> + <version>${postgresql.version}</version> + </dependency> + + <!-- Druid --> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>druid-spring-boot-starter</artifactId> + <version>${druid.version}</version> + </dependency> + + <!-- MinIO --> + <dependency> + <groupId>io.minio</groupId> + <artifactId>minio</artifactId> + <version>${minio.version}</version> + </dependency> + <!-- 寮哄埗缁熶竴OkHttp鐗堟湰 --> + <dependency> + <groupId>com.squareup.okhttp3</groupId> + <artifactId>okhttp</artifactId> + <version>${okhttp.version}</version> + </dependency> + <dependency> + <groupId>com.squareup.okhttp3</groupId> + <artifactId>okhttp-urlconnection</artifactId> + <version>${okhttp.version}</version> + </dependency> + + <!-- FastJSON --> + <dependency> + <groupId>com.alibaba.fastjson2</groupId> + <artifactId>fastjson2</artifactId> + <version>${fastjson.version}</version> + </dependency> + + <!-- Hutool --> + <dependency> + <groupId>cn.hutool</groupId> + <artifactId>hutool-all</artifactId> + <version>${hutool.version}</version> + </dependency> + + <!-- Knife4j API鏂囨。 --> + <dependency> + <groupId>com.github.xiaoymin</groupId> + <artifactId>knife4j-spring-boot-starter</artifactId> + <version>${knife4j.version}</version> + </dependency> + + <!-- Lombok --> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <optional>true</optional> + </dependency> + + <!-- Spring Boot Test --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <!--鍒嗛〉鎻掍欢--> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <configuration> + <excludes> + <exclude> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/src/main/java/com/webmanage/WebManageApplication.java b/src/main/java/com/webmanage/WebManageApplication.java new file mode 100644 index 0000000..4af56a8 --- /dev/null +++ b/src/main/java/com/webmanage/WebManageApplication.java @@ -0,0 +1,21 @@ +package com.webmanage; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 绉垎绠$悊绯荤粺鍚姩绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@SpringBootApplication +@MapperScan("com.webmanage.mapper") +public class WebManageApplication { + + public static void main(String[] args) { + SpringApplication.run(WebManageApplication.class, args); + System.out.println("绉垎绠$悊绯荤粺鍚姩鎴愬姛锛�"); + } +} diff --git a/src/main/java/com/webmanage/common/BusinessException.java b/src/main/java/com/webmanage/common/BusinessException.java new file mode 100644 index 0000000..8824d41 --- /dev/null +++ b/src/main/java/com/webmanage/common/BusinessException.java @@ -0,0 +1,40 @@ +package com.webmanage.common; + +/** + * 涓氬姟寮傚父绫� + * + * @author webmanage + * @date 2024-08-07 + */ +public class BusinessException extends RuntimeException { + + private Integer code; + + public BusinessException(String message) { + super(message); + this.code = 500; + } + + public BusinessException(Integer code, String message) { + super(message); + this.code = code; + } + + public BusinessException(String message, Throwable cause) { + super(message, cause); + this.code = 500; + } + + public BusinessException(Integer code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } +} diff --git a/src/main/java/com/webmanage/common/FileUploadException.java b/src/main/java/com/webmanage/common/FileUploadException.java new file mode 100644 index 0000000..b9bf2b4 --- /dev/null +++ b/src/main/java/com/webmanage/common/FileUploadException.java @@ -0,0 +1,40 @@ +package com.webmanage.common; + +/** + * 鏂囦欢涓婁紶寮傚父绫� + * + * @author webmanage + * @date 2024-08-07 + */ +public class FileUploadException extends RuntimeException { + + private Integer code; + + public FileUploadException(String message) { + super(message); + this.code = 400; + } + + public FileUploadException(Integer code, String message) { + super(message); + this.code = code; + } + + public FileUploadException(String message, Throwable cause) { + super(message, cause); + this.code = 400; + } + + public FileUploadException(Integer code, String message, Throwable cause) { + super(message, cause); + this.code = code; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } +} diff --git a/src/main/java/com/webmanage/common/GlobalExceptionHandler.java b/src/main/java/com/webmanage/common/GlobalExceptionHandler.java new file mode 100644 index 0000000..b448615 --- /dev/null +++ b/src/main/java/com/webmanage/common/GlobalExceptionHandler.java @@ -0,0 +1,115 @@ +package com.webmanage.common; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.util.stream.Collectors; + +/** + * 鍏ㄥ眬寮傚父澶勭悊鍣� + * + * @author webmanage + * @date 2024-08-07 + */ +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + /** + * 澶勭悊鍙傛暟鏍¢獙寮傚父 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + String message = e.getBindingResult().getFieldErrors().stream() + .map(FieldError::getDefaultMessage) + .collect(Collectors.joining(", ")); + log.warn("鍙傛暟鏍¢獙澶辫触: {}", message); + return Result.error(400, "鍙傛暟鏍¢獙澶辫触: " + message); + } + + /** + * 澶勭悊缁戝畾寮傚父 + */ + @ExceptionHandler(BindException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleBindException(BindException e) { + String message = e.getBindingResult().getFieldErrors().stream() + .map(FieldError::getDefaultMessage) + .collect(Collectors.joining(", ")); + log.warn("鍙傛暟缁戝畾澶辫触: {}", message); + return Result.error(400, "鍙傛暟缁戝畾澶辫触: " + message); + } + + /** + * 澶勭悊绾︽潫杩濆弽寮傚父 + */ + @ExceptionHandler(ConstraintViolationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleConstraintViolationException(ConstraintViolationException e) { + String message = e.getConstraintViolations().stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.joining(", ")); + log.warn("绾︽潫鏍¢獙澶辫触: {}", message); + return Result.error(400, "绾︽潫鏍¢獙澶辫触: " + message); + } + + /** + * 澶勭悊鍙傛暟绫诲瀷涓嶅尮閰嶅紓甯� + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { + log.warn("鍙傛暟绫诲瀷涓嶅尮閰�: {}", e.getMessage()); + return Result.error(400, "鍙傛暟绫诲瀷涓嶅尮閰�: " + e.getName()); + } + + /** + * 澶勭悊涓氬姟寮傚父 + */ + @ExceptionHandler(BusinessException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleBusinessException(BusinessException e) { + log.warn("涓氬姟寮傚父: {}", e.getMessage()); + return Result.error(e.getCode(), e.getMessage()); + } + + /** + * 澶勭悊鏂囦欢涓婁紶寮傚父 + */ + @ExceptionHandler(FileUploadException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Result<String> handleFileUploadException(FileUploadException e) { + log.warn("鏂囦欢涓婁紶寮傚父: {}", e.getMessage()); + return Result.error(e.getCode(), e.getMessage()); + } + + /** + * 澶勭悊閫氱敤杩愯鏃跺紓甯� + */ + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public Result<String> handleRuntimeException(RuntimeException e) { + log.error("杩愯鏃跺紓甯�: ", e); + return Result.error(500, "绯荤粺鍐呴儴閿欒: " + e.getMessage()); + } + + /** + * 澶勭悊閫氱敤寮傚父 + */ + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public Result<String> handleException(Exception e) { + log.error("绯荤粺寮傚父: ", e); + return Result.error(500, "绯荤粺寮傚父锛岃鑱旂郴绠$悊鍛�"); + } +} diff --git a/src/main/java/com/webmanage/common/PageResult.java b/src/main/java/com/webmanage/common/PageResult.java new file mode 100644 index 0000000..0f0a7ec --- /dev/null +++ b/src/main/java/com/webmanage/common/PageResult.java @@ -0,0 +1,64 @@ +package com.webmanage.common; + +import lombok.Data; +import java.util.List; + +/** + * 鍒嗛〉缁撴灉 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +public class PageResult<T> { + + /** + * 鏁版嵁鍒楄〃 + */ + private List<T> list; + + /** + * 鎬昏褰曟暟 + */ + private Long total; + + /** + * 褰撳墠椤电爜 + */ + private Long pageNum; + + /** + * 姣忛〉澶у皬 + */ + private Long pageSize; + + /** + * 鎬婚〉鏁� + */ + private Long pages; + + public PageResult() {} + + public PageResult(List<T> list, Long total, Long pageNum, Long pageSize) { + this.list = list; + this.total = total; + this.pageNum = pageNum; + this.pageSize = pageSize; + this.pages = (total + pageSize - 1) / pageSize; + } + + public PageResult(List<T> list, Long total, Long pageNum, Long pageSize, Long pages) { + this.list = list; + this.total = total; + this.pageNum = pageNum; + this.pageSize = pageSize; + this.pages = pages; + } + + /** + * 鍒涘缓鍒嗛〉缁撴灉 + */ + public static <T> PageResult<T> of(List<T> list, Long total, Long pageNum, Long pageSize) { + return new PageResult<>(list, total, pageNum, pageSize); + } +} diff --git a/src/main/java/com/webmanage/common/Result.java b/src/main/java/com/webmanage/common/Result.java new file mode 100644 index 0000000..04b6e66 --- /dev/null +++ b/src/main/java/com/webmanage/common/Result.java @@ -0,0 +1,97 @@ +package com.webmanage.common; + +import lombok.Data; + +/** + * 缁熶竴杩斿洖缁撴灉 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +public class Result<T> { + + /** + * 鐘舵�佺爜 + */ + private Integer code; + + /** + * 杩斿洖娑堟伅 + */ + private String msg; + + /** + * 杩斿洖鏁版嵁 + */ + private T data; + + /** + * 鏃堕棿鎴� + */ + private Long timestamp; + + public Result() { + this.timestamp = System.currentTimeMillis(); + } + + public Result(Integer code, String msg) { + this(); + this.code = code; + this.msg = msg; + } + + public Result(Integer code, String msg, T data) { + this(code, msg); + this.data = data; + } + + /** + * 鎴愬姛杩斿洖 + */ + public static <T> Result<T> success() { + return new Result<>(200, "鎿嶄綔鎴愬姛"); + } + + /** + * 鎴愬姛杩斿洖 + */ + public static <T> Result<T> success(String msg) { + return new Result<>(200, msg); + } + + /** + * 鎴愬姛杩斿洖 + */ + public static <T> Result<T> success(T data) { + return new Result<>(200, "鎿嶄綔鎴愬姛", data); + } + + /** + * 鎴愬姛杩斿洖 + */ + public static <T> Result<T> success(String msg, T data) { + return new Result<>(200, msg, data); + } + + /** + * 澶辫触杩斿洖 + */ + public static <T> Result<T> error() { + return new Result<>(500, "鎿嶄綔澶辫触"); + } + + /** + * 澶辫触杩斿洖 + */ + public static <T> Result<T> error(String msg) { + return new Result<>(500, msg); + } + + /** + * 澶辫触杩斿洖 + */ + public static <T> Result<T> error(Integer code, String msg) { + return new Result<>(code, msg); + } +} diff --git a/src/main/java/com/webmanage/config/JacksonConfig.java b/src/main/java/com/webmanage/config/JacksonConfig.java new file mode 100644 index 0000000..3152853 --- /dev/null +++ b/src/main/java/com/webmanage/config/JacksonConfig.java @@ -0,0 +1,43 @@ +package com.webmanage.config; + +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.format.DateTimeFormatter; + +/** + * @ClassName JacksonConfig + * @Description TODO + * @Author wangxudong + * @Date 2025/8/13 22:52 + * @Version 1.0 + **/ +@Configuration +public class JacksonConfig { + @Bean + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return builder -> { + // Java 8鏃ユ湡鏃堕棿鏍煎紡 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + builder.serializers( + new LocalDateTimeSerializer(formatter), + new LocalDateSerializer(DateTimeFormatter.ISO_DATE), + new LocalTimeSerializer(DateTimeFormatter.ISO_TIME) + ); + + builder.deserializers( + new LocalDateTimeDeserializer(formatter), + new LocalDateDeserializer(DateTimeFormatter.ISO_DATE), + new LocalTimeDeserializer(DateTimeFormatter.ISO_TIME) + ); + }; + } +} diff --git a/src/main/java/com/webmanage/config/MinioConfig.java b/src/main/java/com/webmanage/config/MinioConfig.java new file mode 100644 index 0000000..29f0bdf --- /dev/null +++ b/src/main/java/com/webmanage/config/MinioConfig.java @@ -0,0 +1,50 @@ +package com.webmanage.config; + +import io.minio.MinioClient; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MinIO閰嶇疆绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@Configuration +@ConfigurationProperties(prefix = "minio") +public class MinioConfig { + + /** + * MinIO鏈嶅姟鍦板潃 + */ + private String endpoint; + + /** + * 璁块棶瀵嗛挜 + */ + private String accessKey; + + /** + * 绉樺瘑瀵嗛挜 + */ + private String secretKey; + + /** + * 榛樿瀛樺偍妗跺悕绉� + */ + private String bucketName; + + /** + * 鍒涘缓MinIO瀹㈡埛绔� + */ + @Bean + public MinioClient minioClient() { + return MinioClient.builder() + .endpoint(endpoint) + .credentials(accessKey, secretKey) + .build(); + } +} diff --git a/src/main/java/com/webmanage/config/MybatisPlusConfig.java b/src/main/java/com/webmanage/config/MybatisPlusConfig.java new file mode 100644 index 0000000..1b867ba --- /dev/null +++ b/src/main/java/com/webmanage/config/MybatisPlusConfig.java @@ -0,0 +1,50 @@ +package com.webmanage.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * MyBatis Plus閰嶇疆绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 鍒嗛〉鎻掍欢 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL)); + return interceptor; + } + + /** + * 鑷姩濉厖澶勭悊鍣� + */ + @Component + public static class MyMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now()); + this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); + } + } +} diff --git a/src/main/java/com/webmanage/config/RedisConfig.java b/src/main/java/com/webmanage/config/RedisConfig.java new file mode 100644 index 0000000..65383b7 --- /dev/null +++ b/src/main/java/com/webmanage/config/RedisConfig.java @@ -0,0 +1,47 @@ +package com.webmanage.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Redis閰嶇疆绫� + */ +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate<String, Object> template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + // 浣跨敤Jackson2JsonRedisSerializer鏉ュ簭鍒楀寲鍜屽弽搴忓垪鍖杛edis鐨剉alue鍊� + Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + + // 浣跨敤StringRedisSerializer鏉ュ簭鍒楀寲鍜屽弽搴忓垪鍖杛edis鐨刱ey鍊� + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + + // key閲囩敤String鐨勫簭鍒楀寲鏂瑰紡 + template.setKeySerializer(stringRedisSerializer); + // hash鐨刱ey涔熼噰鐢⊿tring鐨勫簭鍒楀寲鏂瑰紡 + template.setHashKeySerializer(stringRedisSerializer); + // value搴忓垪鍖栨柟寮忛噰鐢╦ackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash鐨剉alue搴忓垪鍖栨柟寮忛噰鐢╦ackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + + return template; + } +} diff --git a/src/main/java/com/webmanage/controller/ApprovalController.java b/src/main/java/com/webmanage/controller/ApprovalController.java new file mode 100644 index 0000000..69474b2 --- /dev/null +++ b/src/main/java/com/webmanage/controller/ApprovalController.java @@ -0,0 +1,113 @@ +package com.webmanage.controller; + +import com.webmanage.common.Result; +import com.webmanage.dto.ApprovalActionDTO; +import com.webmanage.dto.ApprovalQueryDTO; +import com.webmanage.entity.ApprovalRecord; +import com.webmanage.service.ApprovalRecordService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 瀹℃壒绠$悊Controller + */ +@Slf4j +@RestController +@RequestMapping("/api/approval") +@Api(tags = "瀹℃壒绠$悊") +@Validated +public class ApprovalController { + + @Resource + private ApprovalRecordService approvalRecordService; + + @PostMapping("/page") + @ApiOperation("鍒嗛〉鏌ヨ瀹℃壒璁板綍") + public Result<Object> getApprovalRecordPage(@Valid @RequestBody ApprovalQueryDTO queryDTO) { + try { + return Result.success(approvalRecordService.getApprovalRecordPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ瀹℃壒璁板綍澶辫触", e); + return Result.error("鏌ヨ瀹℃壒璁板綍澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/pending/page") + @ApiOperation("鍒嗛〉鏌ヨ寰呭鎵硅鍗�") + public Result<Object> getPendingApprovalPage(@Valid @RequestBody ApprovalQueryDTO queryDTO) { + try { + return Result.success(approvalRecordService.getPendingApprovalPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ寰呭鎵硅鍗曞け璐�", e); + return Result.error("鏌ヨ寰呭鎵硅鍗曞け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/order/{orderId}") + @ApiOperation("鏍规嵁璁㈠崟ID鏌ヨ瀹℃壒璁板綍") + public Result<Object> getApprovalRecordsByOrderId(@ApiParam("璁㈠崟ID") @PathVariable String orderId) { + try { + List<ApprovalRecord> records = approvalRecordService.getApprovalRecordsByOrderId(orderId); + return Result.success(records); + } catch (Exception e) { + log.error("鏌ヨ璁㈠崟瀹℃壒璁板綍澶辫触", e); + return Result.error("鏌ヨ璁㈠崟瀹℃壒璁板綍澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/approve") + @ApiOperation("瀹℃壒璁㈠崟") + public Result<Object> approveOrder(@Valid @RequestBody ApprovalActionDTO actionDTO) { + try { + boolean result = approvalRecordService.approveOrder(actionDTO); + if (result) { + return Result.success("瀹℃壒鎴愬姛"); + } else { + return Result.error("瀹℃壒澶辫触"); + } + } catch (Exception e) { + log.error("瀹℃壒璁㈠崟澶辫触", e); + return Result.error("瀹℃壒璁㈠崟澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/authorize/{approvalId}") + @ApiOperation("鎺堟潈瀹℃壒") + public Result<Object> authorizeApproval(@ApiParam("瀹℃壒璁板綍ID") @PathVariable Long approvalId, + @ApiParam("鎺堟潈浜篒D") @RequestParam @NotNull Long authorizerId, + @ApiParam("鎺堟潈浜哄鍚�") @RequestParam @NotNull String authorizerName, + @ApiParam("鎺堟潈鎰忚") @RequestParam String authorizationOpinion) { + try { + boolean result = approvalRecordService.authorizeApproval(approvalId, authorizerId, authorizerName, authorizationOpinion); + if (result) { + return Result.success("鎺堟潈鎴愬姛"); + } else { + return Result.error("鎺堟潈澶辫触"); + } + } catch (Exception e) { + log.error("鎺堟潈瀹℃壒澶辫触", e); + return Result.error("鎺堟潈瀹℃壒澶辫触锛�" + e.getMessage()); + } + } + + @GetMapping("/status/{orderId}") + @ApiOperation("鑾峰彇璁㈠崟褰撳墠瀹℃壒鐘舵��") + public Result<Object> getOrderCurrentApprovalStatus(@ApiParam("璁㈠崟ID") @PathVariable String orderId) { + try { + String status = approvalRecordService.getOrderCurrentApprovalStatus(orderId); + return Result.success(status); + } catch (Exception e) { + log.error("鑾峰彇璁㈠崟瀹℃壒鐘舵�佸け璐�", e); + return Result.error("鑾峰彇璁㈠崟瀹℃壒鐘舵�佸け璐ワ細" + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/controller/CartController.java b/src/main/java/com/webmanage/controller/CartController.java new file mode 100644 index 0000000..1452cfc --- /dev/null +++ b/src/main/java/com/webmanage/controller/CartController.java @@ -0,0 +1,214 @@ +package com.webmanage.controller; + +import com.webmanage.common.Result; +import com.webmanage.dto.CartItemDTO; +import com.webmanage.dto.CartQueryDTO; +import com.webmanage.service.CartService; +import com.webmanage.vo.CartVO; +import com.webmanage.vo.CartItemVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 璐墿杞︾鐞咰ontroller + */ +@Slf4j +@RestController +@RequestMapping("/api/cart") +@Api(tags = "璐墿杞︾鐞�") +@Validated +public class CartController { + + @Resource + private CartService cartService; + + @PostMapping("/add") + @ApiOperation("娣诲姞鍟嗗搧鍒拌喘鐗╄溅") + public Result<Object> addToCart(@Valid @RequestBody CartItemDTO cartItemDTO, + @RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + boolean result = cartService.addToCart(userId, unitId, cartItemDTO); + if (result) { + return Result.success("娣诲姞鍟嗗搧鍒拌喘鐗╄溅鎴愬姛"); + } else { + return Result.error("娣诲姞鍟嗗搧鍒拌喘鐗╄溅澶辫触"); + } + } catch (Exception e) { + log.error("娣诲姞鍟嗗搧鍒拌喘鐗╄溅澶辫触", e); + return Result.error("娣诲姞鍟嗗搧鍒拌喘鐗╄溅澶辫触锛�" + e.getMessage()); + } + } + + @DeleteMapping("/remove") + @ApiOperation("浠庤喘鐗╄溅绉婚櫎鍟嗗搧") + public Result<Object> removeFromCart(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId, + @RequestParam @NotNull Long pricingId) { + try { + boolean result = cartService.removeFromCart(userId, unitId, pricingId); + if (result) { + return Result.success("浠庤喘鐗╄溅绉婚櫎鍟嗗搧鎴愬姛"); + } else { + return Result.error("浠庤喘鐗╄溅绉婚櫎鍟嗗搧澶辫触"); + } + } catch (Exception e) { + log.error("浠庤喘鐗╄溅绉婚櫎鍟嗗搧澶辫触", e); + return Result.error("浠庤喘鐗╄溅绉婚櫎鍟嗗搧澶辫触锛�" + e.getMessage()); + } + } + + @PutMapping("/update") + @ApiOperation("鏇存柊璐墿杞﹀晢鍝佹暟閲�") + public Result<Object> updateCartItemQuantity(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId, + @RequestParam @NotNull Long pricingId, + @RequestParam @NotNull @Min(1) Integer quantity) { + try { + boolean result = cartService.updateCartItemQuantity(userId, unitId, pricingId, quantity); + if (result) { + return Result.success("鏇存柊璐墿杞﹀晢鍝佹暟閲忔垚鍔�"); + } else { + return Result.error("鏇存柊璐墿杞﹀晢鍝佹暟閲忓け璐�"); + } + } catch (Exception e) { + log.error("鏇存柊璐墿杞﹀晢鍝佹暟閲忓け璐�", e); + return Result.error("鏇存柊璐墿杞﹀晢鍝佹暟閲忓け璐ワ細" + e.getMessage()); + } + } + + @DeleteMapping("/clear") + @ApiOperation("娓呯┖璐墿杞�") + public Result<Object> clearCart(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + boolean result = cartService.clearCart(userId, unitId); + if (result) { + return Result.success("娓呯┖璐墿杞︽垚鍔�"); + } else { + return Result.error("娓呯┖璐墿杞﹀け璐�"); + } + } catch (Exception e) { + log.error("娓呯┖璐墿杞﹀け璐�", e); + return Result.error("娓呯┖璐墿杞﹀け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/info") + @ApiOperation("鑾峰彇璐墿杞︿俊鎭�") + public Result<Object> getCart(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + CartVO cart = cartService.getCart(userId, unitId); + return Result.success(cart); + } catch (Exception e) { + log.error("鑾峰彇璐墿杞︿俊鎭け璐�", e); + return Result.error("鑾峰彇璐墿杞︿俊鎭け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/items") + @ApiOperation("鑾峰彇璐墿杞﹀晢鍝佸垪琛�") + public Result<Object> getCartItems(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + List<CartItemVO> items = cartService.getCartItems(userId, unitId); + return Result.success(items); + } catch (Exception e) { + log.error("鑾峰彇璐墿杞﹀晢鍝佸垪琛ㄥけ璐�", e); + return Result.error("鑾峰彇璐墿杞﹀晢鍝佸垪琛ㄥけ璐ワ細" + e.getMessage()); + } + } + + @DeleteMapping("/batch-remove") + @ApiOperation("鎵归噺鍒犻櫎璐墿杞﹀晢鍝�") + public Result<Object> batchRemoveFromCart(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId, + @RequestBody List<Long> pricingIds) { + try { + boolean result = cartService.batchRemoveFromCart(userId, unitId, pricingIds); + if (result) { + return Result.success("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佹垚鍔�"); + } else { + return Result.error("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佸け璐�"); + } + } catch (Exception e) { + log.error("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佸け璐�", e); + return Result.error("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佸け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/count") + @ApiOperation("鑾峰彇璐墿杞﹀晢鍝佹暟閲�") + public Result<Object> getCartItemCount(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + Integer count = cartService.getCartItemCount(userId, unitId); + return Result.success(count); + } catch (Exception e) { + log.error("鑾峰彇璐墿杞﹀晢鍝佹暟閲忓け璐�", e); + return Result.error("鑾峰彇璐墿杞﹀晢鍝佹暟閲忓け璐ワ細" + e.getMessage()); + } + } + + @PostMapping("/sync-to-db") + @ApiOperation("鍚屾Redis璐墿杞︽暟鎹埌鏁版嵁搴�") + public Result<Object> syncCartToDatabase(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + boolean result = cartService.syncCartToDatabase(userId, unitId); + if (result) { + return Result.success("鍚屾璐墿杞︽暟鎹埌鏁版嵁搴撴垚鍔�"); + } else { + return Result.error("鍚屾璐墿杞︽暟鎹埌鏁版嵁搴撳け璐�"); + } + } catch (Exception e) { + log.error("鍚屾璐墿杞︽暟鎹埌鏁版嵁搴撳け璐�", e); + return Result.error("鍚屾璐墿杞︽暟鎹埌鏁版嵁搴撳け璐ワ細" + e.getMessage()); + } + } + + @PostMapping("/load-from-db") + @ApiOperation("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹埌Redis") + public Result<Object> loadCartFromDatabase(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + boolean result = cartService.loadCartFromDatabase(userId, unitId); + if (result) { + return Result.success("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹垚鍔�"); + } else { + return Result.error("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹け璐�"); + } + } catch (Exception e) { + log.error("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹け璐�", e); + return Result.error("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/consistency") + @ApiOperation("妫�鏌ヨ喘鐗╄溅鏁版嵁涓�鑷存��") + public Result<Object> checkCartConsistency(@RequestParam @NotNull Long userId, + @RequestParam @NotNull Long unitId) { + try { + boolean isConsistent = cartService.checkCartConsistency(userId, unitId); + if (isConsistent) { + return Result.success("璐墿杞︽暟鎹竴鑷�"); + } else { + return Result.error("璐墿杞︽暟鎹笉涓�鑷�"); + } + } catch (Exception e) { + log.error("妫�鏌ヨ喘鐗╄溅鏁版嵁涓�鑷存�уけ璐�", e); + return Result.error("妫�鏌ヨ喘鐗╄溅鏁版嵁涓�鑷存�уけ璐ワ細" + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/controller/FileController.java b/src/main/java/com/webmanage/controller/FileController.java new file mode 100644 index 0000000..c3d3292 --- /dev/null +++ b/src/main/java/com/webmanage/controller/FileController.java @@ -0,0 +1,156 @@ +package com.webmanage.controller; + +import com.webmanage.common.Result; +import com.webmanage.service.MinioService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * 鏂囦欢涓婁紶涓嬭浇鎺у埗鍣� + * + * @author webmanage + * @date 2024-08-07 + */ +@Slf4j +@RestController +@RequestMapping("/file") +@Api(tags = "鏂囦欢绠$悊") +public class FileController { + + @Autowired + private MinioService minioService; + + /** + * 涓婁紶鏂囦欢 + */ + @PostMapping("/upload") + @ApiOperation("涓婁紶鏂囦欢") + public Result<String> uploadFile( + @ApiParam("鏂囦欢") @RequestParam("file") MultipartFile file, + @ApiParam("鏂囦欢澶�") @RequestParam(defaultValue = "common") String folder) { + try { + if (file.isEmpty()) { + return Result.error("鏂囦欢涓嶈兘涓虹┖"); + } + + // 妫�鏌ユ枃浠跺ぇ灏忥紙闄愬埗涓�100MB锛� + if (file.getSize() > 100 * 1024 * 1024) { + return Result.error("鏂囦欢澶у皬涓嶈兘瓒呰繃100MB"); + } + + String fileName = minioService.uploadFile(file, folder); + return Result.success("鏂囦欢涓婁紶鎴愬姛", fileName); + } catch (Exception e) { + log.error("鏂囦欢涓婁紶澶辫触: ", e); + return Result.error("鏂囦欢涓婁紶澶辫触: " + e.getMessage()); + } + } + + /** + * 涓嬭浇鏂囦欢 + */ + @GetMapping("/download/{fileName}") + @ApiOperation("涓嬭浇鏂囦欢") + public ResponseEntity<InputStreamResource> downloadFile( + @ApiParam("鏂囦欢鍚�") @PathVariable String fileName, + @ApiParam("鍘熷鏂囦欢鍚�") @RequestParam(required = false) String originalName) { + try { + InputStream inputStream = minioService.downloadFile(fileName); + + // 濡傛灉娌℃湁鎻愪緵鍘熷鏂囦欢鍚嶏紝浠庤矾寰勪腑鎻愬彇 + if (originalName == null || originalName.isEmpty()) { + String[] parts = fileName.split("/"); + originalName = parts[parts.length - 1]; + } + + // 璁剧疆鍝嶅簲澶� + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", + URLEncoder.encode(originalName, StandardCharsets.UTF_8.toString())); + + InputStreamResource resource = new InputStreamResource(inputStream); + + return ResponseEntity.ok() + .headers(headers) + .body(resource); + } catch (Exception e) { + log.error("鏂囦欢涓嬭浇澶辫触: ", e); + return ResponseEntity.notFound().build(); + } + } + + /** + * 鑾峰彇鏂囦欢棰勮URL + */ + @GetMapping("/preview/{fileName}") + @ApiOperation("鑾峰彇鏂囦欢棰勮URL") + public Result<String> getPreviewUrl(@ApiParam("鏂囦欢鍚�") @PathVariable String fileName) { + try { + String previewUrl = minioService.getPreviewUrl(fileName); + return Result.success("鑾峰彇棰勮URL鎴愬姛", previewUrl); + } catch (Exception e) { + log.error("鑾峰彇棰勮URL澶辫触: ", e); + return Result.error("鑾峰彇棰勮URL澶辫触: " + e.getMessage()); + } + } + + /** + * 鑾峰彇鏂囦欢涓嬭浇URL + */ + @GetMapping("/download-url/{fileName}") + @ApiOperation("鑾峰彇鏂囦欢涓嬭浇URL") + public Result<String> getDownloadUrl(@ApiParam("鏂囦欢鍚�") @PathVariable String fileName) { + try { + String downloadUrl = minioService.getDownloadUrl(fileName); + return Result.success("鑾峰彇涓嬭浇URL鎴愬姛", downloadUrl); + } catch (Exception e) { + log.error("鑾峰彇涓嬭浇URL澶辫触: ", e); + return Result.error("鑾峰彇涓嬭浇URL澶辫触: " + e.getMessage()); + } + } + + /** + * 鍒犻櫎鏂囦欢 + */ + @DeleteMapping("/delete/{fileName}") + @ApiOperation("鍒犻櫎鏂囦欢") + public Result<Boolean> deleteFile(@ApiParam("鏂囦欢鍚�") @PathVariable String fileName) { + try { + minioService.deleteFile(fileName); + return Result.success("鏂囦欢鍒犻櫎鎴愬姛", true); + } catch (Exception e) { + log.error("鏂囦欢鍒犻櫎澶辫触: ", e); + return Result.error("鏂囦欢鍒犻櫎澶辫触: " + e.getMessage()); + } + } + + /** + * 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦� + */ + @GetMapping("/exists/{fileName}") + @ApiOperation("妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�") + public Result<Boolean> fileExists(@ApiParam("鏂囦欢鍚�") @PathVariable String fileName) { + try { + boolean exists = minioService.fileExists(fileName); + return Result.success("妫�鏌ュ畬鎴�", exists); + } catch (Exception e) { + log.error("妫�鏌ユ枃浠舵槸鍚﹀瓨鍦ㄥけ璐�: ", e); + return Result.error("妫�鏌ユ枃浠舵槸鍚﹀瓨鍦ㄥけ璐�: " + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/controller/OrderController.java b/src/main/java/com/webmanage/controller/OrderController.java new file mode 100644 index 0000000..6680838 --- /dev/null +++ b/src/main/java/com/webmanage/controller/OrderController.java @@ -0,0 +1,182 @@ +package com.webmanage.controller; + +import com.webmanage.common.Result; +import com.webmanage.dto.CreateOrderDTO; +import com.webmanage.dto.OrderQueryDTO; +import com.webmanage.service.OrderInfoService; +import com.webmanage.service.OrderNoService; +import com.webmanage.vo.OrderDetailVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 璁㈠崟绠$悊Controller + */ +@Slf4j +@RestController +@RequestMapping("/api/order") +@Api(tags = "璁㈠崟绠$悊") +@Validated +public class OrderController { + @Resource private OrderInfoService orderInfoService; + @Resource private OrderNoService orderNoService; + + @PostMapping("/buyer/page") + @ApiOperation("鍒嗛〉鏌ヨ涔板璁㈠崟鍒楄〃") + public Result<Object> getBuyerOrderPage(@Valid @RequestBody OrderQueryDTO queryDTO) { + try { return Result.success(orderInfoService.getBuyerOrderPage(queryDTO)); } + catch (Exception e) { log.error("鏌ヨ涔板璁㈠崟鍒楄〃澶辫触", e); return Result.error("鏌ヨ涔板璁㈠崟鍒楄〃澶辫触锛�" + e.getMessage()); } + } + + @PostMapping("/create") + @ApiOperation("鍒涘缓璁㈠崟锛堝寘鍚鍗曡鎯咃級") + public Result<Object> createOrder(@Valid @RequestBody CreateOrderDTO createOrderDTO) { + try { + String orderId = orderInfoService.createOrder(createOrderDTO); + return Result.success(orderId); + } catch (Exception e) { + log.error("鍒涘缓璁㈠崟澶辫触", e); + return Result.error("鍒涘缓璁㈠崟澶辫触锛�" + e.getMessage()); + } + } + + @GetMapping("/no/new") + @ApiOperation("鐢熸垚鍞竴璁㈠崟鍙�") + public Result<Object> generateOrderNo() { + try { + String orderNo = orderNoService.generateOrderNo(); + return Result.success(orderNo); + } catch (Exception e) { + log.error("鐢熸垚璁㈠崟鍙峰け璐�", e); + return Result.error("鐢熸垚璁㈠崟鍙峰け璐ワ細" + e.getMessage()); + } + } + + @PostMapping("/seller/page") + @ApiOperation("鍒嗛〉鏌ヨ鍗栧璁㈠崟鍒楄〃") + public Result<Object> getSellerOrderPage(@Valid @RequestBody OrderQueryDTO queryDTO) { + try { + if (queryDTO.getProviderId() == null) { + return Result.error("鎻愪緵鑰匢D涓嶈兘涓虹┖"); + } + return Result.success(orderInfoService.getSellerOrderPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ鍗栧璁㈠崟鍒楄〃澶辫触", e); + return Result.error("鏌ヨ鍗栧璁㈠崟鍒楄〃澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/approval/page") + @ApiOperation("鍒嗛〉鏌ヨ寰呭鎵硅鍗曞垪琛�") + public Result<Object> getPendingApprovalOrderPage(@Valid @RequestBody OrderQueryDTO queryDTO) { + try { + return Result.success(orderInfoService.getPendingApprovalOrderPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ寰呭鎵硅鍗曞垪琛ㄥけ璐�", e); + return Result.error("鏌ヨ寰呭鎵硅鍗曞垪琛ㄥけ璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/detail/{orderId}") + @ApiOperation("鑾峰彇璁㈠崟璇︽儏") + public Result<OrderDetailVO> getOrderDetail( + @ApiParam("璁㈠崟ID") @PathVariable @NotBlank String orderId) { + try { + OrderDetailVO orderDetail = orderInfoService.getOrderDetail(orderId); + return Result.success(orderDetail); + } catch (Exception e) { + log.error("鑾峰彇璁㈠崟璇︽儏澶辫触锛岃鍗旾D: {}", orderId, e); + return Result.error("鑾峰彇璁㈠崟璇︽儏澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/attachment/upload") + @ApiOperation("涓婁紶璁㈠崟闄勪欢") + public Result<Boolean> uploadOrderAttachment( + @ApiParam("璁㈠崟ID") @RequestParam @NotBlank String orderId, + @ApiParam("鏂囦欢鍚�") @RequestParam @NotBlank String fileName, + @ApiParam("鍘熷鏂囦欢鍚�") @RequestParam String originalName, + @ApiParam("闄勪欢绫诲瀷") @RequestParam @NotBlank String fileType, + @ApiParam("闄勪欢澶у皬") @RequestParam @NotNull Long fileSize, + @ApiParam("闄勪欢鍦板潃") @RequestParam @NotBlank String fileUrl, + @ApiParam("瀛樺偍妗跺悕绉�") @RequestParam String bucketName, + @ApiParam("瀵硅薄鍚嶇О") @RequestParam String objectName, + @ApiParam("涓婁紶鐢ㄦ埛ID") @RequestParam @NotNull Long uploadUserId, + @ApiParam("涓婁紶鐢ㄦ埛鍚�") @RequestParam @NotBlank String uploadUserName, + @ApiParam("闄勪欢绫诲瀷") @RequestParam String attachmentType, + @ApiParam("闄勪欢鎻忚堪") @RequestParam String description) { + try { + boolean result = orderInfoService.uploadOrderAttachment( + orderId, fileName, originalName, fileType, fileSize, fileUrl, + bucketName, objectName, uploadUserId, uploadUserName, attachmentType, description + ); + return result ? Result.success(true) : Result.error("涓婁紶璁㈠崟闄勪欢澶辫触"); + } catch (Exception e) { + log.error("涓婁紶璁㈠崟闄勪欢澶辫触锛岃鍗旾D: {}", orderId, e); + return Result.error("涓婁紶璁㈠崟闄勪欢澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/evaluation/add") + @ApiOperation("娣诲姞璁㈠崟璇勪环") + public Result<Boolean> addOrderEvaluation( + @ApiParam("璁㈠崟ID") @RequestParam @NotBlank String orderId, + @ApiParam("璇勪环浜篒D") @RequestParam @NotNull Long evaluatorId, + @ApiParam("璇勪环浜哄鍚�") @RequestParam @NotBlank String evaluatorName, + @ApiParam("璇勪环浜虹被鍨�") @RequestParam @NotBlank String evaluatorType, + @ApiParam("璇勪环鍐呭") @RequestParam @NotBlank String content, + @ApiParam("璇勫垎") @RequestParam @NotNull Integer rating, + @ApiParam("鏈嶅姟璇勫垎") @RequestParam Integer serviceRating, + @ApiParam("璐ㄩ噺璇勫垎") @RequestParam Integer qualityRating, + @ApiParam("浜や粯璇勫垎") @RequestParam Integer deliveryRating, + @ApiParam("鏄惁鍖垮悕") @RequestParam Boolean isAnonymous) { + try { + boolean result = orderInfoService.addOrderEvaluation( + orderId, evaluatorId, evaluatorName, evaluatorType, content, rating, + serviceRating, qualityRating, deliveryRating, isAnonymous + ); + return result ? Result.success(true) : Result.error("娣诲姞璁㈠崟璇勪环澶辫触"); + } catch (Exception e) { + log.error("娣诲姞璁㈠崟璇勪环澶辫触锛岃鍗旾D: {}", orderId, e); + return Result.error("娣诲姞璁㈠崟璇勪环澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/transaction/confirm") + @ApiOperation("浜ゆ槗纭") + public Result<Boolean> confirmTransaction( + @ApiParam("璁㈠崟ID") @RequestParam @NotBlank String orderId, + @ApiParam("鐢ㄦ埛ID") @RequestParam @NotNull Long userId) { + try { + boolean result = orderInfoService.confirmTransaction(orderId, userId); + return result ? Result.success(true) : Result.error("浜ゆ槗纭澶辫触"); + } catch (Exception e) { + log.error("浜ゆ槗纭澶辫触锛岃鍗旾D: {}", orderId, e); + return Result.error("浜ゆ槗纭澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/evaluation/reply") + @ApiOperation("鍥炲璇勪环") + public Result<Boolean> replyEvaluation( + @ApiParam("璇勪环ID") @RequestParam @NotNull Long evaluationId, + @ApiParam("鍥炲鍐呭") @RequestParam @NotBlank String replyContent, + @ApiParam("鍥炲鐢ㄦ埛ID") @RequestParam @NotNull Long replyUserId) { + try { + boolean result = orderInfoService.replyEvaluation(evaluationId, replyContent, replyUserId); + return result ? Result.success(true) : Result.error("鍥炲璇勪环澶辫触"); + } catch (Exception e) { + log.error("鍥炲璇勪环澶辫触锛岃瘎浠稩D: {}", evaluationId, e); + return Result.error("鍥炲璇勪环澶辫触锛�" + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/controller/PointsController.java b/src/main/java/com/webmanage/controller/PointsController.java new file mode 100644 index 0000000..b4e0ba5 --- /dev/null +++ b/src/main/java/com/webmanage/controller/PointsController.java @@ -0,0 +1,275 @@ +package com.webmanage.controller; + +import com.webmanage.common.Result; +import com.webmanage.dto.AddPointsFlowDTO; +import com.webmanage.dto.PointsFlowQueryDTO; +import com.webmanage.dto.PointsMainQueryDTO; +import com.webmanage.dto.PointsRuleDTO; +import com.webmanage.entity.Points; +import com.webmanage.entity.PointsRule; +import com.webmanage.service.PointsFlowService; +import com.webmanage.service.PointsRuleService; +import com.webmanage.service.PointsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.List; +import com.webmanage.entity.PointsFlow; + +/** + * 绉垎绠$悊Controller + */ +@Slf4j +@RestController +@RequestMapping("/api/points") +@Api(tags = "绉垎绠$悊") +@Validated +public class PointsController { + + @Resource + private PointsRuleService pointsRuleService; + + @Resource + private PointsFlowService pointsFlowService; + + @Resource + private PointsService pointsService; + + // ==================== 绉垎涓昏〃绠$悊 ==================== + + @PostMapping("/main/page") + @ApiOperation("鍒嗛〉鏌ヨ绉垎涓昏〃") + public Result<Object> getPointsMainPage(@Valid @RequestBody PointsMainQueryDTO queryDTO) { + try { + return Result.success(pointsService.getPointsMainPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ绉垎涓昏〃澶辫触", e); + return Result.error("鏌ヨ绉垎涓昏〃澶辫触锛�" + e.getMessage()); + } + } + + + // ==================== 绉垎瑙勫垯绠$悊 ==================== + + @PostMapping("/rule/page") + @ApiOperation("鍒嗛〉鏌ヨ绉垎瑙勫垯") + public Result<Object> getPointsRulePage(@RequestParam(defaultValue = "1") Integer pageNum, + @RequestParam(defaultValue = "10") Integer pageSize, + @RequestParam(required = false) String ruleName, + @RequestParam(required = false) String ruleType) { + try { + return Result.success(pointsRuleService.getPointsRulePage(pageNum, pageSize, ruleName, ruleType)); + } catch (Exception e) { + log.error("鏌ヨ绉垎瑙勫垯澶辫触", e); + return Result.error("鏌ヨ绉垎瑙勫垯澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/rule/add") + @ApiOperation("鏂板绉垎瑙勫垯") + public Result<Object> addPointsRule(@Valid @RequestBody PointsRuleDTO pointsRuleDTO) { + try { + boolean result = pointsRuleService.addPointsRule(pointsRuleDTO); + if (result) { + return Result.success("鏂板绉垎瑙勫垯鎴愬姛"); + } else { + return Result.error("鏂板绉垎瑙勫垯澶辫触"); + } + } catch (Exception e) { + log.error("鏂板绉垎瑙勫垯澶辫触", e); + return Result.error("鏂板绉垎瑙勫垯澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/rule/update") + @ApiOperation("淇敼绉垎瑙勫垯") + public Result<Object> updatePointsRule(@Valid @RequestBody PointsRuleDTO pointsRuleDTO) { + try { + boolean result = pointsRuleService.updatePointsRule(pointsRuleDTO); + if (result) { + return Result.success("淇敼绉垎瑙勫垯鎴愬姛"); + } else { + return Result.error("淇敼绉垎瑙勫垯澶辫触"); + } + } catch (Exception e) { + log.error("淇敼绉垎瑙勫垯澶辫触", e); + return Result.error("淇敼绉垎瑙勫垯澶辫触锛�" + e.getMessage()); + } + } + + @DeleteMapping("/rule/{id}") + @ApiOperation("鍒犻櫎绉垎瑙勫垯") + public Result<Object> deletePointsRule(@ApiParam("瑙勫垯ID") @PathVariable Long id) { + try { + boolean result = pointsRuleService.deletePointsRule(id); + if (result) { + return Result.success("鍒犻櫎绉垎瑙勫垯鎴愬姛"); + } else { + return Result.error("鍒犻櫎绉垎瑙勫垯澶辫触"); + } + } catch (Exception e) { + log.error("鍒犻櫎绉垎瑙勫垯澶辫触", e); + return Result.error("鍒犻櫎绉垎瑙勫垯澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/rule/toggle/{id}") + @ApiOperation("鍚敤/绂佺敤绉垎瑙勫垯") + public Result<Object> togglePointsRuleStatus(@ApiParam("瑙勫垯ID") @PathVariable Long id, + @ApiParam("鏄惁鍚敤") @RequestParam @NotNull Boolean isEnabled) { + try { + boolean result = pointsRuleService.togglePointsRuleStatus(id, isEnabled); + if (result) { + return Result.success("鎿嶄綔鎴愬姛"); + } else { + return Result.error("鎿嶄綔澶辫触"); + } + } catch (Exception e) { + log.error("鎿嶄綔绉垎瑙勫垯鐘舵�佸け璐�", e); + return Result.error("鎿嶄綔绉垎瑙勫垯鐘舵�佸け璐ワ細" + e.getMessage()); + } + } + + @GetMapping("/rule/type/{ruleType}") + @ApiOperation("鏍规嵁瑙勫垯绫诲瀷鏌ヨ鍚敤鐨勮鍒�") + public Result<Object> getEnabledRulesByType(@ApiParam("瑙勫垯绫诲瀷") @PathVariable String ruleType) { + try { + List<PointsRule> rules = pointsRuleService.getEnabledRulesByType(ruleType); + return Result.success(rules); + } catch (Exception e) { + log.error("鏌ヨ绉垎瑙勫垯澶辫触", e); + return Result.error("鏌ヨ绉垎瑙勫垯澶辫触锛�" + e.getMessage()); + } + } + + // ==================== 绉垎娴佹按鏌ヨ ==================== + + @PostMapping("/flow/personal/page") + @ApiOperation("鍒嗛〉鏌ヨ涓汉绉垎娴佹按") + public Result<Object> getPersonalPointsFlowPage(@Valid @RequestBody PointsFlowQueryDTO queryDTO) { + try { + return Result.success(pointsFlowService.getPersonalPointsFlowPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ涓汉绉垎娴佹按澶辫触", e); + return Result.error("鏌ヨ涓汉绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/flow/unit/page") + @ApiOperation("鍒嗛〉鏌ヨ鍗曚綅绉垎娴佹按") + public Result<Object> getUnitPointsFlowPage(@Valid @RequestBody PointsFlowQueryDTO queryDTO) { + try { + return Result.success(pointsFlowService.getUnitPointsFlowPage(queryDTO)); + } catch (Exception e) { + log.error("鏌ヨ鍗曚綅绉垎娴佹按澶辫触", e); + return Result.error("鏌ヨ鍗曚綅绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + @GetMapping("/flow/user/{userId}") + @ApiOperation("鏍规嵁鐢ㄦ埛ID鏌ヨ绉垎娴佹按") + public Result<Object> getPointsFlowByUserId(@ApiParam("鐢ㄦ埛ID") @PathVariable Long userId) { + try { + List<PointsFlow> flows = pointsFlowService.getPointsFlowByUserId(userId); + return Result.success(flows); + } catch (Exception e) { + log.error("鏌ヨ鐢ㄦ埛绉垎娴佹按澶辫触", e); + return Result.error("鏌ヨ鐢ㄦ埛绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + @GetMapping("/flow/unit/{unitId}") + @ApiOperation("鏍规嵁鍗曚綅ID鏌ヨ绉垎娴佹按") + public Result<Object> getPointsFlowByUnitId(@ApiParam("鍗曚綅ID") @PathVariable Long unitId) { + try { + List<PointsFlow> flows = pointsFlowService.getPointsFlowByUnitId(unitId); + return Result.success(flows); + } catch (Exception e) { + log.error("鏌ヨ鍗曚綅绉垎娴佹按澶辫触", e); + return Result.error("鏌ヨ鍗曚綅绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + // ==================== 鏂板绉垎娴佹按 ==================== + + @PostMapping("/flow/add") + @ApiOperation("鏂板绉垎娴佹按锛堟牴鎹鍒欒嚜鍔ㄨ绠楋級") + public Result<Object> addPointsFlow(@Valid @RequestBody AddPointsFlowDTO addPointsFlowDTO) { + try { + boolean result = pointsFlowService.addPointsFlowByRule(addPointsFlowDTO); + if (result) { + return Result.success("鏂板绉垎娴佹按鎴愬姛"); + } else { + return Result.error("鏂板绉垎娴佹按澶辫触"); + } + } catch (Exception e) { + log.error("鏂板绉垎娴佹按澶辫触", e); + return Result.error("鏂板绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/flow/add/personal") + @ApiOperation("鏂板涓汉绉垎娴佹按") + public Result<Object> addPersonalPointsFlow(@Valid @RequestBody AddPointsFlowDTO addPointsFlowDTO) { + try { + boolean result = pointsFlowService.addPointsFlowByRule(addPointsFlowDTO); + if (result) { + return Result.success("鏂板涓汉绉垎娴佹按鎴愬姛"); + } else { + return Result.error("鏂板涓汉绉垎娴佹按澶辫触"); + } + } catch (Exception e) { + log.error("鏂板涓汉绉垎娴佹按澶辫触", e); + return Result.error("鏂板涓汉绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + @PostMapping("/flow/add/unit") + @ApiOperation("鏂板鍗曚綅绉垎娴佹按") + public Result<Object> addUnitPointsFlow(@Valid @RequestBody AddPointsFlowDTO addPointsFlowDTO) { + try { + boolean result = pointsFlowService.addPointsFlowByRule(addPointsFlowDTO); + if (result) { + return Result.success("鏂板鍗曚綅绉垎娴佹按鎴愬姛"); + } else { + return Result.error("鏂板鍗曚綅绉垎娴佹按澶辫触"); + } + } catch (Exception e) { + log.error("鏂板鍗曚綅绉垎娴佹按澶辫触", e); + return Result.error("鏂板鍗曚綅绉垎娴佹按澶辫触锛�" + e.getMessage()); + } + } + + // ==================== 绉垎缁熻 ==================== + + @GetMapping("/total/user/{userId}") + @ApiOperation("鑾峰彇鐢ㄦ埛绉垎缁熻") + public Result<Object> getUserPointsTotal(@ApiParam("鐢ㄦ埛ID") @PathVariable Long userId) { + try { + Integer total = pointsFlowService.getUserPointsTotal(userId); + return Result.success(total); + } catch (Exception e) { + log.error("鑾峰彇鐢ㄦ埛绉垎缁熻澶辫触", e); + return Result.error("鑾峰彇鐢ㄦ埛绉垎缁熻澶辫触锛�" + e.getMessage()); + } + } + + @GetMapping("/total/unit/{unitId}") + @ApiOperation("鑾峰彇鍗曚綅绉垎缁熻") + public Result<Object> getUnitPointsTotal(@ApiParam("鍗曚綅ID") @PathVariable Long unitId) { + try { + Integer total = pointsFlowService.getUnitPointsTotal(unitId); + return Result.success(total); + } catch (Exception e) { + log.error("鑾峰彇鍗曚綅绉垎缁熻澶辫触", e); + return Result.error("鑾峰彇鍗曚綅绉垎缁熻澶辫触锛�" + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/controller/ProductPricingController.java b/src/main/java/com/webmanage/controller/ProductPricingController.java new file mode 100644 index 0000000..1ca6f19 --- /dev/null +++ b/src/main/java/com/webmanage/controller/ProductPricingController.java @@ -0,0 +1,164 @@ +package com.webmanage.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.common.Result; +import com.webmanage.entity.ProductPricing; +import com.webmanage.service.ProductPricingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +/** + * 浜у搧瀹氫环绠$悊鎺у埗鍣� + * + * @author webmanage + * @date 2024-08-07 + */ +@Slf4j +@RestController +@RequestMapping("/product-pricing") +@Api(tags = "浜у搧瀹氫环绠$悊") +@Validated +public class ProductPricingController { + + @Autowired + private ProductPricingService productPricingService; + + /** + * 鏂板浜у搧瀹氫环 + */ + @PostMapping("/add") + @ApiOperation("鏂板浜у搧瀹氫环") + public Result<Boolean> addProductPricing(@Valid @RequestBody ProductPricing productPricing) { + try { + boolean result = productPricingService.addProductPricing(productPricing); + return result ? Result.success("鏂板浜у搧瀹氫环鎴愬姛", true) : Result.error("鏂板浜у搧瀹氫环澶辫触"); + } catch (Exception e) { + log.error("鏂板浜у搧瀹氫环澶辫触: ", e); + return Result.error("鏂板浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 缂栬緫浜у搧瀹氫环 + */ + @PutMapping("/update") + @ApiOperation("缂栬緫浜у搧瀹氫环") + public Result<Boolean> updateProductPricing(@Valid @RequestBody ProductPricing productPricing) { + try { + if (productPricing.getId() == null) { + return Result.error("浜у搧瀹氫环ID涓嶈兘涓虹┖"); + } + boolean result = productPricingService.updateProductPricing(productPricing); + return result ? Result.success("缂栬緫浜у搧瀹氫环鎴愬姛", true) : Result.error("缂栬緫浜у搧瀹氫环澶辫触"); + } catch (Exception e) { + log.error("缂栬緫浜у搧瀹氫环澶辫触: ", e); + return Result.error("缂栬緫浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 鍒犻櫎浜у搧瀹氫环锛堥�昏緫鍒犻櫎锛� + */ + @DeleteMapping("/delete/{id}") + @ApiOperation("鍒犻櫎浜у搧瀹氫环") + public Result<Boolean> deleteProductPricing(@ApiParam("浜у搧瀹氫环ID") @PathVariable Long id) { + try { + if (id == null) { + return Result.error("浜у搧瀹氫环ID涓嶈兘涓虹┖"); + } + boolean result = productPricingService.deleteProductPricing(id); + return result ? Result.success("鍒犻櫎浜у搧瀹氫环鎴愬姛", true) : Result.error("鍒犻櫎浜у搧瀹氫环澶辫触"); + } catch (Exception e) { + log.error("鍒犻櫎浜у搧瀹氫环澶辫触: ", e); + return Result.error("鍒犻櫎浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 鍒嗛〉鏌ヨ浜у搧瀹氫环鍒楄〃 + */ + @GetMapping("/page") + @ApiOperation("鍒嗛〉鏌ヨ浜у搧瀹氫环鍒楄〃") + public Result<IPage<ProductPricing>> getProductPricingPage( + @ApiParam("椤电爜") @RequestParam(defaultValue = "1") Long pageNum, + @ApiParam("姣忛〉澶у皬") @RequestParam(defaultValue = "10") Long pageSize, + @ApiParam("浜у搧ID") @RequestParam(required = false) Long productId) { + try { + Page<ProductPricing> page = new Page<>(pageNum, pageSize); + IPage<ProductPricing> result = productPricingService.getProductPricingPage(page, productId); + return Result.success("鏌ヨ鎴愬姛", result); + } catch (Exception e) { + log.error("鍒嗛〉鏌ヨ浜у搧瀹氫环澶辫触: ", e); + return Result.error("鍒嗛〉鏌ヨ浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 鏍规嵁浜у搧ID鏌ヨ瀹氫环鍒楄〃 + */ + @GetMapping("/product/{productId}") + @ApiOperation("鏍规嵁浜у搧ID鏌ヨ瀹氫环鍒楄〃") + public Result<List<ProductPricing>> getPricingByProductId(@ApiParam("浜у搧ID") @PathVariable Long productId) { + try { + if (productId == null) { + return Result.error("浜у搧ID涓嶈兘涓虹┖"); + } + List<ProductPricing> result = productPricingService.getPricingByProductId(productId); + return Result.success("鏌ヨ鎴愬姛", result); + } catch (Exception e) { + log.error("鏍规嵁浜у搧ID鏌ヨ瀹氫环澶辫触: ", e); + return Result.error("鏍规嵁浜у搧ID鏌ヨ瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环 + */ + @GetMapping("/condition") + @ApiOperation("鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环") + public Result<List<ProductPricing>> getPricingByCondition( + @ApiParam("濂椾欢鍚嶇О") @RequestParam(required = false) String suiteName, + @ApiParam("閿�鍞舰寮�") @RequestParam(required = false) String salesForm, + @ApiParam("瀹㈡埛瀵硅薄") @RequestParam(required = false) String customerType, + @ApiParam("浠锋牸绫诲瀷") @RequestParam(required = false) String priceType, + @ApiParam("鍚敤鐘舵��") @RequestParam(required = false) Boolean isActive) { + try { + List<ProductPricing> result = productPricingService.getPricingByCondition( + suiteName, salesForm, customerType, priceType, isActive); + return Result.success("鏌ヨ鎴愬姛", result); + } catch (Exception e) { + log.error("鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环澶辫触: ", e); + return Result.error("鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + /** + * 鑾峰彇浜у搧瀹氫环璇︽儏 + */ + @GetMapping("/detail/{id}") + @ApiOperation("鑾峰彇浜у搧瀹氫环璇︽儏") + public Result<ProductPricing> getProductPricingDetail(@ApiParam("浜у搧瀹氫环ID") @PathVariable Long id) { + try { + if (id == null) { + return Result.error("浜у搧瀹氫环ID涓嶈兘涓虹┖"); + } + ProductPricing result = productPricingService.getById(id); + if (result == null) { + return Result.error("浜у搧瀹氫环涓嶅瓨鍦�"); + } + return Result.success("鏌ヨ鎴愬姛", result); + } catch (Exception e) { + log.error("鑾峰彇浜у搧瀹氫环璇︽儏澶辫触: ", e); + return Result.error("鑾峰彇浜у搧瀹氫环璇︽儏澶辫触: " + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/dto/AddPointsFlowDTO.java b/src/main/java/com/webmanage/dto/AddPointsFlowDTO.java new file mode 100644 index 0000000..5fbb5c0 --- /dev/null +++ b/src/main/java/com/webmanage/dto/AddPointsFlowDTO.java @@ -0,0 +1,41 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 鏂板绉垎娴佹按DTO + */ +@Data +@ApiModel(value = "AddPointsFlowDTO", description = "鏂板绉垎娴佹按") +public class AddPointsFlowDTO { + + @ApiModelProperty("鐢ㄦ埛ID") + @NotNull(message = "鐢ㄦ埛ID涓嶈兘涓虹┖") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + @NotNull(message = "鍗曚綅ID涓嶈兘涓虹┖") + private Long unitId; + + @ApiModelProperty("瑙勫垯绫诲瀷(鑾峰緱/娑堣垂)") + @NotBlank(message = "瑙勫垯绫诲瀷涓嶈兘涓虹┖") + private String ruleType; + + @ApiModelProperty("瑙勫垯鍚嶇О") + @NotBlank(message = "瑙勫垯鍚嶇О涓嶈兘涓虹┖") + private String ruleName; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + private String orderId; + + @ApiModelProperty("绉垎娴佹按鎻忚堪") + private String description; + + @ApiModelProperty("瑙﹀彂娆℃暟(榛樿涓�1)") + private Integer count = 1; +} diff --git a/src/main/java/com/webmanage/dto/ApprovalActionDTO.java b/src/main/java/com/webmanage/dto/ApprovalActionDTO.java new file mode 100644 index 0000000..e622829 --- /dev/null +++ b/src/main/java/com/webmanage/dto/ApprovalActionDTO.java @@ -0,0 +1,55 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 瀹℃壒鎿嶄綔DTO + */ +@Data +@ApiModel(value = "ApprovalActionDTO", description = "瀹℃壒鎿嶄綔") +public class ApprovalActionDTO { + + @ApiModelProperty("璁㈠崟ID") + @NotBlank(message = "璁㈠崟ID涓嶈兘涓虹┖") + private String orderId; + + @ApiModelProperty("瀹℃壒浜篒D") + @NotNull(message = "瀹℃壒浜篒D涓嶈兘涓虹┖") + private Long approverId; + + @ApiModelProperty("瀹℃壒浜哄鍚�") + @NotBlank(message = "瀹℃壒浜哄鍚嶄笉鑳戒负绌�") + private String approverName; + + @ApiModelProperty("瀹℃壒浜鸿鑹�") + @NotBlank(message = "瀹℃壒浜鸿鑹蹭笉鑳戒负绌�") + private String approverRole; + + @ApiModelProperty("瀹℃壒姝ラ") + @NotBlank(message = "瀹℃壒姝ラ涓嶈兘涓虹┖") + private String approvalStep; + + @ApiModelProperty("瀹℃壒缁撴灉(閫氳繃/椹冲洖)") + @NotBlank(message = "瀹℃壒缁撴灉涓嶈兘涓虹┖") + private String approvalResult; + + @ApiModelProperty("瀹℃壒鎰忚") + private String approvalOpinion; + + @ApiModelProperty("鏄惁闇�瑕佹巿鏉�") + private Boolean needAuthorization = false; + + @ApiModelProperty("鎺堟潈浜篒D") + private Long authorizerId; + + @ApiModelProperty("鎺堟潈浜哄鍚�") + private String authorizerName; + + @ApiModelProperty("鎺堟潈鎰忚") + private String authorizationOpinion; +} diff --git a/src/main/java/com/webmanage/dto/ApprovalQueryDTO.java b/src/main/java/com/webmanage/dto/ApprovalQueryDTO.java new file mode 100644 index 0000000..a35ab24 --- /dev/null +++ b/src/main/java/com/webmanage/dto/ApprovalQueryDTO.java @@ -0,0 +1,60 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 瀹℃壒鏌ヨ鏉′欢DTO + */ +@Data +@ApiModel(value = "ApprovalQueryDTO", description = "瀹℃壒鏌ヨ鏉′欢") +public class ApprovalQueryDTO { + + @ApiModelProperty("褰撳墠椤电爜") + private Integer pageNum = 1; + + @ApiModelProperty("姣忛〉澶у皬") + private Integer pageSize = 10; + + @ApiModelProperty("璁㈠崟ID") + private String orderId; + + @ApiModelProperty("浜у搧鍚嶇О") + private String productName; + + @ApiModelProperty("鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("瀹℃壒浜篒D") + private Long approverId; + + @ApiModelProperty("瀹℃壒缁撴灉") + private String approvalResult; + + @ApiModelProperty("瀹℃壒姝ラ") + private String approvalStep; + + @ApiModelProperty("鏄惁闇�瑕佹巿鏉�") + private Boolean needAuthorization; + + @ApiModelProperty("鐢宠寮�濮嬫椂闂�") + private LocalDateTime applyTimeStart; + + @ApiModelProperty("鐢宠缁撴潫鏃堕棿") + private LocalDateTime applyTimeEnd; + + @ApiModelProperty("瀹℃壒寮�濮嬫椂闂�") + private LocalDateTime approvalTimeStart; + + @ApiModelProperty("瀹℃壒缁撴潫鏃堕棿") + private LocalDateTime approvalTimeEnd; + + @ApiModelProperty("鎺掑簭瀛楁") + private String orderBy = "created_at"; + + @ApiModelProperty("鎺掑簭鏂瑰悜(asc/desc)") + private String orderDirection = "desc"; +} diff --git a/src/main/java/com/webmanage/dto/CartItemDTO.java b/src/main/java/com/webmanage/dto/CartItemDTO.java new file mode 100644 index 0000000..8514c92 --- /dev/null +++ b/src/main/java/com/webmanage/dto/CartItemDTO.java @@ -0,0 +1,73 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 璐墿杞﹀晢鍝侀」DTO + */ +@Data +@ApiModel(value = "CartItemDTO", description = "璐墿杞﹀晢鍝侀」") +public class CartItemDTO { + + @ApiModelProperty("鍟嗗搧瀹氫环ID") + @NotNull(message = "鍟嗗搧瀹氫环ID涓嶈兘涓虹┖") + private Long pricingId; + + @ApiModelProperty("鍟嗗搧ID") + @NotNull(message = "鍟嗗搧ID涓嶈兘涓虹┖") + private Long productId; + + @ApiModelProperty("鍟嗗搧鍚嶇О") + private String productName; + + @ApiModelProperty("鍟嗗搧濂椾欢鍚嶇О") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + @NotNull(message = "鍗曚环涓嶈兘涓虹┖") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + @NotNull(message = "鏁伴噺涓嶈兘涓虹┖") + @Min(value = 1, message = "鏁伴噺蹇呴』澶т簬0") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + private Integer duration; + + @ApiModelProperty("灏忚閲戦") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("澶囨敞") + private String remarks; +} diff --git a/src/main/java/com/webmanage/dto/CartQueryDTO.java b/src/main/java/com/webmanage/dto/CartQueryDTO.java new file mode 100644 index 0000000..4bca7f3 --- /dev/null +++ b/src/main/java/com/webmanage/dto/CartQueryDTO.java @@ -0,0 +1,29 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 璐墿杞︽煡璇TO + */ +@Data +@ApiModel(value = "CartQueryDTO", description = "璐墿杞︽煡璇㈡潯浠�") +public class CartQueryDTO { + + @ApiModelProperty("鐢ㄦ埛ID") + @NotNull(message = "鐢ㄦ埛ID涓嶈兘涓虹┖") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + @NotNull(message = "鍗曚綅ID涓嶈兘涓虹┖") + private Long unitId; + + @ApiModelProperty("鍟嗗搧鍚嶇О") + private String productName; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; +} diff --git a/src/main/java/com/webmanage/dto/CreateOrderDTO.java b/src/main/java/com/webmanage/dto/CreateOrderDTO.java new file mode 100644 index 0000000..8d940ae --- /dev/null +++ b/src/main/java/com/webmanage/dto/CreateOrderDTO.java @@ -0,0 +1,50 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; + +@Data +@ApiModel(value = "CreateOrderDTO", description = "鍒涘缓璁㈠崟璇锋眰") +public class CreateOrderDTO { + + @ApiModelProperty("鐢ㄦ埛ID") + @NotNull(message = "鐢ㄦ埛ID涓嶈兘涓虹┖") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + @NotNull(message = "鍗曚綅ID涓嶈兘涓虹┖") + private Long unitId; + + @ApiModelProperty("浜у搧鍚嶇О") + @NotBlank(message = "浜у搧鍚嶇О涓嶈兘涓虹┖") + private String productName; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("鏀粯鏂瑰紡锛堝锛氱Н鍒�/鐜伴噾/娣峰悎锛�") + @NotBlank(message = "鏀粯鏂瑰紡涓嶈兘涓虹┖") + private String paymentType; + + @ApiModelProperty("涔板澶囨敞") + private String buyerRemarks; + + @ApiModelProperty("璁㈠崟鎬婚噾棰濓紙鍙笉浼狅紝鍚庣鎸夋槑缁嗗悎璁¤绠楋級") + private BigDecimal totalAmount; + + @ApiModelProperty("璁㈠崟鏄庣粏鍒楄〃") + @Valid + @NotEmpty(message = "璁㈠崟鏄庣粏涓嶈兘涓虹┖") + private List<CreateOrderItemDTO> items; +} diff --git a/src/main/java/com/webmanage/dto/CreateOrderItemDTO.java b/src/main/java/com/webmanage/dto/CreateOrderItemDTO.java new file mode 100644 index 0000000..e34bc55 --- /dev/null +++ b/src/main/java/com/webmanage/dto/CreateOrderItemDTO.java @@ -0,0 +1,65 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +@Data +@ApiModel(value = "CreateOrderItemDTO", description = "鍒涘缓璁㈠崟-鏄庣粏椤�") +public class CreateOrderItemDTO { + @ApiModelProperty("鍏宠仈浜у搧瀹氫环ID") + private Long pricingId; + + @ApiModelProperty("浜у搧ID") + @NotNull(message = "浜у搧ID涓嶈兘涓虹┖") + private Long productId; + + @ApiModelProperty("浜у搧濂椾欢鍚嶇О") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + @NotNull(message = "鍗曚环涓嶈兘涓虹┖") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + @NotNull(message = "鏁伴噺涓嶈兘涓虹┖") + @Min(value = 1, message = "鏁伴噺蹇呴』澶т簬0") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + private Integer duration; + + @ApiModelProperty("灏忚閲戦(鍙笉浼狅紝鍚庣鎸夊崟浠�*鏁伴噺璁$畻)") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("澶囨敞") + private String remarks; +} diff --git a/src/main/java/com/webmanage/dto/OrderQueryDTO.java b/src/main/java/com/webmanage/dto/OrderQueryDTO.java new file mode 100644 index 0000000..9f96807 --- /dev/null +++ b/src/main/java/com/webmanage/dto/OrderQueryDTO.java @@ -0,0 +1,66 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 璁㈠崟鏌ヨ鏉′欢DTO + */ +@Data +@ApiModel(value = "OrderQueryDTO", description = "璁㈠崟鏌ヨ鏉′欢") +public class OrderQueryDTO { + + @ApiModelProperty("褰撳墠椤电爜") + private Integer pageNum = 1; + + @ApiModelProperty("姣忛〉澶у皬") + private Integer pageSize = 10; + + @ApiModelProperty("鐢ㄦ埛ID") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + private Long unitId; + + @ApiModelProperty("鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("璁㈠崟鐘舵��") + private String orderStatus; + + @ApiModelProperty("鏀粯鐘舵��") + private String paymentStatus; + + @ApiModelProperty("鏀粯鏂瑰紡") + private String paymentType; + + @ApiModelProperty("浜у搧鍚嶇О") + private String productName; + + @ApiModelProperty("鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("璁㈠崟缂栧彿") + private String orderId; + + @ApiModelProperty("鐢宠寮�濮嬫椂闂�") + private LocalDateTime applyTimeStart; + + @ApiModelProperty("鐢宠缁撴潫鏃堕棿") + private LocalDateTime applyTimeEnd; + + @ApiModelProperty("鍒涘缓寮�濮嬫椂闂�") + private LocalDateTime createTimeStart; + + @ApiModelProperty("鍒涘缓缁撴潫鏃堕棿") + private LocalDateTime createTimeEnd; + + @ApiModelProperty("鎺掑簭瀛楁") + private String orderBy = "created_at"; + + @ApiModelProperty("鎺掑簭鏂瑰悜(asc/desc)") + private String orderDirection = "desc"; +} diff --git a/src/main/java/com/webmanage/dto/PointsDTO.java b/src/main/java/com/webmanage/dto/PointsDTO.java new file mode 100644 index 0000000..92c0b08 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsDTO.java @@ -0,0 +1,41 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +/** + * 绉垎涓昏〃DTO + */ +@Data +@ApiModel(value = "PointsDTO", description = "绉垎涓昏〃") +public class PointsDTO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("绉垎鍚嶇О") + @NotBlank(message = "绉垎鍚嶇О涓嶈兘涓虹┖") + private String pointsName; + + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�") + private LocalDateTime effectiveStart; + + @ApiModelProperty("鐢熸晥缁撴潫鏃堕棿") + private LocalDateTime effectiveEnd; + + + @ApiModelProperty("淇敼浜哄鍚�") + private String modifierName; + + @ApiModelProperty("鐗堟湰鍙�") + private String version; + + + @ApiModelProperty("鐘舵��") + private String status; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/dto/PointsFlowQueryDTO.java b/src/main/java/com/webmanage/dto/PointsFlowQueryDTO.java new file mode 100644 index 0000000..3234cf0 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsFlowQueryDTO.java @@ -0,0 +1,48 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 绉垎娴佹按鏌ヨ鏉′欢DTO + */ +@Data +@ApiModel(value = "PointsFlowQueryDTO", description = "绉垎娴佹按鏌ヨ鏉′欢") +public class PointsFlowQueryDTO { + + @ApiModelProperty("褰撳墠椤电爜") + private Integer pageNum = 1; + + @ApiModelProperty("姣忛〉澶у皬") + private Integer pageSize = 10; + + @ApiModelProperty("鐢ㄦ埛ID") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + private Long unitId; + + @ApiModelProperty("娴佹按绫诲瀷(鑾峰緱/娑堣垂)") + private String flowType; + + @ApiModelProperty("绉垎鏉ユ簮") + private String pointsSource; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + private String orderId; + + @ApiModelProperty("寮�濮嬫椂闂�") + private LocalDateTime startTime; + + @ApiModelProperty("缁撴潫鏃堕棿") + private LocalDateTime endTime; + + @ApiModelProperty("鎺掑簭瀛楁") + private String orderBy = "created_at"; + + @ApiModelProperty("鎺掑簭鏂瑰悜(asc/desc)") + private String orderDirection = "desc"; +} diff --git a/src/main/java/com/webmanage/dto/PointsMainQueryDTO.java b/src/main/java/com/webmanage/dto/PointsMainQueryDTO.java new file mode 100644 index 0000000..dbe278d --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsMainQueryDTO.java @@ -0,0 +1,51 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 绉垎涓昏〃鏌ヨDTO + */ +@Data +@ApiModel(value = "PointsMainQueryDTO", description = "绉垎涓昏〃鏌ヨ鏉′欢") +public class PointsMainQueryDTO { + + @ApiModelProperty("褰撳墠椤电爜") + private Integer pageNum = 1; + + @ApiModelProperty("姣忛〉澶у皬") + private Integer pageSize = 10; + + @ApiModelProperty("绉垎鍚嶇О") + private String pointsName; + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�-寮�濮�") + private LocalDateTime effectiveStartTime; + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�-缁撴潫") + private LocalDateTime effectiveEndTime; + + @ApiModelProperty("淇敼浜哄鍚�") + private String modifierName; + + @ApiModelProperty("鐗堟湰鍙�") + private String version; + + @ApiModelProperty("鐘舵��") + private String status; + + @ApiModelProperty("鍒涘缓鏃堕棿-寮�濮�") + private LocalDateTime createdAtBegin; + + @ApiModelProperty("鍒涘缓鏃堕棿-缁撴潫") + private LocalDateTime createdAtEnd; + + @ApiModelProperty("鎺掑簭瀛楁") + private String orderBy = "created_at"; + + @ApiModelProperty("鎺掑簭鏂瑰悜(asc/desc)") + private String orderDirection = "desc"; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/dto/PointsOperateDTO.java b/src/main/java/com/webmanage/dto/PointsOperateDTO.java new file mode 100644 index 0000000..3e03be4 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsOperateDTO.java @@ -0,0 +1,18 @@ +package com.webmanage.dto; + +import lombok.Data; + +/** + * 璁拌处鎿嶄綔DTO锛氭寜瑙勫垯鍚嶆柊澧炴祦姘� + */ +@Data +public class PointsOperateDTO { + /** 瀵瑰簲 points_rule.rule_name */ + private String ruleName; + /** 娆℃暟/鏁伴噺锛屽彲绌洪粯璁�1 */ + private Integer count; + /** 娴佹按鍚嶇О/鎻忚堪锛堝彲閫夛紝涓嶅~鐢ㄨ鍒欐弿杩帮級 */ + private String name; +} + + diff --git a/src/main/java/com/webmanage/dto/PointsQueryDTO.java b/src/main/java/com/webmanage/dto/PointsQueryDTO.java new file mode 100644 index 0000000..27b0219 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsQueryDTO.java @@ -0,0 +1,50 @@ +package com.webmanage.dto; + +import lombok.Data; + +/** + * 绉垎鏌ヨDTO + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +public class PointsQueryDTO { + + /** + * 鐢ㄦ埛ID锛堝彲閫夛紝鐢ㄤ簬闄愬畾涓汉娴佹按锛� + */ + private Long userId; + + /** + * 鍗曚綅ID锛堝彲閫夛紝鐢ㄤ簬闄愬畾鍗曚綅娴佹按锛� + */ + private Long unitId; + + /** 鏁版嵁绫荤洰 */ + private String dataCategory; + + /** 鏁版嵁绫诲瀷 */ + private String dataType; + + /** 寮�濮嬫椂闂� */ + private String startTime; + + /** 缁撴潫鏃堕棿 */ + private String endTime; + + /** 骞翠唤 */ + private String year; + + /** 鏈堜唤 */ + private String month; + + /** 鏃ユ湡 */ + private String day; + + /** 椤电爜 */ + private Integer pageNum = 1; + + /** 姣忛〉澶у皬 */ + private Integer pageSize = 10; +} diff --git a/src/main/java/com/webmanage/dto/PointsRuleDTO.java b/src/main/java/com/webmanage/dto/PointsRuleDTO.java new file mode 100644 index 0000000..e816a14 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsRuleDTO.java @@ -0,0 +1,54 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 绉垎瑙勫垯DTO + */ +@Data +@ApiModel(value = "PointsRuleDTO", description = "绉垎瑙勫垯") +public class PointsRuleDTO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("瑙勫垯鍚嶇О") + @NotBlank(message = "瑙勫垯鍚嶇О涓嶈兘涓虹┖") + private String ruleName; + + @ApiModelProperty("瑙勫垯绫诲瀷(鑾峰緱/娑堣垂)") + @NotBlank(message = "瑙勫垯绫诲瀷涓嶈兘涓虹┖") + private String ruleType; + + @ApiModelProperty("绉垎鍊�") + @NotNull(message = "绉垎鍊间笉鑳戒负绌�") + private Integer pointsValue; + + @ApiModelProperty("瑙﹀彂鏉′欢") + @NotBlank(message = "瑙﹀彂鏉′欢涓嶈兘涓虹┖") + private String triggerCondition; + + @ApiModelProperty("瑙﹀彂閲戦") + private BigDecimal triggerAmount; + + @ApiModelProperty("瑙勫垯鎻忚堪") + private String description; + + @ApiModelProperty("鏄惁鍚敤") + private Boolean isEnabled = true; + + @ApiModelProperty("浼樺厛绾�") + private Integer priority = 1; + + @ApiModelProperty("鏈夋晥鏈熷紑濮嬫椂闂�") + private String validStartTime; + + @ApiModelProperty("鏈夋晥鏈熺粨鏉熸椂闂�") + private String validEndTime; +} diff --git a/src/main/java/com/webmanage/dto/PointsRuleDetailDTO.java b/src/main/java/com/webmanage/dto/PointsRuleDetailDTO.java new file mode 100644 index 0000000..3ba8ca5 --- /dev/null +++ b/src/main/java/com/webmanage/dto/PointsRuleDetailDTO.java @@ -0,0 +1,56 @@ +package com.webmanage.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 绉垎瑙勫垯璇︽儏DTO + */ +@Data +@ApiModel(value = "PointsRuleDetailDTO", description = "绉垎瑙勫垯璇︽儏") +public class PointsRuleDetailDTO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("鍏宠仈绉垎瑙勫垯ID") + @NotNull(message = "鍏宠仈绉垎瑙勫垯ID涓嶈兘涓虹┖") + private Long ruleId; + + @ApiModelProperty("鍏宠仈绉垎ID") + @NotNull(message = "鍏宠仈绉垎ID涓嶈兘涓虹┖") + private Long pointsId; + + @ApiModelProperty("绉垎鍊�") + @NotNull(message = "绉垎鍊间笉鑳戒负绌�") + private Integer pointsValue; + + @ApiModelProperty("姣忔棩绉垎涓婇檺鍊�") + private Integer dailyLimit; + + @ApiModelProperty("姣忔湀绉垎涓婇檺鍊�") + private Integer monthlyLimit; + + @ApiModelProperty("姣忓勾绉垎涓婇檺鍊�") + private Integer yearlyLimit; + + @ApiModelProperty("鏈�灏忓��") + private Integer minValue; + + @ApiModelProperty("鏈�澶у��") + private Integer maxValue; + + @ApiModelProperty("杞崲姣旂巼") + private BigDecimal conversionRate; + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�") + private LocalDateTime effectiveStart; + + @ApiModelProperty("鐢熸晥缁撴潫鏃堕棿") + private LocalDateTime effectiveEnd; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/entity/ApprovalRecord.java b/src/main/java/com/webmanage/entity/ApprovalRecord.java new file mode 100644 index 0000000..0315756 --- /dev/null +++ b/src/main/java/com/webmanage/entity/ApprovalRecord.java @@ -0,0 +1,88 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 瀹℃壒璁板綍瀹炰綋绫� + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("approval_record") +@ApiModel(value = "ApprovalRecord", description = "瀹℃壒璁板綍") +public class ApprovalRecord { + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + @TableField("order_id") + private String orderId; + + @ApiModelProperty("瀹℃壒浜篒D") + @TableField("approver_id") + private Long approverId; + + @ApiModelProperty("瀹℃壒浜哄鍚�") + @TableField("approver_name") + private String approverName; + + @ApiModelProperty("瀹℃壒浜鸿鑹�") + @TableField("approver_role") + private String approverRole; + + @ApiModelProperty("瀹℃壒姝ラ") + @TableField("approval_step") + private String approvalStep; + + @ApiModelProperty("瀹℃壒缁撴灉(閫氳繃/椹冲洖)") + @TableField("approval_result") + private String approvalResult; + + @ApiModelProperty("瀹℃壒鎰忚") + @TableField("approval_opinion") + private String approvalOpinion; + + @ApiModelProperty("瀹℃壒鏃堕棿") + @TableField("approval_time") + private LocalDateTime approvalTime; + + @ApiModelProperty("鏄惁闇�瑕佹巿鏉�") + @TableField("need_authorization") + private Boolean needAuthorization; + + @ApiModelProperty("鎺堟潈浜篒D") + @TableField("authorizer_id") + private Long authorizerId; + + @ApiModelProperty("鎺堟潈浜哄鍚�") + @TableField("authorizer_name") + private String authorizerName; + + @ApiModelProperty("鎺堟潈鏃堕棿") + @TableField("authorization_time") + private LocalDateTime authorizationTime; + + @ApiModelProperty("鎺堟潈鎰忚") + @TableField("authorization_opinion") + private String authorizationOpinion; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/Cart.java b/src/main/java/com/webmanage/entity/Cart.java new file mode 100644 index 0000000..2504dd7 --- /dev/null +++ b/src/main/java/com/webmanage/entity/Cart.java @@ -0,0 +1,112 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 璐墿杞﹀疄浣撶被 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("cart") +@ApiModel(value = "Cart", description = "璐墿杞�") +public class Cart { + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鐢ㄦ埛ID") + @TableField("user_id") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + @TableField("unit_id") + private Long unitId; + + @ApiModelProperty("鍟嗗搧瀹氫环ID") + @TableField("pricing_id") + private Long pricingId; + + @ApiModelProperty("鍟嗗搧ID") + @TableField("product_id") + private Long productId; + + @ApiModelProperty("鍟嗗搧鍚嶇О") + @TableField("product_name") + private String productName; + + @ApiModelProperty("鍟嗗搧濂椾欢鍚嶇О") + @TableField("suite_name") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + @TableField("sales_form") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + @TableField("customer_type") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + @TableField("account_limit") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + @TableField("concurrent_nodes") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + @TableField("price_type") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + @TableField("price_unit") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + @TableField("unit_price") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + @TableField("quantity") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + @TableField("duration") + private Integer duration; + + @ApiModelProperty("灏忚閲戦") + @TableField("total_price") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + @TableField("provider_id") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + @TableField("provider_name") + private String providerName; + + @ApiModelProperty("澶囨敞") + @TableField("remarks") + private String remarks; + + @ApiModelProperty("娣诲姞鏃堕棿") + @TableField("add_time") + private LocalDateTime addTime; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField("update_time") + private LocalDateTime updateTime; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/OrderAttachment.java b/src/main/java/com/webmanage/entity/OrderAttachment.java new file mode 100644 index 0000000..97b406c --- /dev/null +++ b/src/main/java/com/webmanage/entity/OrderAttachment.java @@ -0,0 +1,88 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 璁㈠崟闄勪欢瀹炰綋绫� + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("order_attachment") +@ApiModel(value = "OrderAttachment", description = "璁㈠崟闄勪欢") +public class OrderAttachment { + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + @TableField("order_id") + private String orderId; + + @ApiModelProperty("闄勪欢鍚嶇О") + @TableField("file_name") + private String fileName; + + @ApiModelProperty("鍘熷鏂囦欢鍚�") + @TableField("original_name") + private String originalName; + + @ApiModelProperty("闄勪欢绫诲瀷") + @TableField("file_type") + private String fileType; + + @ApiModelProperty("闄勪欢澶у皬(瀛楄妭)") + @TableField("file_size") + private Long fileSize; + + @ApiModelProperty("闄勪欢鍦板潃") + @TableField("file_url") + private String fileUrl; + + @ApiModelProperty("鏂囦欢瀛樺偍璺緞") + @TableField("file_path") + private String filePath; + + @ApiModelProperty("MinIO瀛樺偍妗跺悕绉�") + @TableField("bucket_name") + private String bucketName; + + @ApiModelProperty("MinIO瀵硅薄鍚嶇О") + @TableField("object_name") + private String objectName; + + @ApiModelProperty("涓婁紶鐢ㄦ埛ID") + @TableField("upload_user_id") + private Long uploadUserId; + + @ApiModelProperty("涓婁紶鐢ㄦ埛鍚�") + @TableField("upload_user_name") + private String uploadUserName; + + @ApiModelProperty("闄勪欢绫诲瀷(鍚堝悓/鍙戠エ/鍏朵粬)") + @TableField("attachment_type") + private String attachmentType; + + @ApiModelProperty("闄勪欢鎻忚堪") + @TableField("description") + private String description; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/OrderDetail.java b/src/main/java/com/webmanage/entity/OrderDetail.java new file mode 100644 index 0000000..f2bb3e4 --- /dev/null +++ b/src/main/java/com/webmanage/entity/OrderDetail.java @@ -0,0 +1,105 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 璁㈠崟璇︽儏瀹炰綋绫� + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("order_detail") +@ApiModel(value = "OrderDetail", description = "璁㈠崟璇︽儏") +public class OrderDetail { + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + @TableField("order_id") + private String orderId; + + @ApiModelProperty("鍏宠仈浜у搧瀹氫环ID") + @TableField("pricing_id") + private Long pricingId; + + @ApiModelProperty("浜у搧ID") + @TableField("product_id") + private Long productId; + + @ApiModelProperty("浜у搧濂椾欢鍚嶇О") + @TableField("suite_name") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + @TableField("sales_form") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + @TableField("customer_type") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + @TableField("account_limit") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + @TableField("concurrent_nodes") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + @TableField("price_type") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + @TableField("price_unit") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + @TableField("unit_price") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + @TableField("quantity") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + @TableField("duration") + private Integer duration; + + @ApiModelProperty("灏忚閲戦") + @TableField("total_price") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + @TableField("provider_id") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + @TableField("provider_name") + private String providerName; + + @ApiModelProperty("澶囨敞") + @TableField("remarks") + private String remarks; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/OrderEvaluation.java b/src/main/java/com/webmanage/entity/OrderEvaluation.java new file mode 100644 index 0000000..9ae5922 --- /dev/null +++ b/src/main/java/com/webmanage/entity/OrderEvaluation.java @@ -0,0 +1,88 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 璁㈠崟璇勪环瀹炰綋绫� + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("order_evaluation") +@ApiModel(value = "OrderEvaluation", description = "璁㈠崟璇勪环") +public class OrderEvaluation { + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + @TableField("order_id") + private String orderId; + + @ApiModelProperty("璇勪环浜篒D") + @TableField("evaluator_id") + private Long evaluatorId; + + @ApiModelProperty("璇勪环浜哄鍚�") + @TableField("evaluator_name") + private String evaluatorName; + + @ApiModelProperty("璇勪环浜虹被鍨�") + @TableField("evaluator_type") + private String evaluatorType; + + @ApiModelProperty("璇勪环鍐呭") + @TableField("content") + private String content; + + @ApiModelProperty("璇勫垎(1-5)") + @TableField("rating") + private Integer rating; + + @ApiModelProperty("鏈嶅姟璇勫垎") + @TableField("service_rating") + private Integer serviceRating; + + @ApiModelProperty("璐ㄩ噺璇勫垎") + @TableField("quality_rating") + private Integer qualityRating; + + @ApiModelProperty("浜や粯璇勫垎") + @TableField("delivery_rating") + private Integer deliveryRating; + + @ApiModelProperty("鏄惁鍖垮悕璇勪环") + @TableField("is_anonymous") + private Boolean isAnonymous; + + @ApiModelProperty("鍥炲鍐呭") + @TableField("reply_content") + private String replyContent; + + @ApiModelProperty("鍥炲鐢ㄦ埛ID") + @TableField("reply_user_id") + private Long replyUserId; + + @ApiModelProperty("鍥炲鏃堕棿") + @TableField("reply_time") + private LocalDateTime replyTime; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/OrderInfo.java b/src/main/java/com/webmanage/entity/OrderInfo.java new file mode 100644 index 0000000..6ab5947 --- /dev/null +++ b/src/main/java/com/webmanage/entity/OrderInfo.java @@ -0,0 +1,144 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 璁㈠崟淇℃伅瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("order_info") +public class OrderInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 璁㈠崟缂栧彿 + */ + @TableId(value = "order_id", type = IdType.INPUT) + private String orderId; + + /** + * 浜у搧ID + */ + @TableField("product_id") + private Long productId; + + /** + * 鐢ㄦ埛ID + */ + @TableField("user_id") + private Long userId; + + /** + * 鍗曚綅ID + */ + @TableField("unit_id") + private Long unitId; + + /** + * 浜у搧鍚嶇О + */ + @TableField("product_name") + private String productName; + + /** + * 浜у搧鎻愪緵鑰呭悕绉� + */ + @TableField("provider_name") + private String providerName; + + /** + * 鎻愪緵鑰匢D + */ + @TableField("provider_id") + private Long providerId; + + /** + * 鐢宠鏃堕棿 + */ + @TableField("apply_time") + private LocalDateTime applyTime; + + /** + * 璁㈠崟鐘舵�� + */ + @TableField("order_status") + private String orderStatus; + + /** + * 璁㈠崟鎬婚噾棰� + */ + @TableField("total_amount") + private BigDecimal totalAmount; + + /** + * 鏀粯鏂瑰紡 + */ + @TableField("payment_type") + private String paymentType; + + /** + * 鏀粯鐘舵�� + */ + @TableField("payment_status") + private String paymentStatus; + + /** + * 宸ヤ綔娴両D + */ + @TableField("workflow_id") + private String workflowId; + + /** + * 褰撳墠瀹℃壒姝ラ + */ + @TableField("current_step") + private String currentStep; + + /** + * 瀹℃壒娴佺▼閰嶇疆 + */ + @TableField("approval_flow") + private String approvalFlow; + + /** + * 涔板澶囨敞 + */ + @TableField("buyer_remarks") + private String buyerRemarks; + + /** + * 鍗栧澶囨敞 + */ + @TableField("seller_remarks") + private String sellerRemarks; + + /** + * 鍒涘缓鏃堕棿 + */ + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 鏇存柊鏃堕棿 + */ + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + /** + * 閫昏緫鍒犻櫎 + */ + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/Points.java b/src/main/java/com/webmanage/entity/Points.java new file mode 100644 index 0000000..40a6f3f --- /dev/null +++ b/src/main/java/com/webmanage/entity/Points.java @@ -0,0 +1,73 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 绉垎涓昏〃瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("points") +@ApiModel(value = "Points", description = "绉垎涓昏〃") +public class Points implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("绉垎瑙勫垯鍚嶇О") + @TableField("points_name") + private String pointsName; + + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�") + @TableField("effective_start") +// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime effectiveStart; + + + @ApiModelProperty("淇敼浜篒D") + @TableField("modifier_id") + private Long modifierId; + + @ApiModelProperty("淇敼浜哄鍚�") + @TableField("modifier_name") + private String modifierName; + + @ApiModelProperty("鐗堟湰鍙�") + @TableField("version") + @JsonFormat(shape= JsonFormat.Shape.STRING) + private float version; + + + + @ApiModelProperty("鐘舵��") + @TableField("status") + private int status; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎") + @TableLogic + @TableField("deleted") + private Integer deleted; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/entity/PointsFlow.java b/src/main/java/com/webmanage/entity/PointsFlow.java new file mode 100644 index 0000000..0066883 --- /dev/null +++ b/src/main/java/com/webmanage/entity/PointsFlow.java @@ -0,0 +1,89 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 绉垎娴佹按瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("points_flow") +public class PointsFlow implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 涓婚敭ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 鐢ㄦ埛ID + */ + @TableField("user_id") + private Long userId; + + /** + * 鍗曚綅ID + */ + @TableField("unit_id") + private Long unitId; + + /** + * 鏁版嵁绫荤洰 + */ + @TableField("data_category") + private String dataCategory; + + /** + * 鏁版嵁绫诲瀷 + */ + @TableField("data_type") + private String dataType; + + /** + * 鍚嶇О/鎻忚堪 + */ + @TableField("name") + private String name; + + /** + * 绉垎鍊� + */ + @TableField("points") + private Integer points; + + /** + * 娴佹按鏃堕棿 + */ + @TableField("flow_time") + private LocalDateTime flowTime; + + /** + * 鍒涘缓鏃堕棿 + */ + @TableField(value = "create_time", fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 鏇存柊鏃堕棿 + */ + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄� + */ + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/PointsRule.java b/src/main/java/com/webmanage/entity/PointsRule.java new file mode 100644 index 0000000..0a9a8a1 --- /dev/null +++ b/src/main/java/com/webmanage/entity/PointsRule.java @@ -0,0 +1,83 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 绉垎瑙勫垯瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("points_rule") +@ApiModel(value = "PointsRule", description = "绉垎瑙勫垯") +public class PointsRule implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("瑙勫垯鍚嶇О") + @TableField("rule_name") + private String ruleName; + + @ApiModelProperty("瑙勫垯绫诲瀷(鑾峰緱/娑堣垂)") + @TableField("rule_type") + private String ruleType; + + @ApiModelProperty("绉垎鍊�") + @TableField("points_value") + private Integer pointsValue; + + @ApiModelProperty("瑙﹀彂鏉′欢") + @TableField("trigger_condition") + private String triggerCondition; + + @ApiModelProperty("瑙﹀彂閲戦") + @TableField("trigger_amount") + private BigDecimal triggerAmount; + + @ApiModelProperty("瑙勫垯鎻忚堪") + @TableField("rule_description") + private String ruleDescription; + + @ApiModelProperty("鏄惁鍚敤") + @TableField("is_enabled") + private Boolean isEnabled; + + @ApiModelProperty("浼樺厛绾�") + @TableField("priority") + private Integer priority; + + @ApiModelProperty("鏈夋晥鏈熷紑濮嬫椂闂�") + @TableField("valid_start_time") + private LocalDateTime validStartTime; + + @ApiModelProperty("鏈夋晥鏈熺粨鏉熸椂闂�") + @TableField("valid_end_time") + private LocalDateTime validEndTime; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�") + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/PointsRuleDetail.java b/src/main/java/com/webmanage/entity/PointsRuleDetail.java new file mode 100644 index 0000000..15025d9 --- /dev/null +++ b/src/main/java/com/webmanage/entity/PointsRuleDetail.java @@ -0,0 +1,87 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 绉垎瑙勫垯璇︽儏瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("points_rule_detail") +@ApiModel(value = "PointsRuleDetail", description = "绉垎瑙勫垯璇︽儏") +public class PointsRuleDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈绉垎瑙勫垯ID") + @TableField("rule_id") + private Long ruleId; + + @ApiModelProperty("鍏宠仈绉垎ID") + @TableField("points_id") + private Long pointsId; + + @ApiModelProperty("绉垎鍊�") + @TableField("points_value") + private Integer pointsValue; + + @ApiModelProperty("姣忔棩绉垎涓婇檺鍊�") + @TableField("daily_limit") + private Integer dailyLimit; + + @ApiModelProperty("姣忔湀绉垎涓婇檺鍊�") + @TableField("monthly_limit") + private Integer monthlyLimit; + + @ApiModelProperty("姣忓勾绉垎涓婇檺鍊�") + @TableField("yearly_limit") + private Integer yearlyLimit; + + @ApiModelProperty("鏈�灏忓��") + @TableField("min_value") + private Integer minValue; + + @ApiModelProperty("鏈�澶у��") + @TableField("max_value") + private Integer maxValue; + + @ApiModelProperty("杞崲姣旂巼") + @TableField("conversion_rate") + private BigDecimal conversionRate; + + @ApiModelProperty("鐢熸晥寮�濮嬫椂闂�") + @TableField("effective_start") + private LocalDateTime effectiveStart; + + @ApiModelProperty("鐢熸晥缁撴潫鏃堕棿") + @TableField("effective_end") + private LocalDateTime effectiveEnd; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎") + @TableLogic + @TableField("deleted") + private Integer deleted; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/entity/PointsRuleEntity.java b/src/main/java/com/webmanage/entity/PointsRuleEntity.java new file mode 100644 index 0000000..6245c1d --- /dev/null +++ b/src/main/java/com/webmanage/entity/PointsRuleEntity.java @@ -0,0 +1,66 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 绉垎瑙勫垯琛ㄥ疄浣� + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("points_rule") +@ApiModel(value = "PointsRuleEntity", description = "绉垎瑙勫垯") +public class PointsRuleEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("涓婚敭ID") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("鍏宠仈绉垎ID") + @TableField("points_id") + private Long pointsId; + + @ApiModelProperty("绉垎瑙勫垯绫诲瀷") + @TableField("rule_type") + private String ruleType; + + @ApiModelProperty("绉垎绫诲埆") + @TableField("category") + private String category; + + @ApiModelProperty("瑙勫垯鍚嶇О") + @TableField("rule_name") + private String ruleName; + + @ApiModelProperty("瑙勫垯鎻忚堪") + @TableField("rule_description") + private String ruleDescription; + + @ApiModelProperty("瑙勫垯鐘舵��") + @TableField("status") + private String status; + + @ApiModelProperty("鍒涘缓鏃堕棿") + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + @ApiModelProperty("閫昏緫鍒犻櫎") + @TableLogic + @TableField("deleted") + private Integer deleted; +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/entity/ProductPricing.java b/src/main/java/com/webmanage/entity/ProductPricing.java new file mode 100644 index 0000000..7c61271 --- /dev/null +++ b/src/main/java/com/webmanage/entity/ProductPricing.java @@ -0,0 +1,144 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 浜у搧瀹氫环瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("product_pricing") +public class ProductPricing implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 涓婚敭ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 浜у搧濂椾欢鍚嶇О + */ + @TableField("suite_name") + private String suiteName; + + /** + * 閿�鍞舰寮� + */ + @TableField("sales_form") + private String salesForm; + + /** + * 瀹㈡埛瀵硅薄 + */ + @TableField("customer_type") + private String customerType; + + /** + * 璐︽埛鏁伴噺 + */ + @TableField("account_limit") + private String accountLimit; + + /** + * 骞跺彂鑺傜偣鏁� + */ + @TableField("concurrent_nodes") + private String concurrentNodes; + + /** + * 浠锋牸璁剧疆 + */ + @TableField("price_type") + private String priceType; + + /** + * 浠锋牸鍗曚綅 + */ + @TableField("price_unit") + private String priceUnit; + + /** + * 浠锋牸鍊� + */ + @TableField("price") + private BigDecimal price; + + /** + * 鍚敤鐘舵�� + */ + @TableField("is_active") + private Boolean isActive; + + /** + * 鍏宠仈浜у搧ID + */ + @TableField("product_id") + private Long productId; + + /** + * 浜у搧鍚嶇О + */ + @TableField("product_name") + private String productName; + + /** + * 浜у搧鎻愪緵鑰匢D + */ + @TableField("provider_id") + private Long providerId; + + /** + * 浜у搧鎻愪緵鑰呭悕绉� + */ + @TableField("provider_name") + private String providerName; + + /** + * 浜у搧鎻忚堪 + */ + @TableField("description") + private String description; + + /** + * 鍒涘缓鏃堕棿 + */ + @TableField(value = "created_at", fill = FieldFill.INSERT) + private LocalDateTime createdAt; + + /** + * 鏇存柊鏃堕棿 + */ + @TableField(value = "updated_at", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updatedAt; + + /** + * 鍒涘缓浜篒D + */ + @TableField("created_by") + private Long createdBy; + + /** + * 鏇存柊浜篒D + */ + @TableField("updated_by") + private Long updatedBy; + + /** + * 閫昏緫鍒犻櫎 + */ + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/entity/UserPoints.java b/src/main/java/com/webmanage/entity/UserPoints.java new file mode 100644 index 0000000..5448b71 --- /dev/null +++ b/src/main/java/com/webmanage/entity/UserPoints.java @@ -0,0 +1,83 @@ +package com.webmanage.entity; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 鐢ㄦ埛绉垎瀹炰綋 + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("user_points") +public class UserPoints implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 涓婚敭ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 鐢ㄦ埛ID + */ + @TableField("user_id") + private Long userId; + + /** + * 鍗曚綅ID + */ + @TableField("unit_id") + private Long unitId; + + /** + * 绉垎浣欓 + */ + @TableField("balance") + private Integer balance; + + /** + * 绱鑾峰彇绉垎 + */ + @TableField("total_earned") + private Integer totalEarned; + + /** + * 绱娑堣�楃Н鍒� + */ + @TableField("total_consumed") + private Integer totalConsumed; + + /** + * 绱杞崲绉垎 + */ + @TableField("total_converted") + private Integer totalConverted; + + /** + * 鍒涘缓鏃堕棿 + */ + @TableField(value = "create_time", fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 鏇存柊鏃堕棿 + */ + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄� + */ + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/webmanage/mapper/ApprovalRecordMapper.java b/src/main/java/com/webmanage/mapper/ApprovalRecordMapper.java new file mode 100644 index 0000000..35dea0d --- /dev/null +++ b/src/main/java/com/webmanage/mapper/ApprovalRecordMapper.java @@ -0,0 +1,51 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.entity.ApprovalRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 瀹℃壒璁板綍Mapper鎺ュ彛 + */ +@Mapper +public interface ApprovalRecordMapper extends BaseMapper<ApprovalRecord> { + + /** + * 鍒嗛〉鏌ヨ瀹℃壒璁板綍 + */ + IPage<ApprovalRecord> selectApprovalRecordPage(Page<ApprovalRecord> page, + @Param("orderId") String orderId, + @Param("productName") String productName, + @Param("providerName") String providerName, + @Param("approverId") Long approverId, + @Param("approvalResult") String approvalResult, + @Param("approvalStep") String approvalStep, + @Param("needAuthorization") Boolean needAuthorization, + @Param("applyTimeStart") String applyTimeStart, + @Param("applyTimeEnd") String applyTimeEnd, + @Param("approvalTimeStart") String approvalTimeStart, + @Param("approvalTimeEnd") String approvalTimeEnd, + @Param("orderBy") String orderBy, + @Param("orderDirection") String orderDirection); + + /** + * 鏍规嵁璁㈠崟ID鏌ヨ瀹℃壒璁板綍 + */ + List<ApprovalRecord> selectByOrderId(@Param("orderId") String orderId); + + /** + * 鏌ヨ寰呭鎵圭殑璁㈠崟 + */ + IPage<ApprovalRecord> selectPendingApprovalPage(Page<ApprovalRecord> page, + @Param("orderId") String orderId, + @Param("productName") String productName, + @Param("providerName") String providerName, + @Param("approvalStep") String approvalStep, + @Param("orderBy") String orderBy, + @Param("orderDirection") String orderDirection); +} diff --git a/src/main/java/com/webmanage/mapper/CartMapper.java b/src/main/java/com/webmanage/mapper/CartMapper.java new file mode 100644 index 0000000..76abe93 --- /dev/null +++ b/src/main/java/com/webmanage/mapper/CartMapper.java @@ -0,0 +1,35 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.Cart; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 璐墿杞apper鎺ュ彛 + */ +@Mapper +public interface CartMapper extends BaseMapper<Cart> { + + /** + * 鏍规嵁鐢ㄦ埛ID鍜屽崟浣岻D鏌ヨ璐墿杞﹀晢鍝佸垪琛� + */ + List<Cart> selectByUserIdAndUnitId(@Param("userId") Long userId, @Param("unitId") Long unitId); + + /** + * 鏍规嵁鐢ㄦ埛ID銆佸崟浣岻D鍜屽畾浠稩D鏌ヨ璐墿杞﹀晢鍝� + */ + Cart selectByUserIdUnitIdAndPricingId(@Param("userId") Long userId, @Param("unitId") Long unitId, @Param("pricingId") Long pricingId); + + /** + * 鏍规嵁鐢ㄦ埛ID鍜屽崟浣岻D缁熻璐墿杞﹀晢鍝佹暟閲� + */ + Integer countByUserIdAndUnitId(@Param("userId") Long userId, @Param("unitId") Long unitId); + + /** + * 鏍规嵁鐢ㄦ埛ID鍜屽崟浣岻D璁$畻璐墿杞︽�婚噾棰� + */ + java.math.BigDecimal sumTotalAmountByUserIdAndUnitId(@Param("userId") Long userId, @Param("unitId") Long unitId); +} diff --git a/src/main/java/com/webmanage/mapper/OrderAttachmentMapper.java b/src/main/java/com/webmanage/mapper/OrderAttachmentMapper.java new file mode 100644 index 0000000..e10675b --- /dev/null +++ b/src/main/java/com/webmanage/mapper/OrderAttachmentMapper.java @@ -0,0 +1,20 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.OrderAttachment; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 璁㈠崟闄勪欢Mapper鎺ュ彛 + */ +@Mapper +public interface OrderAttachmentMapper extends BaseMapper<OrderAttachment> { + + /** + * 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟闄勪欢鍒楄〃 + */ + List<OrderAttachment> selectByOrderId(@Param("orderId") String orderId); +} diff --git a/src/main/java/com/webmanage/mapper/OrderDetailMapper.java b/src/main/java/com/webmanage/mapper/OrderDetailMapper.java new file mode 100644 index 0000000..02df4af --- /dev/null +++ b/src/main/java/com/webmanage/mapper/OrderDetailMapper.java @@ -0,0 +1,20 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.OrderDetail; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 璁㈠崟璇︽儏Mapper鎺ュ彛 + */ +@Mapper +public interface OrderDetailMapper extends BaseMapper<OrderDetail> { + + /** + * 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟璇︽儏鍒楄〃 + */ + List<OrderDetail> selectByOrderId(@Param("orderId") String orderId); +} diff --git a/src/main/java/com/webmanage/mapper/OrderEvaluationMapper.java b/src/main/java/com/webmanage/mapper/OrderEvaluationMapper.java new file mode 100644 index 0000000..217f070 --- /dev/null +++ b/src/main/java/com/webmanage/mapper/OrderEvaluationMapper.java @@ -0,0 +1,18 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.OrderEvaluation; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 璁㈠崟璇勪环Mapper鎺ュ彛 + */ +@Mapper +public interface OrderEvaluationMapper extends BaseMapper<OrderEvaluation> { + + /** + * 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟璇勪环 + */ + OrderEvaluation selectByOrderId(@Param("orderId") String orderId); +} diff --git a/src/main/java/com/webmanage/mapper/OrderInfoMapper.java b/src/main/java/com/webmanage/mapper/OrderInfoMapper.java new file mode 100644 index 0000000..e019bcb --- /dev/null +++ b/src/main/java/com/webmanage/mapper/OrderInfoMapper.java @@ -0,0 +1,46 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.entity.OrderInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 璁㈠崟淇℃伅Mapper鎺ュ彛 + */ +@Mapper +public interface OrderInfoMapper extends BaseMapper<OrderInfo> { + + /** + * 鍒嗛〉鏌ヨ涔板璁㈠崟鍒楄〃 + */ + IPage<OrderInfo> selectBuyerOrderPage(Page<OrderInfo> page, @Param("userId") Long userId, + @Param("unitId") Long unitId, @Param("orderStatus") String orderStatus, + @Param("paymentStatus") String paymentStatus, @Param("paymentType") String paymentType, + @Param("productName") String productName, @Param("providerName") String providerName, + @Param("orderId") String orderId, @Param("applyTimeStart") String applyTimeStart, + @Param("applyTimeEnd") String applyTimeEnd, @Param("createTimeStart") String createTimeStart, + @Param("createTimeEnd") String createTimeEnd, @Param("orderBy") String orderBy, + @Param("orderDirection") String orderDirection); + + /** + * 鍒嗛〉鏌ヨ鍗栧璁㈠崟鍒楄〃 + */ + IPage<OrderInfo> selectSellerOrderPage(Page<OrderInfo> page, @Param("providerId") Long providerId, + @Param("orderStatus") String orderStatus, @Param("paymentStatus") String paymentStatus, + @Param("productName") String productName, @Param("orderId") String orderId, + @Param("applyTimeStart") String applyTimeStart, @Param("applyTimeEnd") String applyTimeEnd, + @Param("createTimeStart") String createTimeStart, @Param("createTimeEnd") String createTimeEnd, + @Param("orderBy") String orderBy, @Param("orderDirection") String orderDirection); + + /** + * 鍒嗛〉鏌ヨ寰呭鎵硅鍗曞垪琛� + */ + IPage<OrderInfo> selectPendingApprovalOrderPage(Page<OrderInfo> page, @Param("orderStatus") String orderStatus, + @Param("productName") String productName, @Param("providerName") String providerName, + @Param("orderId") String orderId, @Param("applyTimeStart") String applyTimeStart, + @Param("applyTimeEnd") String applyTimeEnd, @Param("orderBy") String orderBy, + @Param("orderDirection") String orderDirection); +} diff --git a/src/main/java/com/webmanage/mapper/PointsFlowMapper.java b/src/main/java/com/webmanage/mapper/PointsFlowMapper.java new file mode 100644 index 0000000..71d0e43 --- /dev/null +++ b/src/main/java/com/webmanage/mapper/PointsFlowMapper.java @@ -0,0 +1,32 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.entity.PointsFlow; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 绉垎娴佹按Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface PointsFlowMapper extends BaseMapper<PointsFlow> { + + /** + * 鍒嗛〉鏌ヨ绉垎娴佹按 + */ + IPage<PointsFlow> selectPage(Page<PointsFlow> page, + @Param("userId") Long userId, + @Param("unitId") Long unitId, + @Param("dataCategory") String dataCategory, + @Param("dataType") String dataType, + @Param("startTime") String startTime, + @Param("endTime") String endTime, + @Param("year") String year, + @Param("month") String month, + @Param("day") String day); +} diff --git a/src/main/java/com/webmanage/mapper/PointsMapper.java b/src/main/java/com/webmanage/mapper/PointsMapper.java new file mode 100644 index 0000000..34473bf --- /dev/null +++ b/src/main/java/com/webmanage/mapper/PointsMapper.java @@ -0,0 +1,24 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.dto.PointsMainQueryDTO; +import com.webmanage.entity.Points; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 绉垎涓昏〃Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface PointsMapper extends BaseMapper<Points> { + + /** + * 鍒嗛〉鏌ヨ绉垎涓昏〃 + */ + IPage<Points> selectPointsMainPage(Page<Points> page, @Param("queryDTO") PointsMainQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/mapper/PointsRuleDetailMapper.java b/src/main/java/com/webmanage/mapper/PointsRuleDetailMapper.java new file mode 100644 index 0000000..0830499 --- /dev/null +++ b/src/main/java/com/webmanage/mapper/PointsRuleDetailMapper.java @@ -0,0 +1,15 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.PointsRuleDetail; +import org.apache.ibatis.annotations.Mapper; + +/** + * 绉垎瑙勫垯璇︽儏Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface PointsRuleDetailMapper extends BaseMapper<PointsRuleDetail> { +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/mapper/PointsRuleMapper.java b/src/main/java/com/webmanage/mapper/PointsRuleMapper.java new file mode 100644 index 0000000..22a5edf --- /dev/null +++ b/src/main/java/com/webmanage/mapper/PointsRuleMapper.java @@ -0,0 +1,15 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.PointsRule; +import org.apache.ibatis.annotations.Mapper; + +/** + * 绉垎瑙勫垯Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface PointsRuleMapper extends BaseMapper<PointsRule> { +} diff --git a/src/main/java/com/webmanage/mapper/ProductPricingMapper.java b/src/main/java/com/webmanage/mapper/ProductPricingMapper.java new file mode 100644 index 0000000..19e467b --- /dev/null +++ b/src/main/java/com/webmanage/mapper/ProductPricingMapper.java @@ -0,0 +1,39 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.webmanage.entity.ProductPricing; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 浜у搧瀹氫环Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface ProductPricingMapper extends BaseMapper<ProductPricing> { + + /** + * 鍒嗛〉鏌ヨ浜у搧瀹氫环鍒楄〃 + */ + IPage<ProductPricing> selectProductPricingPage(Page<ProductPricing> page, @Param("productId") Long productId); + + /** + * 鏍规嵁浜у搧ID鏌ヨ瀹氫环鍒楄〃 + */ + List<ProductPricing> selectByProductId(@Param("productId") Long productId); + + /** + * 鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环 + */ + List<ProductPricing> selectByCondition(@Param("suiteName") String suiteName, + @Param("salesForm") String salesForm, + @Param("customerType") String customerType, + @Param("priceType") String priceType, + @Param("isActive") Boolean isActive); +} diff --git a/src/main/java/com/webmanage/mapper/UserPointsMapper.java b/src/main/java/com/webmanage/mapper/UserPointsMapper.java new file mode 100644 index 0000000..183ad79 --- /dev/null +++ b/src/main/java/com/webmanage/mapper/UserPointsMapper.java @@ -0,0 +1,26 @@ +package com.webmanage.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.webmanage.entity.UserPoints; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 鐢ㄦ埛绉垎Mapper鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +@Mapper +public interface UserPointsMapper extends BaseMapper<UserPoints> { + + /** + * 鏍规嵁鐢ㄦ埛ID鏌ヨ绉垎淇℃伅 + */ + UserPoints selectByUserId(@Param("userId") Long userId); + + /** + * 鏍规嵁鍗曚綅ID鏌ヨ绉垎淇℃伅 + */ + UserPoints selectByUnitId(@Param("unitId") Long unitId); +} diff --git a/src/main/java/com/webmanage/service/ApprovalRecordService.java b/src/main/java/com/webmanage/service/ApprovalRecordService.java new file mode 100644 index 0000000..0f4f11c --- /dev/null +++ b/src/main/java/com/webmanage/service/ApprovalRecordService.java @@ -0,0 +1,45 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.common.PageResult; +import com.webmanage.dto.ApprovalActionDTO; +import com.webmanage.dto.ApprovalQueryDTO; +import com.webmanage.entity.ApprovalRecord; + +import java.util.List; + +/** + * 瀹℃壒璁板綍Service鎺ュ彛 + */ +public interface ApprovalRecordService extends IService<ApprovalRecord> { + + /** + * 鍒嗛〉鏌ヨ瀹℃壒璁板綍 + */ + PageResult<ApprovalRecord> getApprovalRecordPage(ApprovalQueryDTO queryDTO); + + /** + * 鍒嗛〉鏌ヨ寰呭鎵硅鍗� + */ + PageResult<ApprovalRecord> getPendingApprovalPage(ApprovalQueryDTO queryDTO); + + /** + * 鏍规嵁璁㈠崟ID鏌ヨ瀹℃壒璁板綍 + */ + List<ApprovalRecord> getApprovalRecordsByOrderId(String orderId); + + /** + * 瀹℃壒璁㈠崟 + */ + boolean approveOrder(ApprovalActionDTO actionDTO); + + /** + * 鎺堟潈瀹℃壒 + */ + boolean authorizeApproval(Long approvalId, Long authorizerId, String authorizerName, String authorizationOpinion); + + /** + * 鑾峰彇璁㈠崟褰撳墠瀹℃壒鐘舵�� + */ + String getOrderCurrentApprovalStatus(String orderId); +} diff --git a/src/main/java/com/webmanage/service/CartService.java b/src/main/java/com/webmanage/service/CartService.java new file mode 100644 index 0000000..58a08bb --- /dev/null +++ b/src/main/java/com/webmanage/service/CartService.java @@ -0,0 +1,73 @@ +package com.webmanage.service; + +import com.webmanage.dto.CartItemDTO; +import com.webmanage.dto.CartQueryDTO; +import com.webmanage.vo.CartVO; +import com.webmanage.vo.CartItemVO; + +import java.util.List; + +/** + * 璐墿杞︽湇鍔℃帴鍙� + */ +public interface CartService { + /** + * 娣诲姞鍟嗗搧鍒拌喘鐗╄溅锛圧edis + 鏁版嵁搴擄級 + */ + boolean addToCart(Long userId, Long unitId, CartItemDTO cartItemDTO); + + /** + * 浠庤喘鐗╄溅绉婚櫎鍟嗗搧锛圧edis + 鏁版嵁搴擄級 + */ + boolean removeFromCart(Long userId, Long unitId, Long pricingId); + + /** + * 鏇存柊璐墿杞﹀晢鍝佹暟閲忥紙Redis + 鏁版嵁搴擄級 + */ + boolean updateCartItemQuantity(Long userId, Long unitId, Long pricingId, Integer quantity); + + /** + * 娓呯┖璐墿杞︼紙Redis + 鏁版嵁搴擄級 + */ + boolean clearCart(Long userId, Long unitId); + + /** + * 鑾峰彇璐墿杞︿俊鎭紙浼樺厛Redis锛屽け璐ュ垯浠庢暟鎹簱鍔犺浇锛� + */ + CartVO getCart(Long userId, Long unitId); + + /** + * 鑾峰彇璐墿杞﹀晢鍝佸垪琛紙浼樺厛Redis锛屽け璐ュ垯浠庢暟鎹簱鍔犺浇锛� + */ + List<CartItemVO> getCartItems(Long userId, Long unitId); + + /** + * 妫�鏌ヨ喘鐗╄溅鍟嗗搧搴撳瓨 + */ + boolean checkCartItemStock(Long userId, Long unitId, Long pricingId); + + /** + * 鎵归噺鍒犻櫎璐墿杞﹀晢鍝侊紙Redis + 鏁版嵁搴擄級 + */ + boolean batchRemoveFromCart(Long userId, Long unitId, List<Long> pricingIds); + + /** + * 鑾峰彇璐墿杞﹀晢鍝佹暟閲忥紙浼樺厛Redis锛屽け璐ュ垯浠庢暟鎹簱鍔犺浇锛� + */ + Integer getCartItemCount(Long userId, Long unitId); + + /** + * 浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹埌Redis + */ + boolean loadCartFromDatabase(Long userId, Long unitId); + + /** + * 鍚屾Redis鏁版嵁鍒版暟鎹簱 + */ + boolean syncCartToDatabase(Long userId, Long unitId); + + /** + * 妫�鏌ヨ喘鐗╄溅鏁版嵁涓�鑷存�� + */ + boolean checkCartConsistency(Long userId, Long unitId); +} diff --git a/src/main/java/com/webmanage/service/MinioService.java b/src/main/java/com/webmanage/service/MinioService.java new file mode 100644 index 0000000..62099c9 --- /dev/null +++ b/src/main/java/com/webmanage/service/MinioService.java @@ -0,0 +1,151 @@ +package com.webmanage.service; + +import com.webmanage.common.FileUploadException; +import com.webmanage.config.MinioConfig; +import io.minio.*; +import io.minio.http.Method; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * MinIO鏈嶅姟绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@Slf4j +@Service +public class MinioService { + + @Autowired + private MinioClient minioClient; + + @Autowired + private MinioConfig minioConfig; + + /** + * 涓婁紶鏂囦欢 + */ + public String uploadFile(MultipartFile file, String folder) { + try { + // 妫�鏌ュ瓨鍌ㄦ《鏄惁瀛樺湪锛屼笉瀛樺湪鍒欏垱寤� + boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder() + .bucket(minioConfig.getBucketName()) + .build()); + + if (!bucketExists) { + minioClient.makeBucket(MakeBucketArgs.builder() + .bucket(minioConfig.getBucketName()) + .build()); + } + + // 鐢熸垚鏂囦欢鍚� + String originalFilename = file.getOriginalFilename(); + String fileExtension = ""; + if (originalFilename != null && originalFilename.contains(".")) { + fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); + } + String fileName = folder + "/" + UUID.randomUUID().toString() + fileExtension; + + // 涓婁紶鏂囦欢 + minioClient.putObject(PutObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .stream(file.getInputStream(), file.getSize(), -1) + .contentType(file.getContentType()) + .build()); + + log.info("鏂囦欢涓婁紶鎴愬姛: {}", fileName); + return fileName; + } catch (Exception e) { + log.error("鏂囦欢涓婁紶澶辫触: ", e); + throw new FileUploadException("鏂囦欢涓婁紶澶辫触: " + e.getMessage()); + } + } + + /** + * 涓嬭浇鏂囦欢 + */ + public InputStream downloadFile(String fileName) { + try { + return minioClient.getObject(GetObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .build()); + } catch (Exception e) { + log.error("鏂囦欢涓嬭浇澶辫触: ", e); + throw new FileUploadException("鏂囦欢涓嬭浇澶辫触: " + e.getMessage()); + } + } + + /** + * 鍒犻櫎鏂囦欢 + */ + public void deleteFile(String fileName) { + try { + minioClient.removeObject(RemoveObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .build()); + log.info("鏂囦欢鍒犻櫎鎴愬姛: {}", fileName); + } catch (Exception e) { + log.error("鏂囦欢鍒犻櫎澶辫触: ", e); + throw new FileUploadException("鏂囦欢鍒犻櫎澶辫触: " + e.getMessage()); + } + } + + /** + * 鐢熸垚鏂囦欢棰勮URL + */ + public String getPreviewUrl(String fileName) { + try { + return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + .method(Method.GET) + .bucket(minioConfig.getBucketName()) + .object(fileName) + .expiry(1, TimeUnit.HOURS) + .build()); + } catch (Exception e) { + log.error("鐢熸垚棰勮URL澶辫触: ", e); + throw new FileUploadException("鐢熸垚棰勮URL澶辫触: " + e.getMessage()); + } + } + + /** + * 鐢熸垚鏂囦欢涓嬭浇URL + */ + public String getDownloadUrl(String fileName) { + try { + return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + .method(Method.GET) + .bucket(minioConfig.getBucketName()) + .object(fileName) + .expiry(24, TimeUnit.HOURS) + .build()); + } catch (Exception e) { + log.error("鐢熸垚涓嬭浇URL澶辫触: ", e); + throw new FileUploadException("鐢熸垚涓嬭浇URL澶辫触: " + e.getMessage()); + } + } + + /** + * 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦� + */ + public boolean fileExists(String fileName) { + try { + minioClient.statObject(StatObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .build()); + return true; + } catch (Exception e) { + return false; + } + } +} diff --git a/src/main/java/com/webmanage/service/OrderInfoService.java b/src/main/java/com/webmanage/service/OrderInfoService.java new file mode 100644 index 0000000..8e85fc7 --- /dev/null +++ b/src/main/java/com/webmanage/service/OrderInfoService.java @@ -0,0 +1,65 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.common.PageResult; +import com.webmanage.dto.CreateOrderDTO; +import com.webmanage.dto.OrderQueryDTO; +import com.webmanage.entity.OrderInfo; +import com.webmanage.vo.OrderDetailVO; + +/** + * 璁㈠崟淇℃伅Service鎺ュ彛 + */ +public interface OrderInfoService extends IService<OrderInfo> { + + /** + * 鍒嗛〉鏌ヨ涔板璁㈠崟鍒楄〃 + */ + PageResult<OrderInfo> getBuyerOrderPage(OrderQueryDTO queryDTO); + + /** + * 鍒嗛〉鏌ヨ鍗栧璁㈠崟鍒楄〃 + */ + PageResult<OrderInfo> getSellerOrderPage(OrderQueryDTO queryDTO); + + /** + * 鍒嗛〉鏌ヨ寰呭鎵硅鍗曞垪琛� + */ + PageResult<OrderInfo> getPendingApprovalOrderPage(OrderQueryDTO queryDTO); + + /** + * 鑾峰彇璁㈠崟璇︽儏 + */ + OrderDetailVO getOrderDetail(String orderId); + + /** + * 鍒涘缓璁㈠崟锛堝寘鍚鍗曞ご涓庢槑缁嗘彃鍏ワ級锛岃繑鍥炶鍗曠紪鍙� + */ + String createOrder(CreateOrderDTO createOrderDTO); + + /** + * 涓婁紶璁㈠崟闄勪欢 + */ + boolean uploadOrderAttachment(String orderId, String fileName, String originalName, + String fileType, Long fileSize, String fileUrl, + String bucketName, String objectName, Long uploadUserId, + String uploadUserName, String attachmentType, String description); + + /** + * 娣诲姞璁㈠崟璇勪环 + */ + boolean addOrderEvaluation(String orderId, Long evaluatorId, String evaluatorName, + String evaluatorType, String content, Integer rating, + Integer serviceRating, Integer qualityRating, Integer deliveryRating, + Boolean isAnonymous); + + /** + * 浜ゆ槗纭 + */ + boolean confirmTransaction(String orderId, Long userId); + + /** + * 鍥炲璇勪环 + */ + boolean replyEvaluation(Long evaluationId, String replyContent, Long replyUserId); +} diff --git a/src/main/java/com/webmanage/service/OrderNoService.java b/src/main/java/com/webmanage/service/OrderNoService.java new file mode 100644 index 0000000..5a8b248 --- /dev/null +++ b/src/main/java/com/webmanage/service/OrderNoService.java @@ -0,0 +1,16 @@ +package com.webmanage.service; + +/** + * 璁㈠崟缂栧彿鏈嶅姟 + */ +public interface OrderNoService { + /** + * 鐢熸垚鍞竴璁㈠崟鍙凤紙瀛楃涓插舰寮忥紝渚夸簬浣滀负涓氬姟涓婚敭浣跨敤锛� + */ + String generateOrderNo(); + + /** + * 鐢熸垚鍘熷闆姳ID锛堥暱鏁村瀷锛� + */ + long generateSnowflakeId(); +} diff --git a/src/main/java/com/webmanage/service/PointsFlowService.java b/src/main/java/com/webmanage/service/PointsFlowService.java new file mode 100644 index 0000000..7ff3d0d --- /dev/null +++ b/src/main/java/com/webmanage/service/PointsFlowService.java @@ -0,0 +1,56 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.common.PageResult; +import com.webmanage.dto.AddPointsFlowDTO; +import com.webmanage.dto.PointsFlowQueryDTO; +import com.webmanage.entity.PointsFlow; + +import java.util.List; + +/** + * 绉垎娴佹按Service鎺ュ彛 + */ +public interface PointsFlowService extends IService<PointsFlow> { + + /** + * 鍒嗛〉鏌ヨ涓汉绉垎娴佹按 + */ + PageResult<PointsFlow> getPersonalPointsFlowPage(PointsFlowQueryDTO queryDTO); + + /** + * 鍒嗛〉鏌ヨ鍗曚綅绉垎娴佹按 + */ + PageResult<PointsFlow> getUnitPointsFlowPage(PointsFlowQueryDTO queryDTO); + + /** + * 鏍规嵁鐢ㄦ埛ID鏌ヨ绉垎娴佹按 + */ + List<PointsFlow> getPointsFlowByUserId(Long userId); + + /** + * 鏍规嵁鍗曚綅ID鏌ヨ绉垎娴佹按 + */ + List<PointsFlow> getPointsFlowByUnitId(Long unitId); + + /** + * 璁板綍绉垎娴佹按 + */ + boolean recordPointsFlow(Long userId, Long unitId, String flowType, String pointsSource, + Integer pointsValue, String orderId, String description); + + /** + * 鏂板绉垎娴佹按锛堟牴鎹鍒欒嚜鍔ㄨ绠楋級 + */ + boolean addPointsFlowByRule(AddPointsFlowDTO addPointsFlowDTO); + + /** + * 鑾峰彇鐢ㄦ埛绉垎缁熻 + */ + Integer getUserPointsTotal(Long userId); + + /** + * 鑾峰彇鍗曚綅绉垎缁熻 + */ + Integer getUnitPointsTotal(Long unitId); +} diff --git a/src/main/java/com/webmanage/service/PointsRuleDetailService.java b/src/main/java/com/webmanage/service/PointsRuleDetailService.java new file mode 100644 index 0000000..2777f6d --- /dev/null +++ b/src/main/java/com/webmanage/service/PointsRuleDetailService.java @@ -0,0 +1,11 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.entity.PointsRuleDetail; + +/** + * 绉垎瑙勫垯璇︽儏Service鎺ュ彛 + */ +public interface PointsRuleDetailService extends IService<PointsRuleDetail> { + // 绉垎瑙勫垯璇︽儏鐩稿叧涓氬姟閫昏緫鏂规硶鍙湪姝ゆ坊鍔� +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/service/PointsRuleService.java b/src/main/java/com/webmanage/service/PointsRuleService.java new file mode 100644 index 0000000..da6de60 --- /dev/null +++ b/src/main/java/com/webmanage/service/PointsRuleService.java @@ -0,0 +1,49 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.common.PageResult; +import com.webmanage.dto.PointsRuleDTO; +import com.webmanage.entity.PointsRule; + +import java.util.List; + +/** + * 绉垎瑙勫垯Service鎺ュ彛 + */ +public interface PointsRuleService extends IService<PointsRule> { + + /** + * 鍒嗛〉鏌ヨ绉垎瑙勫垯 + */ + PageResult<PointsRule> getPointsRulePage(Integer pageNum, Integer pageSize, String ruleName, String ruleType); + + /** + * 鏂板绉垎瑙勫垯 + */ + boolean addPointsRule(PointsRuleDTO pointsRuleDTO); + + /** + * 淇敼绉垎瑙勫垯 + */ + boolean updatePointsRule(PointsRuleDTO pointsRuleDTO); + + /** + * 鍒犻櫎绉垎瑙勫垯 + */ + boolean deletePointsRule(Long id); + + /** + * 鍚敤/绂佺敤绉垎瑙勫垯 + */ + boolean togglePointsRuleStatus(Long id, Boolean isEnabled); + + /** + * 鏍规嵁瑙勫垯绫诲瀷鏌ヨ鍚敤鐨勮鍒� + */ + List<PointsRule> getEnabledRulesByType(String ruleType); + + /** + * 鏍规嵁瑙﹀彂鏉′欢鏌ヨ閫傜敤鐨勮鍒� + */ + PointsRule getRuleByTriggerCondition(String triggerCondition); +} diff --git a/src/main/java/com/webmanage/service/PointsService.java b/src/main/java/com/webmanage/service/PointsService.java new file mode 100644 index 0000000..d64242a --- /dev/null +++ b/src/main/java/com/webmanage/service/PointsService.java @@ -0,0 +1,17 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.common.PageResult; +import com.webmanage.dto.PointsMainQueryDTO; +import com.webmanage.entity.Points; + +/** + * 绉垎涓昏〃Service鎺ュ彛 + */ +public interface PointsService extends IService<Points> { + + /** + * 鍒嗛〉鏌ヨ绉垎涓昏〃 + */ + PageResult<Points> getPointsMainPage(PointsMainQueryDTO queryDTO); +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/service/ProductPricingService.java b/src/main/java/com/webmanage/service/ProductPricingService.java new file mode 100644 index 0000000..1f0b329 --- /dev/null +++ b/src/main/java/com/webmanage/service/ProductPricingService.java @@ -0,0 +1,48 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.entity.ProductPricing; + +import java.util.List; + +/** + * 浜у搧瀹氫环鏈嶅姟鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +public interface ProductPricingService extends IService<ProductPricing> { + + /** + * 鏂板浜у搧瀹氫环 + */ + boolean addProductPricing(ProductPricing productPricing); + + /** + * 缂栬緫浜у搧瀹氫环 + */ + boolean updateProductPricing(ProductPricing productPricing); + + /** + * 鍒犻櫎浜у搧瀹氫环锛堥�昏緫鍒犻櫎锛� + */ + boolean deleteProductPricing(Long id); + + /** + * 鍒嗛〉鏌ヨ浜у搧瀹氫环鍒楄〃 + */ + IPage<ProductPricing> getProductPricingPage(Page<ProductPricing> page, Long productId); + + /** + * 鏍规嵁浜у搧ID鏌ヨ瀹氫环鍒楄〃 + */ + List<ProductPricing> getPricingByProductId(Long productId); + + /** + * 鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环 + */ + List<ProductPricing> getPricingByCondition(String suiteName, String salesForm, + String customerType, String priceType, Boolean isActive); +} diff --git a/src/main/java/com/webmanage/service/UserPointsService.java b/src/main/java/com/webmanage/service/UserPointsService.java new file mode 100644 index 0000000..390481f --- /dev/null +++ b/src/main/java/com/webmanage/service/UserPointsService.java @@ -0,0 +1,28 @@ +package com.webmanage.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.webmanage.vo.PointsStatsVO; + +/** + * 鐢ㄦ埛绉垎Service鎺ュ彛 + * + * @author webmanage + * @date 2024-08-07 + */ +public interface UserPointsService extends IService<com.webmanage.entity.UserPoints> { + + /** + * 鑾峰彇涓汉绉垎缁熻 + */ + PointsStatsVO getPersonalPointsStats(Long userId); + + /** + * 鑾峰彇鍗曚綅绉垎缁熻 + */ + PointsStatsVO getUnitPointsStats(Long unitId); + + /** + * 鏇存柊鐢ㄦ埛绉垎 + */ + void updateUserPoints(Long userId, Long unitId, Integer points); +} diff --git a/src/main/java/com/webmanage/service/impl/ApprovalRecordServiceImpl.java b/src/main/java/com/webmanage/service/impl/ApprovalRecordServiceImpl.java new file mode 100644 index 0000000..a7aac05 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/ApprovalRecordServiceImpl.java @@ -0,0 +1,170 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.BusinessException; +import com.webmanage.common.PageResult; +import com.webmanage.dto.ApprovalActionDTO; +import com.webmanage.dto.ApprovalQueryDTO; +import com.webmanage.entity.ApprovalRecord; +import com.webmanage.entity.OrderInfo; +import com.webmanage.mapper.ApprovalRecordMapper; +import com.webmanage.mapper.OrderInfoMapper; +import com.webmanage.service.ApprovalRecordService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 瀹℃壒璁板綍Service瀹炵幇绫� + */ +@Slf4j +@Service +public class ApprovalRecordServiceImpl extends ServiceImpl<ApprovalRecordMapper, ApprovalRecord> implements ApprovalRecordService { + + @Resource + private OrderInfoMapper orderInfoMapper; + + @Override + public PageResult<ApprovalRecord> getApprovalRecordPage(ApprovalQueryDTO queryDTO) { + Page<ApprovalRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + IPage<ApprovalRecord> result = baseMapper.selectApprovalRecordPage( + page, queryDTO.getOrderId(), queryDTO.getProductName(), queryDTO.getProviderName(), + queryDTO.getApproverId(), queryDTO.getApprovalResult(), queryDTO.getApprovalStep(), + queryDTO.getNeedAuthorization(), + queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null, + queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null, + queryDTO.getApprovalTimeStart() != null ? queryDTO.getApprovalTimeStart().toString() : null, + queryDTO.getApprovalTimeEnd() != null ? queryDTO.getApprovalTimeEnd().toString() : null, + queryDTO.getOrderBy(), queryDTO.getOrderDirection() + ); + return new PageResult<ApprovalRecord>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public PageResult<ApprovalRecord> getPendingApprovalPage(ApprovalQueryDTO queryDTO) { + Page<ApprovalRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + IPage<ApprovalRecord> result = baseMapper.selectPendingApprovalPage( + page, queryDTO.getOrderId(), queryDTO.getProductName(), queryDTO.getProviderName(), + queryDTO.getApprovalStep(), queryDTO.getOrderBy(), queryDTO.getOrderDirection() + ); + return new PageResult<ApprovalRecord>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public List<ApprovalRecord> getApprovalRecordsByOrderId(String orderId) { + if (!StringUtils.hasText(orderId)) { + throw new BusinessException("璁㈠崟ID涓嶈兘涓虹┖"); + } + return baseMapper.selectByOrderId(orderId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean approveOrder(ApprovalActionDTO actionDTO) { + // 楠岃瘉璁㈠崟鏄惁瀛樺湪 + OrderInfo orderInfo = orderInfoMapper.selectById(actionDTO.getOrderId()); + if (orderInfo == null) { + throw new BusinessException("璁㈠崟涓嶅瓨鍦�"); + } + + // 鍒涘缓瀹℃壒璁板綍 + ApprovalRecord approvalRecord = new ApprovalRecord(); + approvalRecord.setOrderId(actionDTO.getOrderId()); + approvalRecord.setApproverId(actionDTO.getApproverId()); + approvalRecord.setApproverName(actionDTO.getApproverName()); + approvalRecord.setApproverRole(actionDTO.getApproverRole()); + approvalRecord.setApprovalStep(actionDTO.getApprovalStep()); + approvalRecord.setApprovalResult(actionDTO.getApprovalResult()); + approvalRecord.setApprovalOpinion(actionDTO.getApprovalOpinion()); + approvalRecord.setApprovalTime(LocalDateTime.now()); + approvalRecord.setNeedAuthorization(actionDTO.getNeedAuthorization()); + + // 濡傛灉闇�瑕佹巿鏉冿紝璁剧疆鎺堟潈浜轰俊鎭� + if (Boolean.TRUE.equals(actionDTO.getNeedAuthorization()) && actionDTO.getAuthorizerId() != null) { + approvalRecord.setAuthorizerId(actionDTO.getAuthorizerId()); + approvalRecord.setAuthorizerName(actionDTO.getAuthorizerName()); + approvalRecord.setAuthorizationOpinion(actionDTO.getAuthorizationOpinion()); + approvalRecord.setAuthorizationTime(LocalDateTime.now()); + } + + // 淇濆瓨瀹℃壒璁板綍 + boolean saved = save(approvalRecord); + if (!saved) { + throw new BusinessException("淇濆瓨瀹℃壒璁板綍澶辫触"); + } + + // 鏇存柊璁㈠崟鐘舵�� + if ("閫氳繃".equals(actionDTO.getApprovalResult())) { + orderInfo.setOrderStatus("宸插鎵�"); + orderInfo.setCurrentStep(actionDTO.getApprovalStep()); + } else if ("椹冲洖".equals(actionDTO.getApprovalResult())) { + orderInfo.setOrderStatus("宸查┏鍥�"); + } + + int updated = orderInfoMapper.updateById(orderInfo); + if (updated <= 0) { + throw new BusinessException("鏇存柊璁㈠崟鐘舵�佸け璐�"); + } + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean authorizeApproval(Long approvalId, Long authorizerId, String authorizerName, String authorizationOpinion) { + ApprovalRecord approvalRecord = getById(approvalId); + if (approvalRecord == null) { + throw new BusinessException("瀹℃壒璁板綍涓嶅瓨鍦�"); + } + + if (!Boolean.TRUE.equals(approvalRecord.getNeedAuthorization())) { + throw new BusinessException("璇ュ鎵硅褰曚笉闇�瑕佹巿鏉�"); + } + + approvalRecord.setAuthorizerId(authorizerId); + approvalRecord.setAuthorizerName(authorizerName); + approvalRecord.setAuthorizationOpinion(authorizationOpinion); + approvalRecord.setAuthorizationTime(LocalDateTime.now()); + + return updateById(approvalRecord); + } + + @Override + public String getOrderCurrentApprovalStatus(String orderId) { + if (!StringUtils.hasText(orderId)) { + return "鏈煡"; + } + + QueryWrapper<ApprovalRecord> wrapper = new QueryWrapper<>(); + wrapper.eq("order_id", orderId) + .orderByDesc("created_at") + .last("LIMIT 1"); + + ApprovalRecord latestRecord = getOne(wrapper); + if (latestRecord == null) { + return "寰呭鎵�"; + } + + return latestRecord.getApprovalResult(); + } +} diff --git a/src/main/java/com/webmanage/service/impl/CartServiceImpl.java b/src/main/java/com/webmanage/service/impl/CartServiceImpl.java new file mode 100644 index 0000000..304a9fe --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/CartServiceImpl.java @@ -0,0 +1,488 @@ +package com.webmanage.service.impl; + +import com.webmanage.common.BusinessException; +import com.webmanage.dto.CartItemDTO; +import com.webmanage.entity.Cart; +import com.webmanage.entity.ProductPricing; +import com.webmanage.mapper.CartMapper; +import com.webmanage.mapper.ProductPricingMapper; +import com.webmanage.service.CartService; +import com.webmanage.vo.CartItemVO; +import com.webmanage.vo.CartVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 璐墿杞︽湇鍔″疄鐜扮被 + */ +@Slf4j +@Service +public class CartServiceImpl implements CartService { + + @Resource + private RedisTemplate<String, Object> redisTemplate; + + @Resource + private CartMapper cartMapper; + + @Resource + private ProductPricingMapper productPricingMapper; + + // Redis key鍓嶇紑 + private static final String CART_KEY_PREFIX = "cart:"; + private static final String CART_ITEM_KEY_PREFIX = "cart_item:"; + private static final int CART_EXPIRE_DAYS = 30; // 璐墿杞﹁繃鏈熸椂闂�30澶� + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean addToCart(Long userId, Long unitId, CartItemDTO cartItemDTO) { + try { + // 楠岃瘉鍟嗗搧瀹氫环鏄惁瀛樺湪 + ProductPricing pricing = productPricingMapper.selectById(cartItemDTO.getPricingId()); + if (pricing == null) { + throw new BusinessException("鍟嗗搧瀹氫环涓嶅瓨鍦�"); + } + + // 鏋勫缓璐墿杞ey + String cartKey = buildCartKey(userId, unitId); + String cartItemKey = buildCartItemKey(userId, unitId, cartItemDTO.getPricingId()); + + // 妫�鏌ュ晢鍝佹槸鍚﹀凡鍦ㄨ喘鐗╄溅涓� + CartItemVO existingItem = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey); + if (existingItem != null) { + // 濡傛灉宸插瓨鍦紝鏇存柊鏁伴噺 + existingItem.setQuantity(existingItem.getQuantity() + cartItemDTO.getQuantity()); + existingItem.setTotalPrice(existingItem.getUnitPrice().multiply(BigDecimal.valueOf(existingItem.getQuantity()))); + existingItem.setUpdateTime(LocalDateTime.now()); + } else { + // 濡傛灉涓嶅瓨鍦紝鍒涘缓鏂扮殑璐墿杞﹂」 + existingItem = new CartItemVO(); + BeanUtils.copyProperties(cartItemDTO, existingItem); + existingItem.setAddTime(LocalDateTime.now()); + existingItem.setUpdateTime(LocalDateTime.now()); + // 璁$畻灏忚閲戦 + if (existingItem.getTotalPrice() == null) { + existingItem.setTotalPrice(existingItem.getUnitPrice().multiply(BigDecimal.valueOf(existingItem.getQuantity()))); + } + } + + // 淇濆瓨鍒癛edis + redisTemplate.opsForValue().set(cartItemKey, existingItem, CART_EXPIRE_DAYS, TimeUnit.DAYS); + + // 鏇存柊璐墿杞﹀晢鍝佸垪琛� + updateCartItemList(userId, unitId, cartItemDTO.getPricingId(), true); + + // 璁剧疆璐墿杞﹁繃鏈熸椂闂� + redisTemplate.expire(cartKey, CART_EXPIRE_DAYS, TimeUnit.DAYS); + + // 鍚屾鍒版暟鎹簱 + syncCartItemToDatabase(userId, unitId, existingItem); + + log.info("鐢ㄦ埛{}鎴愬姛娣诲姞鍟嗗搧{}鍒拌喘鐗╄溅", userId, cartItemDTO.getProductName()); + return true; + } catch (Exception e) { + log.error("娣诲姞鍟嗗搧鍒拌喘鐗╄溅澶辫触", e); + throw new BusinessException("娣诲姞鍟嗗搧鍒拌喘鐗╄溅澶辫触锛�" + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeFromCart(Long userId, Long unitId, Long pricingId) { + try { + String cartItemKey = buildCartItemKey(userId, unitId, pricingId); + + // 浠嶳edis涓垹闄ゅ晢鍝侀」 + Boolean removed = redisTemplate.delete(cartItemKey); + if (Boolean.TRUE.equals(removed)) { + // 鏇存柊璐墿杞﹀晢鍝佸垪琛� + updateCartItemList(userId, unitId, pricingId, false); + + // 浠庢暟鎹簱涓垹闄� + removeCartItemFromDatabase(userId, unitId, pricingId); + + log.info("鐢ㄦ埛{}鎴愬姛浠庤喘鐗╄溅绉婚櫎鍟嗗搧{}", userId, pricingId); + return true; + } + return false; + } catch (Exception e) { + log.error("浠庤喘鐗╄溅绉婚櫎鍟嗗搧澶辫触", e); + throw new BusinessException("浠庤喘鐗╄溅绉婚櫎鍟嗗搧澶辫触锛�" + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateCartItemQuantity(Long userId, Long unitId, Long pricingId, Integer quantity) { + try { + if (quantity <= 0) { + return removeFromCart(userId, unitId, pricingId); + } + + String cartItemKey = buildCartItemKey(userId, unitId, pricingId); + CartItemVO cartItem = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey); + if (cartItem == null) { + throw new BusinessException("璐墿杞﹀晢鍝佷笉瀛樺湪"); + } + + cartItem.setQuantity(quantity); + cartItem.setTotalPrice(cartItem.getUnitPrice().multiply(BigDecimal.valueOf(quantity))); + cartItem.setUpdateTime(LocalDateTime.now()); + + // 鏇存柊鍒癛edis + redisTemplate.opsForValue().set(cartItemKey, cartItem, CART_EXPIRE_DAYS, TimeUnit.DAYS); + + // 鍚屾鍒版暟鎹簱 + syncCartItemToDatabase(userId, unitId, cartItem); + + log.info("鐢ㄦ埛{}鎴愬姛鏇存柊璐墿杞﹀晢鍝亄}鏁伴噺涓簕}", userId, pricingId, quantity); + return true; + } catch (Exception e) { + log.error("鏇存柊璐墿杞﹀晢鍝佹暟閲忓け璐�", e); + throw new BusinessException("鏇存柊璐墿杞﹀晢鍝佹暟閲忓け璐ワ細" + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean clearCart(Long userId, Long unitId) { + try { + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = getCartItemPricingIds(userId, unitId); + + // 鍒犻櫎鎵�鏈夊晢鍝侀」 + for (Long pricingId : pricingIds) { + String cartItemKey = buildCartItemKey(userId, unitId, pricingId); + redisTemplate.delete(cartItemKey); + } + + // 鍒犻櫎璐墿杞﹀垪琛� + redisTemplate.delete(cartKey); + + // 娓呯┖鏁版嵁搴撲腑鐨勮喘鐗╄溅鏁版嵁 + clearCartFromDatabase(userId, unitId); + + log.info("鐢ㄦ埛{}鎴愬姛娓呯┖璐墿杞�", userId); + return true; + } catch (Exception e) { + log.error("娓呯┖璐墿杞﹀け璐�", e); + throw new BusinessException("娓呯┖璐墿杞﹀け璐ワ細" + e.getMessage()); + } + } + + @Override + public CartVO getCart(Long userId, Long unitId) { + try { + CartVO cartVO = new CartVO(); + cartVO.setUserId(userId); + cartVO.setUnitId(unitId); + + List<CartItemVO> items = getCartItems(userId, unitId); + cartVO.setItems(items); + + // 璁$畻鎬绘暟閲忓拰鎬婚噾棰� + int totalQuantity = items.stream().mapToInt(item -> item.getQuantity()).sum(); + BigDecimal totalAmount = items.stream() + .map(item -> item.getTotalPrice()) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + cartVO.setTotalQuantity(totalQuantity); + cartVO.setTotalAmount(totalAmount); + cartVO.setLastUpdateTime(LocalDateTime.now()); + + return cartVO; + } catch (Exception e) { + log.error("鑾峰彇璐墿杞︿俊鎭け璐�", e); + throw new BusinessException("鑾峰彇璐墿杞︿俊鎭け璐ワ細" + e.getMessage()); + } + } + + @Override + public List<CartItemVO> getCartItems(Long userId, Long unitId) { + try { + // 浼樺厛浠嶳edis鑾峰彇 + List<CartItemVO> items = getCartItemsFromRedis(userId, unitId); + if (items != null && !items.isEmpty()) { + return items; + } + + // Redis涓病鏈夋暟鎹紝浠庢暟鎹簱鍔犺浇 + log.info("Redis涓棤璐墿杞︽暟鎹紝浠庢暟鎹簱鍔犺浇鐢ㄦ埛{}鐨勮喘鐗╄溅", userId); + return loadCartFromDatabase(userId, unitId) ? getCartItemsFromRedis(userId, unitId) : new ArrayList<>(); + } catch (Exception e) { + log.error("鑾峰彇璐墿杞﹀晢鍝佸垪琛ㄥけ璐�", e); + // 闄嶇骇鍒版暟鎹簱鏌ヨ + return getCartItemsFromDatabase(userId, unitId); + } + } + + @Override + public boolean checkCartItemStock(Long userId, Long unitId, Long pricingId) { + // TODO: 瀹炵幇搴撳瓨妫�鏌ラ�昏緫 + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean batchRemoveFromCart(Long userId, Long unitId, List<Long> pricingIds) { + try { + if (CollectionUtils.isEmpty(pricingIds)) { + return true; + } + + for (Long pricingId : pricingIds) { + removeFromCart(userId, unitId, pricingId); + } + + return true; + } catch (Exception e) { + log.error("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佸け璐�", e); + throw new BusinessException("鎵归噺鍒犻櫎璐墿杞﹀晢鍝佸け璐ワ細" + e.getMessage()); + } + } + + @Override + public Integer getCartItemCount(Long userId, Long unitId) { + try { + // 浼樺厛浠嶳edis鑾峰彇 + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey); + if (pricingIds != null) { + return pricingIds.size(); + } + + // 浠庢暟鎹簱鑾峰彇 + return cartMapper.countByUserIdAndUnitId(userId, unitId); + } catch (Exception e) { + log.error("鑾峰彇璐墿杞﹀晢鍝佹暟閲忓け璐�", e); + return 0; + } + } + + @Override + public boolean loadCartFromDatabase(Long userId, Long unitId) { + try { + List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId); + if (CollectionUtils.isEmpty(cartItems)) { + return false; + } + + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = new ArrayList<>(); + + for (Cart cartItem : cartItems) { + CartItemVO itemVO = convertCartToCartItemVO(cartItem); + String cartItemKey = buildCartItemKey(userId, unitId, cartItem.getPricingId()); + + // 淇濆瓨鍒癛edis + redisTemplate.opsForValue().set(cartItemKey, itemVO, CART_EXPIRE_DAYS, TimeUnit.DAYS); + pricingIds.add(cartItem.getPricingId()); + } + + // 淇濆瓨璐墿杞﹀垪琛ㄥ埌Redis + redisTemplate.opsForValue().set(cartKey, pricingIds, CART_EXPIRE_DAYS, TimeUnit.DAYS); + + log.info("鎴愬姛浠庢暟鎹簱鍔犺浇鐢ㄦ埛{}鐨勮喘鐗╄溅鏁版嵁鍒癛edis", userId); + return true; + } catch (Exception e) { + log.error("浠庢暟鎹簱鍔犺浇璐墿杞︽暟鎹け璐�", e); + return false; + } + } + + @Override + public boolean syncCartToDatabase(Long userId, Long unitId) { + try { + List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId); + if (CollectionUtils.isEmpty(redisItems)) { + return true; + } + + // 娓呯┖鏁版嵁搴撲腑鐨勮喘鐗╄溅鏁版嵁 + clearCartFromDatabase(userId, unitId); + + // 鍚屾Redis鏁版嵁鍒版暟鎹簱 + for (CartItemVO item : redisItems) { + syncCartItemToDatabase(userId, unitId, item); + } + + log.info("鎴愬姛鍚屾Redis璐墿杞︽暟鎹埌鏁版嵁搴擄紝鐢ㄦ埛{}", userId); + return true; + } catch (Exception e) { + log.error("鍚屾璐墿杞︽暟鎹埌鏁版嵁搴撳け璐�", e); + return false; + } + } + + @Override + public boolean checkCartConsistency(Long userId, Long unitId) { + try { + List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId); + List<Cart> dbItems = cartMapper.selectByUserIdAndUnitId(userId, unitId); + + if (redisItems.size() != dbItems.size()) { + log.warn("璐墿杞︽暟鎹笉涓�鑷达細Redis鏁伴噺{}锛屾暟鎹簱鏁伴噺{}", redisItems.size(), dbItems.size()); + return false; + } + + // 妫�鏌ユ瘡涓晢鍝侀」鏄惁涓�鑷� + for (CartItemVO redisItem : redisItems) { + boolean found = false; + for (Cart dbItem : dbItems) { + if (redisItem.getPricingId().equals(dbItem.getPricingId()) && + redisItem.getQuantity().equals(dbItem.getQuantity())) { + found = true; + break; + } + } + if (!found) { + log.warn("璐墿杞﹀晢鍝侀」涓嶄竴鑷达細pricingId={}", redisItem.getPricingId()); + return false; + } + } + + return true; + } catch (Exception e) { + log.error("妫�鏌ヨ喘鐗╄溅鏁版嵁涓�鑷存�уけ璐�", e); + return false; + } + } + + // ==================== 绉佹湁鏂规硶 ==================== + + private String buildCartKey(Long userId, Long unitId) { + return CART_KEY_PREFIX + userId + ":" + unitId; + } + + private String buildCartItemKey(Long userId, Long unitId, Long pricingId) { + return CART_ITEM_KEY_PREFIX + userId + ":" + unitId + ":" + pricingId; + } + + private void updateCartItemList(Long userId, Long unitId, Long pricingId, boolean add) { + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey); + + if (pricingIds == null) { + pricingIds = new ArrayList<>(); + } + + if (add && !pricingIds.contains(pricingId)) { + pricingIds.add(pricingId); + } else if (!add) { + pricingIds.remove(pricingId); + } + + redisTemplate.opsForValue().set(cartKey, pricingIds, CART_EXPIRE_DAYS, TimeUnit.DAYS); + } + + private List<Long> getCartItemPricingIds(Long userId, Long unitId) { + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey); + return pricingIds != null ? pricingIds : new ArrayList<>(); + } + + private List<CartItemVO> getCartItemsFromRedis(Long userId, Long unitId) { + try { + String cartKey = buildCartKey(userId, unitId); + List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey); + + if (CollectionUtils.isEmpty(pricingIds)) { + return new ArrayList<>(); + } + + List<CartItemVO> items = new ArrayList<>(); + for (Long pricingId : pricingIds) { + String cartItemKey = buildCartItemKey(userId, unitId, pricingId); + CartItemVO item = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey); + if (item != null) { + items.add(item); + } + } + + return items; + } catch (Exception e) { + log.error("浠嶳edis鑾峰彇璐墿杞﹀晢鍝佸垪琛ㄥけ璐�", e); + return new ArrayList<>(); + } + } + + private List<CartItemVO> getCartItemsFromDatabase(Long userId, Long unitId) { + try { + List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId); + List<CartItemVO> items = new ArrayList<>(); + + for (Cart cartItem : cartItems) { + items.add(convertCartToCartItemVO(cartItem)); + } + + return items; + } catch (Exception e) { + log.error("浠庢暟鎹簱鑾峰彇璐墿杞﹀晢鍝佸垪琛ㄥけ璐�", e); + return new ArrayList<>(); + } + } + + private CartItemVO convertCartToCartItemVO(Cart cart) { + CartItemVO itemVO = new CartItemVO(); + BeanUtils.copyProperties(cart, itemVO); + return itemVO; + } + + private void syncCartItemToDatabase(Long userId, Long unitId, CartItemVO item) { + try { + Cart cart = new Cart(); + BeanUtils.copyProperties(item, cart); + cart.setUserId(userId); + cart.setUnitId(unitId); + cart.setUpdateTime(LocalDateTime.now()); + + // 妫�鏌ユ槸鍚﹀凡瀛樺湪 + Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, item.getPricingId()); + if (existingCart != null) { + // 鏇存柊 + cart.setId(existingCart.getId()); + cartMapper.updateById(cart); + } else { + // 鏂板 + cart.setAddTime(LocalDateTime.now()); + cartMapper.insert(cart); + } + } catch (Exception e) { + log.error("鍚屾璐墿杞﹀晢鍝佸埌鏁版嵁搴撳け璐�", e); + } + } + + private void removeCartItemFromDatabase(Long userId, Long unitId, Long pricingId) { + try { + Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, pricingId); + if (existingCart != null) { + cartMapper.deleteById(existingCart.getId()); + } + } catch (Exception e) { + log.error("浠庢暟鎹簱鍒犻櫎璐墿杞﹀晢鍝佸け璐�", e); + } + } + + private void clearCartFromDatabase(Long userId, Long unitId) { + try { + // 浣跨敤閫昏緫鍒犻櫎 + List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId); + for (Cart item : cartItems) { + cartMapper.deleteById(item.getId()); + } + } catch (Exception e) { + log.error("娓呯┖鏁版嵁搴撹喘鐗╄溅澶辫触", e); + } + } +} diff --git a/src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java b/src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java new file mode 100644 index 0000000..92a9b54 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/OrderInfoServiceImpl.java @@ -0,0 +1,422 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.BusinessException; +import com.webmanage.common.PageResult; +import com.webmanage.dto.CreateOrderDTO; +import com.webmanage.dto.CreateOrderItemDTO; +import com.webmanage.dto.OrderQueryDTO; +import com.webmanage.entity.OrderAttachment; +import com.webmanage.entity.OrderDetail; +import com.webmanage.entity.OrderEvaluation; +import com.webmanage.entity.OrderInfo; +import com.webmanage.mapper.OrderAttachmentMapper; +import com.webmanage.mapper.OrderDetailMapper; +import com.webmanage.mapper.OrderEvaluationMapper; +import com.webmanage.mapper.OrderInfoMapper; +import com.webmanage.service.OrderInfoService; +import com.webmanage.service.OrderNoService; +import com.webmanage.vo.OrderAttachmentVO; +import com.webmanage.vo.OrderDetailItemVO; +import com.webmanage.vo.OrderDetailVO; +import com.webmanage.vo.OrderEvaluationVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 璁㈠崟淇℃伅Service瀹炵幇绫� + */ +@Slf4j +@Service +public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService { + + @Resource + private OrderDetailMapper orderDetailMapper; + + @Resource + private OrderAttachmentMapper orderAttachmentMapper; + + @Resource + private OrderEvaluationMapper orderEvaluationMapper; + + @Resource + private OrderNoService orderNoService; + + @Override + public PageResult<OrderInfo> getBuyerOrderPage(OrderQueryDTO queryDTO) { + // 鍙傛暟鏍¢獙 + if (queryDTO.getUserId() == null) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + // 鍒涘缓鍒嗛〉瀵硅薄 + Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + // 鎵ц鍒嗛〉鏌ヨ + IPage<OrderInfo> result = baseMapper.selectBuyerOrderPage( + page, queryDTO.getUserId(), queryDTO.getUnitId(), queryDTO.getOrderStatus(), + queryDTO.getPaymentStatus(), queryDTO.getPaymentType(), queryDTO.getProductName(), + queryDTO.getProviderName(), queryDTO.getOrderId(), + queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null, + queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null, + queryDTO.getCreateTimeStart() != null ? queryDTO.getCreateTimeStart().toString() : null, + queryDTO.getCreateTimeEnd() != null ? queryDTO.getCreateTimeEnd().toString() : null, + queryDTO.getOrderBy(), queryDTO.getOrderDirection() + ); + + // 鏋勫缓杩斿洖缁撴灉 + return new PageResult<OrderInfo>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public PageResult<OrderInfo> getSellerOrderPage(OrderQueryDTO queryDTO) { + // 鍙傛暟鏍¢獙 + if (queryDTO.getUserId() == null) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + // 鍒涘缓鍒嗛〉瀵硅薄 + Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + // 鎵ц鍒嗛〉鏌ヨ + IPage<OrderInfo> result = baseMapper.selectSellerOrderPage( + page, queryDTO.getUserId(), queryDTO.getOrderStatus(), queryDTO.getPaymentStatus(), + queryDTO.getProductName(), queryDTO.getOrderId(), + queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null, + queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null, + queryDTO.getCreateTimeStart() != null ? queryDTO.getCreateTimeStart().toString() : null, + queryDTO.getCreateTimeEnd() != null ? queryDTO.getCreateTimeEnd().toString() : null, + queryDTO.getOrderBy(), queryDTO.getOrderDirection() + ); + + // 鏋勫缓杩斿洖缁撴灉 + return new PageResult<OrderInfo>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public PageResult<OrderInfo> getPendingApprovalOrderPage(OrderQueryDTO queryDTO) { + // 鍒涘缓鍒嗛〉瀵硅薄 + Page<OrderInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + // 鎵ц鍒嗛〉鏌ヨ + IPage<OrderInfo> result = baseMapper.selectPendingApprovalOrderPage( + page, queryDTO.getOrderStatus(), queryDTO.getProductName(), queryDTO.getProviderName(), + queryDTO.getOrderId(), + queryDTO.getApplyTimeStart() != null ? queryDTO.getApplyTimeStart().toString() : null, + queryDTO.getApplyTimeEnd() != null ? queryDTO.getApplyTimeEnd().toString() : null, + queryDTO.getOrderBy(), queryDTO.getOrderDirection() + ); + + // 鏋勫缓杩斿洖缁撴灉 + return new PageResult<OrderInfo>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public OrderDetailVO getOrderDetail(String orderId) { + // 鍙傛暟鏍¢獙 + if (!StringUtils.hasText(orderId)) { + throw new BusinessException("璁㈠崟ID涓嶈兘涓虹┖"); + } + + // 鏌ヨ璁㈠崟鍩烘湰淇℃伅 + OrderInfo orderInfo = this.getById(orderId); + if (orderInfo == null) { + throw new BusinessException("璁㈠崟涓嶅瓨鍦�"); + } + + // 鏋勫缓璁㈠崟璇︽儏VO + OrderDetailVO orderDetailVO = new OrderDetailVO(); + BeanUtils.copyProperties(orderInfo, orderDetailVO); + + // 鏌ヨ璁㈠崟璇︽儏鍒楄〃 + List<OrderDetail> orderDetails = orderDetailMapper.selectByOrderId(orderId); + List<OrderDetailItemVO> orderDetailItemVOs = orderDetails.stream().map(detail -> { + OrderDetailItemVO itemVO = new OrderDetailItemVO(); + BeanUtils.copyProperties(detail, itemVO); + return itemVO; + }).collect(Collectors.toList()); + orderDetailVO.setOrderDetails(orderDetailItemVOs); + + // 鏌ヨ璁㈠崟闄勪欢鍒楄〃 + List<OrderAttachment> attachments = orderAttachmentMapper.selectByOrderId(orderId); + List<OrderAttachmentVO> attachmentVOs = attachments.stream().map(attachment -> { + OrderAttachmentVO attachmentVO = new OrderAttachmentVO(); + BeanUtils.copyProperties(attachment, attachmentVO); + return attachmentVO; + }).collect(Collectors.toList()); + orderDetailVO.setAttachments(attachmentVOs); + + // 鏌ヨ璁㈠崟璇勪环 + OrderEvaluation evaluation = orderEvaluationMapper.selectByOrderId(orderId); + if (evaluation != null) { + OrderEvaluationVO evaluationVO = new OrderEvaluationVO(); + BeanUtils.copyProperties(evaluation, evaluationVO); + orderDetailVO.setEvaluation(evaluationVO); + } + + return orderDetailVO; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String createOrder(CreateOrderDTO createOrderDTO) { + if (createOrderDTO == null || CollectionUtils.isEmpty(createOrderDTO.getItems())) { + throw new BusinessException("璁㈠崟淇℃伅涓嶅畬鏁�"); + } + // 鐢熸垚璁㈠崟缂栧彿 + String orderId = orderNoService.generateOrderNo(); + + // 璁$畻鎬婚噾棰� + BigDecimal totalAmount = BigDecimal.ZERO; + for (CreateOrderItemDTO item : createOrderDTO.getItems()) { + BigDecimal unitPrice = item.getUnitPrice(); + Integer quantity = item.getQuantity(); + if (unitPrice == null || quantity == null || quantity <= 0) { + throw new BusinessException("鏄庣粏椤瑰崟浠锋垨鏁伴噺涓嶅悎娉�"); + } + BigDecimal lineAmount = unitPrice.multiply(BigDecimal.valueOf(quantity)); + totalAmount = totalAmount.add(lineAmount); + } + + // 淇濆瓨璁㈠崟澶� + OrderInfo orderInfo = new OrderInfo(); + orderInfo.setOrderId(orderId); + orderInfo.setProductId(createOrderDTO.getItems().get(0).getProductId()); + orderInfo.setProductName(createOrderDTO.getProductName()); + orderInfo.setProviderId(createOrderDTO.getProviderId()); + orderInfo.setProviderName(createOrderDTO.getProviderName()); + orderInfo.setUserId(createOrderDTO.getUserId()); + orderInfo.setUnitId(createOrderDTO.getUnitId()); + orderInfo.setApplyTime(LocalDateTime.now()); + orderInfo.setOrderStatus("寰呭鎵�"); + orderInfo.setTotalAmount(createOrderDTO.getTotalAmount() != null ? createOrderDTO.getTotalAmount() : totalAmount); + orderInfo.setPaymentType(createOrderDTO.getPaymentType()); + orderInfo.setPaymentStatus("鏈敮浠�"); + orderInfo.setBuyerRemarks(createOrderDTO.getBuyerRemarks()); + orderInfo.setCreatedAt(LocalDateTime.now()); + orderInfo.setUpdatedAt(LocalDateTime.now()); + + int inserted = this.baseMapper.insert(orderInfo); + if (inserted <= 0) { + throw new BusinessException("淇濆瓨璁㈠崟澶辫触"); + } + + // 淇濆瓨璁㈠崟鏄庣粏 + for (CreateOrderItemDTO item : createOrderDTO.getItems()) { + OrderDetail detail = new OrderDetail(); + detail.setOrderId(orderId); + detail.setPricingId(item.getPricingId()); + detail.setProductId(item.getProductId()); + detail.setSuiteName(item.getSuiteName()); + detail.setSalesForm(item.getSalesForm()); + detail.setCustomerType(item.getCustomerType()); + detail.setAccountLimit(item.getAccountLimit()); + detail.setConcurrentNodes(item.getConcurrentNodes()); + detail.setPriceType(item.getPriceType()); + detail.setPriceUnit(item.getPriceUnit()); + detail.setUnitPrice(item.getUnitPrice()); + detail.setQuantity(item.getQuantity()); + detail.setDuration(item.getDuration()); + BigDecimal lineAmount = item.getUnitPrice().multiply(BigDecimal.valueOf(item.getQuantity())); + detail.setTotalPrice(item.getTotalPrice() != null ? item.getTotalPrice() : lineAmount); + detail.setProviderId(item.getProviderId()); + detail.setProviderName(item.getProviderName()); + detail.setRemarks(item.getRemarks()); + detail.setCreatedAt(LocalDateTime.now()); + detail.setUpdatedAt(LocalDateTime.now()); + orderDetailMapper.insert(detail); + } + + return orderId; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean uploadOrderAttachment(String orderId, String fileName, String originalName, + String fileType, Long fileSize, String fileUrl, + String bucketName, String objectName, Long uploadUserId, + String uploadUserName, String attachmentType, String description) { + // 鍙傛暟鏍¢獙 + if (!StringUtils.hasText(orderId)) { + throw new BusinessException("璁㈠崟ID涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(fileName)) { + throw new BusinessException("鏂囦欢鍚嶄笉鑳戒负绌�"); + } + + // 妫�鏌ヨ鍗曟槸鍚﹀瓨鍦� + OrderInfo orderInfo = this.getById(orderId); + if (orderInfo == null) { + throw new BusinessException("璁㈠崟涓嶅瓨鍦�"); + } + + // 鍒涘缓璁㈠崟闄勪欢 + OrderAttachment attachment = new OrderAttachment(); + attachment.setOrderId(orderId); + attachment.setFileName(fileName); + attachment.setOriginalName(originalName); + attachment.setFileType(fileType); + attachment.setFileSize(fileSize); + attachment.setFileUrl(fileUrl); + attachment.setBucketName(bucketName); + attachment.setObjectName(objectName); + attachment.setUploadUserId(uploadUserId); + attachment.setUploadUserName(uploadUserName); + attachment.setAttachmentType(attachmentType); + attachment.setDescription(description); + + // 淇濆瓨闄勪欢 + return orderAttachmentMapper.insert(attachment) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean addOrderEvaluation(String orderId, Long evaluatorId, String evaluatorName, + String evaluatorType, String content, Integer rating, + Integer serviceRating, Integer qualityRating, Integer deliveryRating, + Boolean isAnonymous) { + // 鍙傛暟鏍¢獙 + if (!StringUtils.hasText(orderId)) { + throw new BusinessException("璁㈠崟ID涓嶈兘涓虹┖"); + } + if (evaluatorId == null) { + throw new BusinessException("璇勪环浜篒D涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(content)) { + throw new BusinessException("璇勪环鍐呭涓嶈兘涓虹┖"); + } + if (rating == null || rating < 1 || rating > 5) { + throw new BusinessException("璇勫垎蹇呴』鍦�1-5涔嬮棿"); + } + + // 妫�鏌ヨ鍗曟槸鍚﹀瓨鍦� + OrderInfo orderInfo = this.getById(orderId); + if (orderInfo == null) { + throw new BusinessException("璁㈠崟涓嶅瓨鍦�"); + } + + // 妫�鏌ユ槸鍚﹀凡缁忚瘎浠疯繃 + OrderEvaluation existingEvaluation = orderEvaluationMapper.selectByOrderId(orderId); + if (existingEvaluation != null) { + throw new BusinessException("璇ヨ鍗曞凡缁忚瘎浠疯繃浜�"); + } + + // 鍒涘缓璁㈠崟璇勪环 + OrderEvaluation evaluation = new OrderEvaluation(); + evaluation.setOrderId(orderId); + evaluation.setEvaluatorId(evaluatorId); + evaluation.setEvaluatorName(evaluatorName); + evaluation.setEvaluatorType(evaluatorType); + evaluation.setContent(content); + evaluation.setRating(rating); + evaluation.setServiceRating(serviceRating); + evaluation.setQualityRating(qualityRating); + evaluation.setDeliveryRating(deliveryRating); + evaluation.setIsAnonymous(isAnonymous != null ? isAnonymous : false); + + // 淇濆瓨璇勪环 + return orderEvaluationMapper.insert(evaluation) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean confirmTransaction(String orderId, Long userId) { + // 鍙傛暟鏍¢獙 + if (!StringUtils.hasText(orderId)) { + throw new BusinessException("璁㈠崟ID涓嶈兘涓虹┖"); + } + if (userId == null) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + // 鏌ヨ璁㈠崟淇℃伅 + OrderInfo orderInfo = this.getById(orderId); + if (orderInfo == null) { + throw new BusinessException("璁㈠崟涓嶅瓨鍦�"); + } + + // 妫�鏌ヨ鍗曠姸鎬� + if (!"寰呬氦鏄撶‘璁�".equals(orderInfo.getOrderStatus())) { + throw new BusinessException("璁㈠崟鐘舵�佷笉姝g‘锛屾棤娉曠‘璁や氦鏄�"); + } + + // 妫�鏌ョ敤鎴锋潈闄� + if (!userId.equals(orderInfo.getUserId())) { + throw new BusinessException("鏃犳潈闄愭搷浣滄璁㈠崟"); + } + + // 鏇存柊璁㈠崟鐘舵�� + orderInfo.setOrderStatus("宸插畬鎴�"); + orderInfo.setUpdatedAt(LocalDateTime.now()); + + // 濡傛灉鏄Н鍒嗕氦鏄擄紝闇�瑕佹墸闄ょН鍒� + if ("绉垎".equals(orderInfo.getPaymentType())) { + // TODO: 瀹炵幇绉垎鎵i櫎閫昏緫 + log.info("绉垎浜ゆ槗纭锛岃鍗旾D: {}, 闇�瑕佹墸闄ょН鍒�", orderId); + } + + // 淇濆瓨璁㈠崟 + return this.updateById(orderInfo); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean replyEvaluation(Long evaluationId, String replyContent, Long replyUserId) { + // 鍙傛暟鏍¢獙 + if (evaluationId == null) { + throw new BusinessException("璇勪环ID涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(replyContent)) { + throw new BusinessException("鍥炲鍐呭涓嶈兘涓虹┖"); + } + if (replyUserId == null) { + throw new BusinessException("鍥炲鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + // 鏌ヨ璇勪环淇℃伅 + OrderEvaluation evaluation = orderEvaluationMapper.selectById(evaluationId); + if (evaluation == null) { + throw new BusinessException("璇勪环涓嶅瓨鍦�"); + } + + // 鏇存柊鍥炲淇℃伅 + evaluation.setReplyContent(replyContent); + evaluation.setReplyUserId(replyUserId); + evaluation.setReplyTime(LocalDateTime.now()); + evaluation.setUpdatedAt(LocalDateTime.now()); + + // 淇濆瓨璇勪环 + return orderEvaluationMapper.updateById(evaluation) > 0; + } +} diff --git a/src/main/java/com/webmanage/service/impl/OrderNoServiceImpl.java b/src/main/java/com/webmanage/service/impl/OrderNoServiceImpl.java new file mode 100644 index 0000000..4aec738 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/OrderNoServiceImpl.java @@ -0,0 +1,50 @@ +package com.webmanage.service.impl; + +import com.webmanage.service.OrderNoService; +import com.webmanage.util.SnowflakeIdWorker; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * 璁㈠崟缂栧彿鏈嶅姟瀹炵幇 + */ +@Service +public class OrderNoServiceImpl implements OrderNoService { + + @Value("${snowflake.worker-id:1}") + private long workerId; + + @Value("${snowflake.datacenter-id:1}") + private long datacenterId; + + @Value("${snowflake.twepoch-ms:1577808000000}") // 2020-01-01 00:00:00 + private long twepochMs; + + private SnowflakeIdWorker idWorker; + + private static final DateTimeFormatter ORDER_PREFIX_FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + @PostConstruct + public void init() { + this.idWorker = new SnowflakeIdWorker(workerId, datacenterId, twepochMs); + } + + @Override + public String generateOrderNo() { + long id = generateSnowflakeId(); + String timePrefix = LocalDateTime.now().format(ORDER_PREFIX_FMT); + // 璁㈠崟鍙锋牸寮忥細鏃堕棿鍓嶇紑 + 闆姳ID鍚�10浣嶏紝淇濊瘉闀垮害涓庢帓搴忓彲璇绘�� + String idStr = String.valueOf(id); + String tail = idStr.length() > 10 ? idStr.substring(idStr.length() - 10) : String.format("%010d", id); + return timePrefix + tail; + } + + @Override + public long generateSnowflakeId() { + return idWorker.nextId(); + } +} diff --git a/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java b/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java new file mode 100644 index 0000000..ac0d99d --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java @@ -0,0 +1,401 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.BusinessException; +import com.webmanage.common.PageResult; +import com.webmanage.dto.AddPointsFlowDTO; +import com.webmanage.dto.PointsFlowQueryDTO; +import com.webmanage.entity.PointsFlow; +import com.webmanage.entity.PointsRule; +import com.webmanage.entity.UserPoints; +import com.webmanage.mapper.PointsFlowMapper; +import com.webmanage.mapper.UserPointsMapper; +import com.webmanage.service.PointsFlowService; +import com.webmanage.service.PointsRuleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 绉垎娴佹按Service瀹炵幇绫� + */ +@Slf4j +@Service +public class PointsFlowServiceImpl extends ServiceImpl<PointsFlowMapper, PointsFlow> implements PointsFlowService { + + @Resource + private UserPointsMapper userPointsMapper; + + @Resource + private PointsRuleService pointsRuleService; + + @Override + public PageResult<PointsFlow> getPersonalPointsFlowPage(PointsFlowQueryDTO queryDTO) { + if (queryDTO.getUserId() == null) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + Page<PointsFlow> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("user_id", queryDTO.getUserId()); + + buildQueryWrapper(wrapper, queryDTO); + + IPage<PointsFlow> result = page(page, wrapper); + + return new PageResult<PointsFlow>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public PageResult<PointsFlow> getUnitPointsFlowPage(PointsFlowQueryDTO queryDTO) { + if (queryDTO.getUnitId() == null) { + throw new BusinessException("鍗曚綅ID涓嶈兘涓虹┖"); + } + + Page<PointsFlow> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("unit_id", queryDTO.getUnitId()); + + buildQueryWrapper(wrapper, queryDTO); + + IPage<PointsFlow> result = page(page, wrapper); + + return new PageResult<PointsFlow>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } + + @Override + public List<PointsFlow> getPointsFlowByUserId(Long userId) { + if (userId == null) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); + } + + QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("user_id", userId) + .orderByDesc("created_at"); + + return list(wrapper); + } + + @Override + public List<PointsFlow> getPointsFlowByUnitId(Long unitId) { + if (unitId == null) { + throw new BusinessException("鍗曚綅ID涓嶈兘涓虹┖"); + } + + QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("unit_id", unitId) + .orderByDesc("created_at"); + + return list(wrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean recordPointsFlow(Long userId, Long unitId, String flowType, String pointsSource, + Integer pointsValue, String orderId, String description) { + if (userId == null || unitId == null || !StringUtils.hasText(flowType) || + !StringUtils.hasText(pointsSource) || pointsValue == null) { + throw new BusinessException("鍙傛暟涓嶅畬鏁�"); + } + + // 鍒涘缓绉垎娴佹按璁板綍 + PointsFlow pointsFlow = new PointsFlow(); + pointsFlow.setUserId(userId); + pointsFlow.setUnitId(unitId); + pointsFlow.setDataType(flowType); + pointsFlow.setDataCategory(pointsSource); + pointsFlow.setPoints(pointsValue); + pointsFlow.setName(description); + pointsFlow.setFlowTime(LocalDateTime.now()); + + boolean saved = save(pointsFlow); + if (!saved) { + throw new BusinessException("淇濆瓨绉垎娴佹按澶辫触"); + } + + // 鏇存柊鐢ㄦ埛绉垎 + updateUserPoints(userId, unitId, pointsValue); + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean addPointsFlowByRule(AddPointsFlowDTO addPointsFlowDTO) { + if (addPointsFlowDTO == null) { + throw new BusinessException("鍙傛暟涓嶈兘涓虹┖"); + } + + Long userId = addPointsFlowDTO.getUserId(); + Long unitId = addPointsFlowDTO.getUnitId(); + String ruleType = addPointsFlowDTO.getRuleType(); + String ruleName = addPointsFlowDTO.getRuleName(); + Integer count = addPointsFlowDTO.getCount() != null ? addPointsFlowDTO.getCount() : 1; + + // 鏌ヨ绉垎瑙勫垯 + PointsRule pointsRule = pointsRuleService.getRuleByTriggerCondition(ruleName); + if (pointsRule == null) { + throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦ㄦ垨鏈惎鐢�: " + ruleName); + } + + // 楠岃瘉瑙勫垯绫诲瀷鏄惁鍖归厤 + if (!ruleType.equals(pointsRule.getRuleType())) { + throw new BusinessException("瑙勫垯绫诲瀷涓嶅尮閰嶏紝鏈熸湜: " + pointsRule.getRuleType() + "锛屽疄闄�: " + ruleType); + } + + // 璁$畻绉垎鍊� + Integer basePoints = pointsRule.getPointsValue() != null ? pointsRule.getPointsValue() : 0; + Integer totalPoints = basePoints * count; + + // 濡傛灉鏄秷璐圭被鍨嬶紝绉垎涓鸿礋鏁� + if ("娑堣垂".equals(ruleType)) { + totalPoints = -totalPoints; + } + + // 妫�鏌ユ瘡鏃ョН鍒嗕笂闄� + if (basePoints > 0 && pointsRule.getPriority() != null && pointsRule.getPriority() > 0) { + checkDailyLimit(userId, unitId, ruleName, totalPoints, pointsRule.getPriority()); + } + + // 鍒涘缓绉垎娴佹按璁板綍 + PointsFlow pointsFlow = new PointsFlow(); + pointsFlow.setUserId(userId); + pointsFlow.setUnitId(unitId); + pointsFlow.setDataType(ruleType); + pointsFlow.setDataCategory(ruleName); + pointsFlow.setPoints(totalPoints); + pointsFlow.setName(addPointsFlowDTO.getDescription() != null ? addPointsFlowDTO.getDescription() : pointsRule.getRuleDescription()); + pointsFlow.setFlowTime(LocalDateTime.now()); + + boolean saved = save(pointsFlow); + if (!saved) { + throw new BusinessException("淇濆瓨绉垎娴佹按澶辫触"); + } + + // 鏇存柊鐢ㄦ埛绉垎璐︽埛 + updateUserPointsByRule(userId, unitId, totalPoints, ruleType); + + return true; + } + + @Override + public Integer getUserPointsTotal(Long userId) { + if (userId == null) { + return 0; + } + + QueryWrapper<UserPoints> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("user_id", userId); + + UserPoints userPoints = userPointsMapper.selectOne(wrapper); + return userPoints != null ? userPoints.getBalance() : 0; + } + + @Override + public Integer getUnitPointsTotal(Long unitId) { + if (unitId == null) { + return 0; + } + + QueryWrapper<UserPoints> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("unit_id", unitId); + + UserPoints userPoints = userPointsMapper.selectOne(wrapper); + return userPoints != null ? userPoints.getBalance() : 0; + } + + /** + * 鏋勫缓鏌ヨ鏉′欢 + */ + private void buildQueryWrapper(QueryWrapper<PointsFlow> wrapper, PointsFlowQueryDTO queryDTO) { + if (StringUtils.hasText(queryDTO.getFlowType())) { + wrapper.eq("flow_type", queryDTO.getFlowType()); + } + if (StringUtils.hasText(queryDTO.getPointsSource())) { + wrapper.eq("points_source", queryDTO.getPointsSource()); + } + if (StringUtils.hasText(queryDTO.getOrderId())) { + wrapper.eq("order_id", queryDTO.getOrderId()); + } + if (queryDTO.getStartTime() != null) { + wrapper.ge("flow_time", queryDTO.getStartTime()); + } + if (queryDTO.getEndTime() != null) { + wrapper.le("flow_time", queryDTO.getEndTime()); + } + + wrapper.orderByDesc("flow_time"); + } + + /** + * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄� + */ + private void checkDailyLimit(Long userId, Long unitId, String ruleName, Integer currentPoints, Integer priority) { + // 鑾峰彇浠婃棩寮�濮嬪拰缁撴潫鏃堕棿 + LocalDate today = LocalDate.now(); + LocalDateTime startOfDay = today.atStartOfDay(); + LocalDateTime endOfDay = today.atTime(23, 59, 59); + + // 鏌ヨ浠婃棩璇ヨ鍒欑殑绉垎娴佹按 + QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("user_id", userId) + .eq("unit_id", unitId) + .eq("data_category", ruleName) + .ge("flow_time", startOfDay) + .le("flow_time", endOfDay); + + List<PointsFlow> todayFlows = list(wrapper); + + // 璁$畻浠婃棩绱绉垎 + int todayTotal = todayFlows.stream() + .mapToInt(flow -> flow.getPoints() != null ? flow.getPoints() : 0) + .sum(); + + // 濡傛灉浠婃棩绱绉垎瓒呰繃浼樺厛绾ч檺鍒讹紝鍒欐姏鍑哄紓甯� + if (Math.abs(todayTotal) >= priority) { + throw new BusinessException("浠婃棩璇ヨ鍒欑Н鍒嗗凡杈句笂闄�: " + priority); + } + } + + /** + * 鏇存柊鐢ㄦ埛绉垎 + */ + private void updateUserPoints(Long userId, Long unitId, Integer pointsValue) { + // 鏇存柊涓汉绉垎 + QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>(); + userWrapper.eq("deleted", 0) + .eq("user_id", userId); + + UserPoints userPoints = userPointsMapper.selectOne(userWrapper); + if (userPoints == null) { + userPoints = new UserPoints(); + userPoints.setUserId(userId); + userPoints.setUnitId(unitId); + userPoints.setBalance(pointsValue); + userPointsMapper.insert(userPoints); + } else { + userPoints.setBalance(userPoints.getBalance() + pointsValue); + userPoints.setUpdateTime(LocalDateTime.now()); + userPointsMapper.updateById(userPoints); + } + + // 鏇存柊鍗曚綅绉垎 + QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>(); + unitWrapper.eq("deleted", 0) + .eq("unit_id", unitId); + + UserPoints unitPoints = userPointsMapper.selectOne(unitWrapper); + if (unitPoints == null) { + unitPoints = new UserPoints(); + unitPoints.setUserId(userId); + unitPoints.setUnitId(unitId); + unitPoints.setBalance(pointsValue); + userPointsMapper.insert(unitPoints); + } else { + unitPoints.setBalance(unitPoints.getBalance() + pointsValue); + unitPoints.setUpdateTime(LocalDateTime.now()); + userPointsMapper.updateById(unitPoints); + } + } + + /** + * 鏍规嵁瑙勫垯鏇存柊鐢ㄦ埛绉垎璐︽埛 + */ + private void updateUserPointsByRule(Long userId, Long unitId, Integer pointsValue, String ruleType) { + // 鏇存柊涓汉绉垎璐︽埛 + QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>(); + userWrapper.eq("deleted", 0) + .eq("user_id", userId); + + UserPoints userPoints = userPointsMapper.selectOne(userWrapper); + if (userPoints == null) { + userPoints = new UserPoints(); + userPoints.setUserId(userId); + userPoints.setUnitId(unitId); + userPoints.setBalance(pointsValue); + userPoints.setTotalEarned(pointsValue > 0 ? pointsValue : 0); + userPoints.setTotalConsumed(pointsValue < 0 ? Math.abs(pointsValue) : 0); + userPointsMapper.insert(userPoints); + } else { + userPoints.setBalance(userPoints.getBalance() + pointsValue); + + // 鏇存柊绱鑾峰彇绉垎 + if (pointsValue > 0) { + userPoints.setTotalEarned(userPoints.getTotalEarned() != null ? + userPoints.getTotalEarned() + pointsValue : pointsValue); + } + + // 鏇存柊绱娑堣�楃Н鍒� + if (pointsValue < 0) { + userPoints.setTotalConsumed(userPoints.getTotalConsumed() != null ? + userPoints.getTotalConsumed() + Math.abs(pointsValue) : Math.abs(pointsValue)); + } + + userPoints.setUpdateTime(LocalDateTime.now()); + userPointsMapper.updateById(userPoints); + } + + // 鏇存柊鍗曚綅绉垎璐︽埛 + QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>(); + unitWrapper.eq("deleted", 0) + .eq("unit_id", unitId); + + UserPoints unitPoints = userPointsMapper.selectOne(unitWrapper); + if (unitPoints == null) { + unitPoints = new UserPoints(); + unitPoints.setUserId(userId); + unitPoints.setUnitId(unitId); + unitPoints.setBalance(pointsValue); + unitPoints.setTotalEarned(pointsValue > 0 ? pointsValue : 0); + unitPoints.setTotalConsumed(pointsValue < 0 ? Math.abs(pointsValue) : 0); + userPointsMapper.insert(unitPoints); + } else { + unitPoints.setBalance(unitPoints.getBalance() + pointsValue); + + // 鏇存柊绱鑾峰彇绉垎 + if (pointsValue > 0) { + unitPoints.setTotalEarned(unitPoints.getTotalEarned() != null ? + unitPoints.getTotalEarned() + pointsValue : pointsValue); + } + + // 鏇存柊绱娑堣�楃Н鍒� + if (pointsValue < 0) { + unitPoints.setTotalConsumed(unitPoints.getTotalConsumed() != null ? + unitPoints.getTotalConsumed() + Math.abs(pointsValue) : Math.abs(pointsValue)); + } + + unitPoints.setUpdateTime(LocalDateTime.now()); + userPointsMapper.updateById(unitPoints); + } + } +} diff --git a/src/main/java/com/webmanage/service/impl/PointsRuleDetailServiceImpl.java b/src/main/java/com/webmanage/service/impl/PointsRuleDetailServiceImpl.java new file mode 100644 index 0000000..657f145 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/PointsRuleDetailServiceImpl.java @@ -0,0 +1,17 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.entity.PointsRuleDetail; +import com.webmanage.mapper.PointsRuleDetailMapper; +import com.webmanage.service.PointsRuleDetailService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 绉垎瑙勫垯璇︽儏Service瀹炵幇绫� + */ +@Slf4j +@Service +public class PointsRuleDetailServiceImpl extends ServiceImpl<PointsRuleDetailMapper, PointsRuleDetail> implements PointsRuleDetailService { + // 绉垎瑙勫垯璇︽儏鐩稿叧涓氬姟閫昏緫瀹炵幇鍙湪姝ゆ坊鍔� +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/service/impl/PointsRuleServiceImpl.java b/src/main/java/com/webmanage/service/impl/PointsRuleServiceImpl.java new file mode 100644 index 0000000..f61054e --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/PointsRuleServiceImpl.java @@ -0,0 +1,185 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.BusinessException; +import com.webmanage.common.PageResult; +import com.webmanage.dto.PointsRuleDTO; +import com.webmanage.entity.Points; +import com.webmanage.entity.PointsRule; +import com.webmanage.entity.PointsRuleDetail; +import com.webmanage.mapper.PointsRuleMapper; +import com.webmanage.service.PointsRuleService; +import com.webmanage.service.PointsService; +import com.webmanage.service.PointsRuleDetailService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 绉垎瑙勫垯Service瀹炵幇绫� + */ +@Slf4j +@Service +public class PointsRuleServiceImpl extends ServiceImpl<PointsRuleMapper, PointsRule> implements PointsRuleService { + + @Autowired + private PointsService pointsService; + + @Autowired + private PointsRuleDetailService pointsRuleDetailService; + + @Override + public PageResult<PointsRule> getPointsRulePage(Integer pageNum, Integer pageSize, String ruleName, String ruleType) { + Page<PointsRule> page = new Page<>(pageNum, pageSize); + + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0); + + if (StringUtils.hasText(ruleName)) { + wrapper.like("rule_name", ruleName); + } + if (StringUtils.hasText(ruleType)) { + wrapper.eq("rule_type", ruleType); + } + + wrapper.orderByDesc("priority", "created_at"); + + IPage<PointsRule> result = page(page, wrapper); + + return new PageResult<PointsRule>( + result.getRecords(), + result.getTotal(), + pageNum.longValue(), + pageSize.longValue(), + result.getPages() + ); + } + + @Override + public boolean addPointsRule(PointsRuleDTO pointsRuleDTO) { + // 楠岃瘉瑙勫垯鍚嶇О鏄惁閲嶅 + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("rule_name", pointsRuleDTO.getRuleName()) + .eq("deleted", 0); + + if (count(wrapper) > 0) { + throw new BusinessException("瑙勫垯鍚嶇О宸插瓨鍦�"); + } + + PointsRule pointsRule = new PointsRule(); + BeanUtils.copyProperties(pointsRuleDTO, pointsRule); + + return save(pointsRule); + } + + @Override + public boolean updatePointsRule(PointsRuleDTO pointsRuleDTO) { + if (pointsRuleDTO.getId() == null) { + throw new BusinessException("瑙勫垯ID涓嶈兘涓虹┖"); + } + + PointsRule existingRule = getById(pointsRuleDTO.getId()); + if (existingRule == null) { + throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦�"); + } + + // 楠岃瘉瑙勫垯鍚嶇О鏄惁閲嶅锛堟帓闄よ嚜韬級 + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("rule_name", pointsRuleDTO.getRuleName()) + .eq("deleted", 0) + .ne("id", pointsRuleDTO.getId()); + + if (count(wrapper) > 0) { + throw new BusinessException("瑙勫垯鍚嶇О宸插瓨鍦�"); + } + + // 鍒涘缓鏂扮殑绉垎涓昏〃璁板綍 + Points points = new Points(); + points.setPointsName(pointsRuleDTO.getRuleName() + "_" + System.currentTimeMillis()); + points.setEffectiveStart(LocalDateTime.now()); + points.setModifierId(1L); // 杩欓噷搴旇浠庝笂涓嬫枃涓幏鍙栧綋鍓嶇敤鎴稩D + points.setModifierName("admin"); // 杩欓噷搴旇浠庝笂涓嬫枃涓幏鍙栧綋鍓嶇敤鎴峰悕 + points.setVersion(1.0f); + points.setStatus(0); + pointsService.save(points); + + // 鍒涘缓绉垎瑙勫垯璇︽儏璁板綍 + PointsRuleDetail pointsRuleDetail = new PointsRuleDetail(); + pointsRuleDetail.setRuleId(pointsRuleDTO.getId()); + pointsRuleDetail.setPointsId(points.getId()); + pointsRuleDetail.setPointsValue(pointsRuleDTO.getPointsValue()); + pointsRuleDetail.setEffectiveStart(LocalDateTime.now()); + pointsRuleDetailService.save(pointsRuleDetail); + + BeanUtils.copyProperties(pointsRuleDTO, existingRule); + existingRule.setUpdatedAt(LocalDateTime.now()); + + return updateById(existingRule); + } + + @Override + public boolean deletePointsRule(Long id) { + if (id == null) { + throw new BusinessException("瑙勫垯ID涓嶈兘涓虹┖"); + } + + PointsRule pointsRule = getById(id); + if (pointsRule == null) { + throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦�"); + } + + return removeById(id); + } + + @Override + public boolean togglePointsRuleStatus(Long id, Boolean isEnabled) { + if (id == null) { + throw new BusinessException("瑙勫垯ID涓嶈兘涓虹┖"); + } + + PointsRule pointsRule = getById(id); + if (pointsRule == null) { + throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦�"); + } + + pointsRule.setIsEnabled(isEnabled); + pointsRule.setUpdatedAt(LocalDateTime.now()); + + return updateById(pointsRule); + } + + @Override + public List<PointsRule> getEnabledRulesByType(String ruleType) { + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("is_enabled", true) + .eq("rule_type", ruleType) + .orderByAsc("priority", "created_at"); + + return list(wrapper); + } + + @Override + public PointsRule getRuleByTriggerCondition(String triggerCondition) { + if (!StringUtils.hasText(triggerCondition)) { + return null; + } + + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("deleted", 0) + .eq("is_enabled", true) + .eq("trigger_condition", triggerCondition) + .orderByAsc("priority") + .last("LIMIT 1"); + + return getOne(wrapper); + } +} diff --git a/src/main/java/com/webmanage/service/impl/PointsServiceImpl.java b/src/main/java/com/webmanage/service/impl/PointsServiceImpl.java new file mode 100644 index 0000000..40a4644 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/PointsServiceImpl.java @@ -0,0 +1,38 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.PageResult; +import com.webmanage.dto.PointsMainQueryDTO; +import com.webmanage.entity.Points; +import com.webmanage.mapper.PointsMapper; +import com.webmanage.service.PointsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 绉垎涓昏〃Service瀹炵幇绫� + */ +@Slf4j +@Service +public class PointsServiceImpl extends ServiceImpl<PointsMapper, Points> implements PointsService { + + @Override + public PageResult<Points> getPointsMainPage(PointsMainQueryDTO queryDTO) { + // 鍒涘缓鍒嗛〉瀵硅薄 + Page<Points> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); + + // 鎵ц鍒嗛〉鏌ヨ + IPage<Points> result = baseMapper.selectPointsMainPage(page, queryDTO); + + // 鏋勫缓杩斿洖缁撴灉 + return new PageResult<Points>( + result.getRecords(), + result.getTotal(), + queryDTO.getPageNum().longValue(), + queryDTO.getPageSize().longValue(), + result.getPages() + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/webmanage/service/impl/ProductPricingServiceImpl.java b/src/main/java/com/webmanage/service/impl/ProductPricingServiceImpl.java new file mode 100644 index 0000000..f14987b --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/ProductPricingServiceImpl.java @@ -0,0 +1,188 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.common.BusinessException; +import com.webmanage.entity.ProductPricing; +import com.webmanage.mapper.ProductPricingMapper; +import com.webmanage.service.ProductPricingService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 浜у搧瀹氫环鏈嶅姟瀹炵幇绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@Slf4j +@Service +public class ProductPricingServiceImpl extends ServiceImpl<ProductPricingMapper, ProductPricing> implements ProductPricingService { + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean addProductPricing(ProductPricing productPricing) { + try { + // 璁剧疆鍒涘缓鏃堕棿 + productPricing.setCreatedAt(LocalDateTime.now()); + productPricing.setUpdatedAt(LocalDateTime.now()); + + // 楠岃瘉蹇呭~瀛楁 + if (!StringUtils.hasText(productPricing.getSuiteName())) { + throw new BusinessException("浜у搧濂椾欢鍚嶇О涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(productPricing.getSalesForm())) { + throw new BusinessException("閿�鍞舰寮忎笉鑳戒负绌�"); + } + if (!StringUtils.hasText(productPricing.getCustomerType())) { + throw new BusinessException("瀹㈡埛瀵硅薄涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(productPricing.getPriceType())) { + throw new BusinessException("浠锋牸璁剧疆涓嶈兘涓虹┖"); + } + if (productPricing.getPrice() == null || productPricing.getPrice().doubleValue() < 0) { + throw new BusinessException("浠锋牸鍊间笉鑳戒负绌轰笖涓嶈兘涓鸿礋鏁�"); + } + if (productPricing.getProductId() == null) { + throw new BusinessException("浜у搧ID涓嶈兘涓虹┖"); + } + + // 璁剧疆榛樿鍊� + if (productPricing.getIsActive() == null) { + productPricing.setIsActive(true); + } + + boolean result = save(productPricing); + if (result) { + log.info("鏂板浜у搧瀹氫环鎴愬姛: {}", productPricing.getSuiteName()); + } + return result; + } catch (Exception e) { + log.error("鏂板浜у搧瀹氫环澶辫触: ", e); + throw new BusinessException("鏂板浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateProductPricing(ProductPricing productPricing) { + try { + // 妫�鏌ュ畾浠锋槸鍚﹀瓨鍦� + ProductPricing existingPricing = getById(productPricing.getId()); + if (existingPricing == null) { + throw new BusinessException("浜у搧瀹氫环涓嶅瓨鍦�"); + } + + // 璁剧疆鏇存柊鏃堕棿 + productPricing.setUpdatedAt(LocalDateTime.now()); + + // 楠岃瘉蹇呭~瀛楁 + if (!StringUtils.hasText(productPricing.getSuiteName())) { + throw new BusinessException("浜у搧濂椾欢鍚嶇О涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(productPricing.getSalesForm())) { + throw new BusinessException("閿�鍞舰寮忎笉鑳戒负绌�"); + } + if (!StringUtils.hasText(productPricing.getCustomerType())) { + throw new BusinessException("瀹㈡埛瀵硅薄涓嶈兘涓虹┖"); + } + if (!StringUtils.hasText(productPricing.getPriceType())) { + throw new BusinessException("浠锋牸璁剧疆涓嶈兘涓虹┖"); + } + if (productPricing.getPrice() == null || productPricing.getPrice().doubleValue() < 0) { + throw new BusinessException("浠锋牸鍊间笉鑳戒负绌轰笖涓嶈兘涓鸿礋鏁�"); + } + + boolean result = updateById(productPricing); + if (result) { + log.info("鏇存柊浜у搧瀹氫环鎴愬姛: {}", productPricing.getSuiteName()); + } + return result; + } catch (Exception e) { + log.error("鏇存柊浜у搧瀹氫环澶辫触: ", e); + throw new BusinessException("鏇存柊浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteProductPricing(Long id) { + try { + // 妫�鏌ュ畾浠锋槸鍚﹀瓨鍦� + ProductPricing existingPricing = getById(id); + if (existingPricing == null) { + throw new BusinessException("浜у搧瀹氫环涓嶅瓨鍦�"); + } + + boolean result = removeById(id); + if (result) { + log.info("鍒犻櫎浜у搧瀹氫环鎴愬姛: {}", existingPricing.getSuiteName()); + } + return result; + } catch (Exception e) { + log.error("鍒犻櫎浜у搧瀹氫环澶辫触: ", e); + throw new BusinessException("鍒犻櫎浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + @Override + public IPage<ProductPricing> getProductPricingPage(Page<ProductPricing> page, Long productId) { + try { + return baseMapper.selectProductPricingPage(page, productId); + } catch (Exception e) { + log.error("鍒嗛〉鏌ヨ浜у搧瀹氫环澶辫触: ", e); + throw new BusinessException("鍒嗛〉鏌ヨ浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } + + @Override + public List<ProductPricing> getPricingByProductId(Long productId) { + try { + if (productId == null) { + throw new BusinessException("浜у搧ID涓嶈兘涓虹┖"); + } + return baseMapper.selectByProductId(productId); + } catch (Exception e) { + log.error("鏍规嵁浜у搧ID鏌ヨ瀹氫环澶辫触: ", e); + throw new BusinessException("鏍规嵁浜у搧ID鏌ヨ瀹氫环澶辫触: " + e.getMessage()); + } + } + + @Override + public List<ProductPricing> getPricingByCondition(String suiteName, String salesForm, + String customerType, String priceType, Boolean isActive) { + try { + QueryWrapper<ProductPricing> queryWrapper = new QueryWrapper<>(); + + if (StringUtils.hasText(suiteName)) { + queryWrapper.like("suite_name", suiteName); + } + if (StringUtils.hasText(salesForm)) { + queryWrapper.eq("sales_form", salesForm); + } + if (StringUtils.hasText(customerType)) { + queryWrapper.eq("customer_type", customerType); + } + if (StringUtils.hasText(priceType)) { + queryWrapper.eq("price_type", priceType); + } + if (isActive != null) { + queryWrapper.eq("is_active", isActive); + } + + queryWrapper.orderByDesc("created_at"); + + return list(queryWrapper); + } catch (Exception e) { + log.error("鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环澶辫触: ", e); + throw new BusinessException("鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环澶辫触: " + e.getMessage()); + } + } +} diff --git a/src/main/java/com/webmanage/service/impl/UserPointsServiceImpl.java b/src/main/java/com/webmanage/service/impl/UserPointsServiceImpl.java new file mode 100644 index 0000000..5b69262 --- /dev/null +++ b/src/main/java/com/webmanage/service/impl/UserPointsServiceImpl.java @@ -0,0 +1,127 @@ +package com.webmanage.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.webmanage.entity.UserPoints; +import com.webmanage.mapper.UserPointsMapper; +import com.webmanage.service.UserPointsService; +import com.webmanage.vo.PointsDetailVO; +import com.webmanage.vo.PointsStatsVO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * 鐢ㄦ埛绉垎Service瀹炵幇绫� + * + * @author webmanage + * @date 2024-08-07 + */ +@Service +public class UserPointsServiceImpl extends ServiceImpl<UserPointsMapper, UserPoints> implements UserPointsService { + + @Override + public PointsStatsVO getPersonalPointsStats(Long userId) { + UserPoints userPoints = this.baseMapper.selectByUserId(userId); + + PointsStatsVO statsVO = new PointsStatsVO(); + if (userPoints != null) { + statsVO.setBalance(userPoints.getBalance()); + statsVO.setTotalEarned(userPoints.getTotalEarned()); + statsVO.setTotalConsumed(userPoints.getTotalConsumed()); + statsVO.setTotalConverted(userPoints.getTotalConverted()); + } else { + statsVO.setBalance(0); + statsVO.setTotalEarned(0); + statsVO.setTotalConsumed(0); + statsVO.setTotalConverted(0); + } + + // 璁剧疆璇︽儏锛堣繖閲屽彲浠ユ牴鎹疄闄呴渶姹傛煡璇㈡暟鎹簱锛� + statsVO.setEarnedDetails(new ArrayList<>()); + statsVO.setConsumedDetails(new ArrayList<>()); + statsVO.setConvertedDetails(new ArrayList<>()); + + return statsVO; + } + + @Override + public PointsStatsVO getUnitPointsStats(Long unitId) { + UserPoints userPoints = this.baseMapper.selectByUnitId(unitId); + + PointsStatsVO statsVO = new PointsStatsVO(); + if (userPoints != null) { + statsVO.setBalance(userPoints.getBalance()); + statsVO.setTotalEarned(userPoints.getTotalEarned()); + statsVO.setTotalConsumed(userPoints.getTotalConsumed()); + statsVO.setTotalConverted(userPoints.getTotalConverted()); + } else { + statsVO.setBalance(0); + statsVO.setTotalEarned(0); + statsVO.setTotalConsumed(0); + statsVO.setTotalConverted(0); + } + + // 璁剧疆鑾峰彇绉垎璇︽儏 + List<PointsDetailVO> earnedDetails = new ArrayList<>(); + earnedDetails.add(createDetailVO("resource_contribution", 10000, 50.0)); + earnedDetails.add(createDetailVO("resource_transaction", 8000, 40.0)); + earnedDetails.add(createDetailVO("resource_dissemination", 1900, 9.5)); + earnedDetails.add(createDetailVO("other", 100, 0.5)); + statsVO.setEarnedDetails(earnedDetails); + + // 璁剧疆娑堣�楃Н鍒嗚鎯� + List<PointsDetailVO> consumedDetails = new ArrayList<>(); + consumedDetails.add(createDetailVO("resource_transaction", 17500, 97.2)); + consumedDetails.add(createDetailVO("resource_dissemination", 500, 2.8)); + statsVO.setConsumedDetails(consumedDetails); + + // 璁剧疆杞崲绉垎璇︽儏 + statsVO.setConvertedDetails(new ArrayList<>()); + + return statsVO; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateUserPoints(Long userId, Long unitId, Integer points) { + // 鏌ヨ鐢ㄦ埛绉垎璁板綍 + LambdaQueryWrapper<UserPoints> wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserPoints::getUserId, userId); + UserPoints userPoints = this.getOne(wrapper); + + if (userPoints == null) { + // 鍒涘缓鏂扮殑绉垎璁板綍 + userPoints = new UserPoints(); + userPoints.setUserId(userId); + userPoints.setUnitId(unitId); + userPoints.setBalance(points > 0 ? points : 0); + userPoints.setTotalEarned(points > 0 ? points : 0); + userPoints.setTotalConsumed(points < 0 ? -points : 0); + userPoints.setTotalConverted(0); + this.save(userPoints); + } else { + // 鏇存柊绉垎璁板綍 + userPoints.setBalance(userPoints.getBalance() + points); + if (points > 0) { + userPoints.setTotalEarned(userPoints.getTotalEarned() + points); + } else { + userPoints.setTotalConsumed(userPoints.getTotalConsumed() - points); + } + this.updateById(userPoints); + } + } + + /** + * 鍒涘缓绉垎璇︽儏VO + */ + private PointsDetailVO createDetailVO(String category, Integer points, Double percentage) { + PointsDetailVO detailVO = new PointsDetailVO(); + detailVO.setCategory(category); + detailVO.setPoints(points); + detailVO.setPercentage(percentage); + return detailVO; + } +} diff --git a/src/main/java/com/webmanage/util/SnowflakeIdWorker.java b/src/main/java/com/webmanage/util/SnowflakeIdWorker.java new file mode 100644 index 0000000..1dadca8 --- /dev/null +++ b/src/main/java/com/webmanage/util/SnowflakeIdWorker.java @@ -0,0 +1,101 @@ +package com.webmanage.util; + +import java.util.concurrent.locks.ReentrantLock; + +/** + * Snowflake 闆姳绠楁硶ID鐢熸垚鍣紙64浣嶏級 + * 缁撴瀯锛�1浣嶇鍙蜂綅 + 41浣嶆椂闂存埑 + 5浣嶆暟鎹腑蹇� + 5浣嶅伐浣滄満鍣� + 12浣嶅簭鍒� + */ +public class SnowflakeIdWorker { + + private final long twepoch; + private final long workerIdBits = 5L; + private final long datacenterIdBits = 5L; + private final long maxWorkerId = -1L ^ (-1L << workerIdBits); + private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + private final long sequenceBits = 12L; + + private final long workerIdShift = sequenceBits; + private final long datacenterIdShift = sequenceBits + workerIdBits; + private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + private final long sequenceMask = -1L ^ (-1L << sequenceBits); + + private final long workerId; + private final long datacenterId; + + private long sequence = 0L; + private long lastTimestamp = -1L; + + private final ReentrantLock lock = new ReentrantLock(true); + + /** + * @param workerId 宸ヤ綔鏈哄櫒ID (0~31) + * @param datacenterId 鏁版嵁涓績ID (0~31) + * @param twepochMs 鑷畾涔夌邯鍏冩椂闂达紙姣锛夛紝寤鸿涓虹郴缁熶笂绾垮墠鍥哄畾鏃堕棿鎴筹紝榛樿 2020-01-01 + */ + public SnowflakeIdWorker(long workerId, long datacenterId, long twepochMs) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException("worker Id can't be greater than " + maxWorkerId + " or less than 0"); + } + if (datacenterId > maxDatacenterId || datacenterId < 0) { + throw new IllegalArgumentException("datacenter Id can't be greater than " + maxDatacenterId + " or less than 0"); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.twepoch = twepochMs; + } + + /** + * 绾跨▼瀹夊叏鐢熸垚涓嬩竴涓狪D + */ + public long nextId() { + lock.lock(); + try { + long timestamp = currentTime(); + + if (timestamp < lastTimestamp) { + // 鏃堕挓鍥炴嫧澶勭悊锛氱瓑寰呭埌 lastTimestamp + long offset = lastTimestamp - timestamp; + try { + Thread.sleep(offset); + } catch (InterruptedException ignored) { } + timestamp = currentTime(); + if (timestamp < lastTimestamp) { + // 濡傛灉浠嶅皬浜庯紝寮哄埗浣跨敤 lastTimestamp + timestamp = lastTimestamp; + } + } + + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + // 鍚屾绉掑唴搴忓垪婧㈠嚭锛岀瓑寰呬笅涓�姣 + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0L; + } + + lastTimestamp = timestamp; + + return ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + } finally { + lock.unlock(); + } + } + + private long tilNextMillis(long lastTimestamp) { + long timestamp = currentTime(); + while (timestamp <= lastTimestamp) { + timestamp = currentTime(); + } + return timestamp; + } + + private long currentTime() { + return System.currentTimeMillis(); + } +} diff --git a/src/main/java/com/webmanage/vo/CartItemVO.java b/src/main/java/com/webmanage/vo/CartItemVO.java new file mode 100644 index 0000000..b41078d --- /dev/null +++ b/src/main/java/com/webmanage/vo/CartItemVO.java @@ -0,0 +1,73 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 璐墿杞﹀晢鍝侀」瑙嗗浘瀵硅薄 + */ +@Data +@ApiModel(value = "CartItemVO", description = "璐墿杞﹀晢鍝侀」淇℃伅") +public class CartItemVO { + + @ApiModelProperty("鍟嗗搧瀹氫环ID") + private Long pricingId; + + @ApiModelProperty("鍟嗗搧ID") + private Long productId; + + @ApiModelProperty("鍟嗗搧鍚嶇О") + private String productName; + + @ApiModelProperty("鍟嗗搧濂椾欢鍚嶇О") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + private Integer duration; + + @ApiModelProperty("灏忚閲戦") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("澶囨敞") + private String remarks; + + @ApiModelProperty("娣诲姞鏃堕棿") + private LocalDateTime addTime; + + @ApiModelProperty("鏈�鍚庢洿鏂版椂闂�") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/webmanage/vo/CartVO.java b/src/main/java/com/webmanage/vo/CartVO.java new file mode 100644 index 0000000..da86729 --- /dev/null +++ b/src/main/java/com/webmanage/vo/CartVO.java @@ -0,0 +1,35 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 璐墿杞﹁鍥惧璞� + */ +@Data +@ApiModel(value = "CartVO", description = "璐墿杞︿俊鎭�") +public class CartVO { + + @ApiModelProperty("鐢ㄦ埛ID") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + private Long unitId; + + @ApiModelProperty("璐墿杞﹀晢鍝侀」鍒楄〃") + private List<CartItemVO> items; + + @ApiModelProperty("鍟嗗搧鎬绘暟閲�") + private Integer totalQuantity; + + @ApiModelProperty("鍟嗗搧鎬婚噾棰�") + private BigDecimal totalAmount; + + @ApiModelProperty("鏈�鍚庢洿鏂版椂闂�") + private LocalDateTime lastUpdateTime; +} diff --git a/src/main/java/com/webmanage/vo/OrderAttachmentVO.java b/src/main/java/com/webmanage/vo/OrderAttachmentVO.java new file mode 100644 index 0000000..c1939eb --- /dev/null +++ b/src/main/java/com/webmanage/vo/OrderAttachmentVO.java @@ -0,0 +1,63 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 璁㈠崟闄勪欢VO + */ +@Data +@ApiModel(value = "OrderAttachmentVO", description = "璁㈠崟闄勪欢") +public class OrderAttachmentVO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + private String orderId; + + @ApiModelProperty("闄勪欢鍚嶇О") + private String fileName; + + @ApiModelProperty("鍘熷鏂囦欢鍚�") + private String originalName; + + @ApiModelProperty("闄勪欢绫诲瀷") + private String fileType; + + @ApiModelProperty("闄勪欢澶у皬(瀛楄妭)") + private Long fileSize; + + @ApiModelProperty("闄勪欢鍦板潃") + private String fileUrl; + + @ApiModelProperty("鏂囦欢瀛樺偍璺緞") + private String filePath; + + @ApiModelProperty("MinIO瀛樺偍妗跺悕绉�") + private String bucketName; + + @ApiModelProperty("MinIO瀵硅薄鍚嶇О") + private String objectName; + + @ApiModelProperty("涓婁紶鐢ㄦ埛ID") + private Long uploadUserId; + + @ApiModelProperty("涓婁紶鐢ㄦ埛鍚�") + private String uploadUserName; + + @ApiModelProperty("闄勪欢绫诲瀷(鍚堝悓/鍙戠エ/鍏朵粬)") + private String attachmentType; + + @ApiModelProperty("闄勪欢鎻忚堪") + private String description; + + @ApiModelProperty("鍒涘缓鏃堕棿") + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/webmanage/vo/OrderDetailItemVO.java b/src/main/java/com/webmanage/vo/OrderDetailItemVO.java new file mode 100644 index 0000000..cce4f5b --- /dev/null +++ b/src/main/java/com/webmanage/vo/OrderDetailItemVO.java @@ -0,0 +1,66 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 璁㈠崟璇︽儏椤筕O + */ +@Data +@ApiModel(value = "OrderDetailItemVO", description = "璁㈠崟璇︽儏椤�") +public class OrderDetailItemVO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("鍏宠仈浜у搧瀹氫环ID") + private Long pricingId; + + @ApiModelProperty("浜у搧ID") + private Long productId; + + @ApiModelProperty("浜у搧濂椾欢鍚嶇О") + private String suiteName; + + @ApiModelProperty("閿�鍞舰寮�") + private String salesForm; + + @ApiModelProperty("瀹㈡埛瀵硅薄") + private String customerType; + + @ApiModelProperty("璐︽埛鏁伴噺") + private String accountLimit; + + @ApiModelProperty("骞跺彂鑺傜偣鏁�") + private String concurrentNodes; + + @ApiModelProperty("浠锋牸绫诲瀷") + private String priceType; + + @ApiModelProperty("浠锋牸鍗曚綅") + private String priceUnit; + + @ApiModelProperty("鍗曚环") + private BigDecimal unitPrice; + + @ApiModelProperty("鏁伴噺") + private Integer quantity; + + @ApiModelProperty("骞撮檺") + private Integer duration; + + @ApiModelProperty("灏忚閲戦") + private BigDecimal totalPrice; + + @ApiModelProperty("浜у搧鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("浜у搧鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("澶囨敞") + private String remarks; +} diff --git a/src/main/java/com/webmanage/vo/OrderDetailVO.java b/src/main/java/com/webmanage/vo/OrderDetailVO.java new file mode 100644 index 0000000..282df60 --- /dev/null +++ b/src/main/java/com/webmanage/vo/OrderDetailVO.java @@ -0,0 +1,83 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 璁㈠崟璇︽儏VO + */ +@Data +@ApiModel(value = "OrderDetailVO", description = "璁㈠崟璇︽儏") +public class OrderDetailVO { + + @ApiModelProperty("璁㈠崟缂栧彿") + private String orderId; + + @ApiModelProperty("浜у搧ID") + private Long productId; + + @ApiModelProperty("鐢ㄦ埛ID") + private Long userId; + + @ApiModelProperty("鍗曚綅ID") + private Long unitId; + + @ApiModelProperty("浜у搧鍚嶇О") + private String productName; + + @ApiModelProperty("鎻愪緵鑰呭悕绉�") + private String providerName; + + @ApiModelProperty("鎻愪緵鑰匢D") + private Long providerId; + + @ApiModelProperty("鐢宠鏃堕棿") + private LocalDateTime applyTime; + + @ApiModelProperty("璁㈠崟鐘舵��") + private String orderStatus; + + @ApiModelProperty("璁㈠崟鎬婚噾棰�") + private BigDecimal totalAmount; + + @ApiModelProperty("鏀粯鏂瑰紡") + private String paymentType; + + @ApiModelProperty("鏀粯鐘舵��") + private String paymentStatus; + + @ApiModelProperty("宸ヤ綔娴両D") + private String workflowId; + + @ApiModelProperty("褰撳墠瀹℃壒姝ラ") + private String currentStep; + + @ApiModelProperty("瀹℃壒娴佺▼閰嶇疆") + private String approvalFlow; + + @ApiModelProperty("涔板澶囨敞") + private String buyerRemarks; + + @ApiModelProperty("鍗栧澶囨敞") + private String sellerRemarks; + + @ApiModelProperty("鍒涘缓鏃堕棿") + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + private LocalDateTime updatedAt; + + @ApiModelProperty("璁㈠崟璇︽儏鍒楄〃") + private List<OrderDetailItemVO> orderDetails; + + @ApiModelProperty("璁㈠崟闄勪欢鍒楄〃") + private List<OrderAttachmentVO> attachments; + + @ApiModelProperty("璁㈠崟璇勪环") + private OrderEvaluationVO evaluation; +} diff --git a/src/main/java/com/webmanage/vo/OrderEvaluationVO.java b/src/main/java/com/webmanage/vo/OrderEvaluationVO.java new file mode 100644 index 0000000..b01dc00 --- /dev/null +++ b/src/main/java/com/webmanage/vo/OrderEvaluationVO.java @@ -0,0 +1,63 @@ +package com.webmanage.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 璁㈠崟璇勪环VO + */ +@Data +@ApiModel(value = "OrderEvaluationVO", description = "璁㈠崟璇勪环") +public class OrderEvaluationVO { + + @ApiModelProperty("涓婚敭ID") + private Long id; + + @ApiModelProperty("鍏宠仈璁㈠崟ID") + private String orderId; + + @ApiModelProperty("璇勪环浜篒D") + private Long evaluatorId; + + @ApiModelProperty("璇勪环浜哄鍚�") + private String evaluatorName; + + @ApiModelProperty("璇勪环浜虹被鍨�") + private String evaluatorType; + + @ApiModelProperty("璇勪环鍐呭") + private String content; + + @ApiModelProperty("璇勫垎(1-5)") + private Integer rating; + + @ApiModelProperty("鏈嶅姟璇勫垎") + private Integer serviceRating; + + @ApiModelProperty("璐ㄩ噺璇勫垎") + private Integer qualityRating; + + @ApiModelProperty("浜や粯璇勫垎") + private Integer deliveryRating; + + @ApiModelProperty("鏄惁鍖垮悕璇勪环") + private Boolean isAnonymous; + + @ApiModelProperty("鍥炲鍐呭") + private String replyContent; + + @ApiModelProperty("鍥炲鐢ㄦ埛ID") + private Long replyUserId; + + @ApiModelProperty("鍥炲鏃堕棿") + private LocalDateTime replyTime; + + @ApiModelProperty("鍒涘缓鏃堕棿") + private LocalDateTime createdAt; + + @ApiModelProperty("鏇存柊鏃堕棿") + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/webmanage/vo/PointsDetailVO.java b/src/main/java/com/webmanage/vo/PointsDetailVO.java new file mode 100644 index 0000000..78a1f64 --- /dev/null +++ b/src/main/java/com/webmanage/vo/PointsDetailVO.java @@ -0,0 +1,28 @@ +package com.webmanage.vo; + +import lombok.Data; + +/** + * 绉垎璇︽儏VO + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +public class PointsDetailVO { + + /** + * 鍒嗙被 + */ + private String category; + + /** + * 绉垎鍊� + */ + private Integer points; + + /** + * 鐧惧垎姣� + */ + private Double percentage; +} diff --git a/src/main/java/com/webmanage/vo/PointsStatsVO.java b/src/main/java/com/webmanage/vo/PointsStatsVO.java new file mode 100644 index 0000000..90c239e --- /dev/null +++ b/src/main/java/com/webmanage/vo/PointsStatsVO.java @@ -0,0 +1,50 @@ +package com.webmanage.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 绉垎缁熻VO + * + * @author webmanage + * @date 2024-08-07 + */ +@Data +public class PointsStatsVO { + + /** + * 绉垎浣欓 + */ + private Integer balance; + + /** + * 绱鑾峰彇 + */ + private Integer totalEarned; + + /** + * 绱娑堣�� + */ + private Integer totalConsumed; + + /** + * 绱杞崲 + */ + private Integer totalConverted; + + /** + * 鑾峰彇绉垎璇︽儏 + */ + private List<PointsDetailVO> earnedDetails; + + /** + * 娑堣�楃Н鍒嗚鎯� + */ + private List<PointsDetailVO> consumedDetails; + + /** + * 杞崲绉垎璇︽儏 + */ + private List<PointsDetailVO> convertedDetails; +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..f12c5d6 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,128 @@ +server: + port: 8080 + servlet: + context-path: /admin + +spring: + application: + name: web-manage-back + + #mcv閰嶇疆 + mvc: + pathmatch: + matching-strategy: ant_path_matcher + + # 鏁版嵁婧愰厤缃� + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://localhost:5432/web_manage?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: postgres + password: postgres + druid: + # 鍒濆杩炴帴鏁� + initial-size: 5 + # 鏈�灏忚繛鎺ユ睜鏁伴噺 + min-idle: 10 + # 鏈�澶ц繛鎺ユ睜鏁伴噺 + max-active: 20 + # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� + max-wait: 60000 + # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 + time-between-eviction-runs-millis: 60000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + min-evictable-idle-time-millis: 300000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + max-evictable-idle-time-millis: 900000 + # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁� + validation-query: SELECT 1 + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 鎵撳紑PSCache锛屽苟涓旀寚瀹氭瘡涓繛鎺ヤ笂PSCache鐨勫ぇ灏� + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + # 閰嶇疆鐩戞帶缁熻鎷︽埅鐨刦ilters锛屽幓鎺夊悗鐩戞帶鐣岄潰sql鏃犳硶缁熻锛�'wall'鐢ㄤ簬闃茬伀澧� + filters: stat,wall,slf4j + # 閫氳繃connectProperties灞炴�ф潵鎵撳紑mergeSql鍔熻兘锛涙參SQL璁板綍 + connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + # 閰嶇疆DruidStatFilter + web-stat-filter: + enabled: true + url-pattern: /* + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 閰嶇疆DruidStatViewServlet + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + login-username: admin + login-password: 123456 + + # Redis閰嶇疆 + redis: + host: localhost + port: 6379 + password: + database: 0 + timeout: 10000ms + lettuce: + pool: + max-active: 8 + max-wait: -1ms + max-idle: 8 + min-idle: 0 + +# MinIO閰嶇疆 +minio: + endpoint: http://localhost:9000 + access-key: minioadmin + secret-key: minioadmin + bucket-name: web-manage + +# MyBatis Plus閰嶇疆 +mybatis-plus: + configuration: + # 寮�鍚┘宄板懡鍚� + map-underscore-to-camel-case: true + # 寮�鍚痵ql鏃ュ織 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + # 涓婚敭绫诲瀷 + id-type: auto + # 閫昏緫鍒犻櫎閰嶇疆 + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + mapper-locations: classpath*:/mapper/**/*.xml + +# 鏃ュ織閰嶇疆 +logging: + level: + com.webmanage: debug + org.springframework.web: debug + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n" + +# Knife4j閰嶇疆 +knife4j: + enable: true + setting: + language: zh-CN + enable-swagger-models: true + enable-document-manage: true + swagger-model-name: 瀹炰綋绫诲垪琛� + basic: + enable: false + +# 璐墿杞﹂厤缃� +cart: + # Redis缂撳瓨杩囨湡鏃堕棿锛堝ぉ锛� + expire-days: 30 + # 鏄惁鍚敤鏁版嵁搴撴寔涔呭寲 + enable-persistence: true + # 鏄惁鍚敤鏁版嵁涓�鑷存�ф鏌� + enable-consistency-check: true + # 鍚屾绛栫暐锛歳ealtime锛堝疄鏃跺悓姝ワ級銆乥atch锛堟壒閲忓悓姝ワ級銆乵anual锛堟墜鍔ㄥ悓姝ワ級 + sync-strategy: realtime diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..88eaa3e --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,133 @@ +server: + port: 8080 + servlet: + context-path: /admin + +spring: + application: + name: web-manage-back + profiles: + active: dev + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + #mcv閰嶇疆 + mvc: + pathmatch: + matching-strategy: ant_path_matcher + + # 鏁版嵁婧愰厤缃� + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://localhost:5432/web_manage?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: postgres + password: zkyxpostgres + druid: + # 鍒濆杩炴帴鏁� + initial-size: 5 + # 鏈�灏忚繛鎺ユ睜鏁伴噺 + min-idle: 10 + # 鏈�澶ц繛鎺ユ睜鏁伴噺 + max-active: 20 + # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� + max-wait: 60000 + # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 + time-between-eviction-runs-millis: 60000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + min-evictable-idle-time-millis: 300000 + # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 + max-evictable-idle-time-millis: 900000 + # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁� + validation-query: SELECT 1 + test-while-idle: true + test-on-borrow: false + test-on-return: false + # 鎵撳紑PSCache锛屽苟涓旀寚瀹氭瘡涓繛鎺ヤ笂PSCache鐨勫ぇ灏� + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + # 閰嶇疆鐩戞帶缁熻鎷︽埅鐨刦ilters锛屽幓鎺夊悗鐩戞帶鐣岄潰sql鏃犳硶缁熻锛�'wall'鐢ㄤ簬闃茬伀澧� + filters: stat,wall,slf4j + # 閫氳繃connectProperties灞炴�ф潵鎵撳紑mergeSql鍔熻兘锛涙參SQL璁板綍 + connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 + # 閰嶇疆DruidStatFilter + web-stat-filter: + enabled: true + url-pattern: /* + exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" + # 閰嶇疆DruidStatViewServlet + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + login-username: admin + login-password: 123456 + + # Redis閰嶇疆 + redis: + host: 192.168.110.129 + port: 6379 + password: + database: 0 + timeout: 10000ms + lettuce: + pool: + max-active: 8 + max-wait: -1ms + max-idle: 8 + min-idle: 0 + +# MinIO閰嶇疆 +minio: + endpoint: http://192.168.110.129:9000 + access-key: minioadmin + secret-key: minioadmin + bucket-name: web-manage + +# MyBatis Plus閰嶇疆 +mybatis-plus: + configuration: + # 寮�鍚┘宄板懡鍚� + map-underscore-to-camel-case: true + # 寮�鍚痵ql鏃ュ織 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + # 涓婚敭绫诲瀷 + id-type: auto + # 閫昏緫鍒犻櫎閰嶇疆 + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + mapper-locations: classpath*:/mapper/**/*.xml + +# 鏃ュ織閰嶇疆 +logging: + level: + com.webmanage: debug + org.springframework.web: debug + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n" + +# Knife4j閰嶇疆 +knife4j: + enable: true + setting: + language: zh-CN + enable-swagger-models: true + enable-document-manage: true + swagger-model-name: 瀹炰綋绫诲垪琛� + basic: + enable: false + +# 璐墿杞﹂厤缃� +cart: + # Redis缂撳瓨杩囨湡鏃堕棿锛堝ぉ锛� + expire-days: 30 + # 鏄惁鍚敤鏁版嵁搴撴寔涔呭寲 + enable-persistence: true + # 鏄惁鍚敤鏁版嵁涓�鑷存�ф鏌� + enable-consistency-check: true + # 鍚屾绛栫暐锛歳ealtime锛堝疄鏃跺悓姝ワ級銆乥atch锛堟壒閲忓悓姝ワ級銆乵anual锛堟墜鍔ㄥ悓姝ワ級 + sync-strategy: realtime diff --git a/src/main/resources/mapper/ApprovalRecordMapper.xml b/src/main/resources/mapper/ApprovalRecordMapper.xml new file mode 100644 index 0000000..11d9bae --- /dev/null +++ b/src/main/resources/mapper/ApprovalRecordMapper.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.ApprovalRecordMapper"> + + <resultMap id="BaseResultMap" type="com.webmanage.entity.ApprovalRecord"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="order_id" property="orderId" jdbcType="VARCHAR"/> + <result column="approver_id" property="approverId" jdbcType="BIGINT"/> + <result column="approver_name" property="approverName" jdbcType="VARCHAR"/> + <result column="approver_role" property="approverRole" jdbcType="VARCHAR"/> + <result column="approval_step" property="approvalStep" jdbcType="VARCHAR"/> + <result column="approval_result" property="approvalResult" jdbcType="VARCHAR"/> + <result column="approval_opinion" property="approvalOpinion" jdbcType="VARCHAR"/> + <result column="approval_time" property="approvalTime" jdbcType="TIMESTAMP"/> + <result column="need_authorization" property="needAuthorization" jdbcType="BOOLEAN"/> + <result column="authorizer_id" property="authorizerId" jdbcType="BIGINT"/> + <result column="authorizer_name" property="authorizerName" jdbcType="VARCHAR"/> + <result column="authorization_time" property="authorizationTime" jdbcType="TIMESTAMP"/> + <result column="authorization_opinion" property="authorizationOpinion" jdbcType="VARCHAR"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <sql id="Base_Column_List"> + id, order_id, approver_id, approver_name, approver_role, approval_step, approval_result, + approval_opinion, approval_time, need_authorization, authorizer_id, authorizer_name, + authorization_time, authorization_opinion, created_at, updated_at, deleted + </sql> + + <select id="selectApprovalRecordPage" resultMap="BaseResultMap"> + SELECT ar.<include refid="Base_Column_List"/> + FROM approval_record ar + LEFT JOIN order_info oi ON ar.order_id = oi.order_id + WHERE ar.deleted = 0 + <if test="orderId != null and orderId != ''"> + AND ar.order_id = #{orderId} + </if> + <if test="productName != null and productName != ''"> + AND oi.product_name LIKE CONCAT('%', #{productName}, '%') + </if> + <if test="providerName != null and providerName != ''"> + AND oi.provider_name LIKE CONCAT('%', #{providerName}, '%') + </if> + <if test="approverId != null"> + AND ar.approver_id = #{approverId} + </if> + <if test="approvalResult != null and approvalResult != ''"> + AND ar.approval_result = #{approvalResult} + </if> + <if test="approvalStep != null and approvalStep != ''"> + AND ar.approval_step = #{approvalStep} + </if> + <if test="needAuthorization != null"> + AND ar.need_authorization = #{needAuthorization} + </if> + <if test="applyTimeStart != null and applyTimeStart != ''"> + AND oi.apply_time >= #{applyTimeStart} + </if> + <if test="applyTimeEnd != null and applyTimeEnd != ''"> + AND oi.apply_time <= #{applyTimeEnd} + </if> + <if test="approvalTimeStart != null and approvalTimeStart != ''"> + AND ar.approval_time >= #{approvalTimeStart} + </if> + <if test="approvalTimeEnd != null and approvalTimeEnd != ''"> + AND ar.approval_time <= #{approvalTimeEnd} + </if> + ORDER BY + <choose> + <when test="orderBy == 'approval_time'">ar.approval_time</when> + <when test="orderBy == 'created_at'">ar.created_at</when> + <otherwise>ar.created_at</otherwise> + </choose> + <choose> + <when test="orderDirection == 'asc'">ASC</when> + <otherwise>DESC</otherwise> + </choose> + </select> + + <select id="selectByOrderId" resultMap="BaseResultMap"> + SELECT <include refid="Base_Column_List"/> + FROM approval_record + WHERE deleted = 0 AND order_id = #{orderId} + ORDER BY created_at ASC + </select> + + <select id="selectPendingApprovalPage" resultMap="BaseResultMap"> + SELECT ar.<include refid="Base_Column_List"/> + FROM approval_record ar + LEFT JOIN order_info oi ON ar.order_id = oi.order_id + WHERE ar.deleted = 0 AND ar.approval_result IS NULL + <if test="orderId != null and orderId != ''"> + AND ar.order_id = #{orderId} + </if> + <if test="productName != null and productName != ''"> + AND oi.product_name LIKE CONCAT('%', #{productName}, '%') + </if> + <if test="providerName != null and providerName != ''"> + AND oi.provider_name LIKE CONCAT('%', #{providerName}, '%') + </if> + <if test="approvalStep != null and approvalStep != ''"> + AND ar.approval_step = #{approvalStep} + </if> + ORDER BY + <choose> + <when test="orderBy == 'approval_time'">ar.approval_time</when> + <when test="orderBy == 'created_at'">ar.created_at</when> + <otherwise>ar.created_at</otherwise> + </choose> + <choose> + <when test="orderDirection == 'asc'">ASC</when> + <otherwise>DESC</otherwise> + </choose> + </select> + +</mapper> diff --git a/src/main/resources/mapper/CartMapper.xml b/src/main/resources/mapper/CartMapper.xml new file mode 100644 index 0000000..086a599 --- /dev/null +++ b/src/main/resources/mapper/CartMapper.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.CartMapper"> + + <resultMap id="BaseResultMap" type="com.webmanage.entity.Cart"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="user_id" property="userId" jdbcType="BIGINT"/> + <result column="unit_id" property="unitId" jdbcType="BIGINT"/> + <result column="pricing_id" property="pricingId" jdbcType="BIGINT"/> + <result column="product_id" property="productId" jdbcType="BIGINT"/> + <result column="product_name" property="productName" jdbcType="VARCHAR"/> + <result column="suite_name" property="suiteName" jdbcType="VARCHAR"/> + <result column="sales_form" property="salesForm" jdbcType="VARCHAR"/> + <result column="customer_type" property="customerType" jdbcType="VARCHAR"/> + <result column="account_limit" property="accountLimit" jdbcType="VARCHAR"/> + <result column="concurrent_nodes" property="concurrentNodes" jdbcType="VARCHAR"/> + <result column="price_type" property="priceType" jdbcType="VARCHAR"/> + <result column="price_unit" property="priceUnit" jdbcType="VARCHAR"/> + <result column="unit_price" property="unitPrice" jdbcType="DECIMAL"/> + <result column="quantity" property="quantity" jdbcType="INTEGER"/> + <result column="duration" property="duration" jdbcType="INTEGER"/> + <result column="total_price" property="totalPrice" jdbcType="DECIMAL"/> + <result column="provider_id" property="providerId" jdbcType="BIGINT"/> + <result column="provider_name" property="providerName" jdbcType="VARCHAR"/> + <result column="remarks" property="remarks" jdbcType="VARCHAR"/> + <result column="add_time" property="addTime" jdbcType="TIMESTAMP"/> + <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <sql id="Base_Column_List"> + id, user_id, unit_id, pricing_id, product_id, product_name, suite_name, sales_form, + customer_type, account_limit, concurrent_nodes, price_type, price_unit, unit_price, + quantity, duration, total_price, provider_id, provider_name, remarks, add_time, + update_time, deleted + </sql> + + <select id="selectByUserIdAndUnitId" resultMap="BaseResultMap"> + SELECT <include refid="Base_Column_List"/> + FROM cart + WHERE deleted = 0 + AND user_id = #{userId} + AND unit_id = #{unitId} + ORDER BY add_time DESC + </select> + + <select id="selectByUserIdUnitIdAndPricingId" resultMap="BaseResultMap"> + SELECT <include refid="Base_Column_List"/> + FROM cart + WHERE deleted = 0 + AND user_id = #{userId} + AND unit_id = #{unitId} + AND pricing_id = #{pricingId} + LIMIT 1 + </select> + + <select id="countByUserIdAndUnitId" resultType="java.lang.Integer"> + SELECT COUNT(*) + FROM cart + WHERE deleted = 0 + AND user_id = #{userId} + AND unit_id = #{unitId} + </select> + + <select id="sumTotalAmountByUserIdAndUnitId" resultType="java.math.BigDecimal"> + SELECT COALESCE(SUM(total_price), 0) + FROM cart + WHERE deleted = 0 + AND user_id = #{userId} + AND unit_id = #{unitId} + </select> + +</mapper> diff --git a/src/main/resources/mapper/OrderAttachmentMapper.xml b/src/main/resources/mapper/OrderAttachmentMapper.xml new file mode 100644 index 0000000..01114a6 --- /dev/null +++ b/src/main/resources/mapper/OrderAttachmentMapper.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.OrderAttachmentMapper"> + + <!-- 鍩虹缁撴灉鏄犲皠 --> + <resultMap id="BaseResultMap" type="com.webmanage.entity.OrderAttachment"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="order_id" property="orderId" jdbcType="VARCHAR"/> + <result column="file_name" property="fileName" jdbcType="VARCHAR"/> + <result column="original_name" property="originalName" jdbcType="VARCHAR"/> + <result column="file_type" property="fileType" jdbcType="VARCHAR"/> + <result column="file_size" property="fileSize" jdbcType="BIGINT"/> + <result column="file_url" property="fileUrl" jdbcType="VARCHAR"/> + <result column="file_path" property="filePath" jdbcType="VARCHAR"/> + <result column="bucket_name" property="bucketName" jdbcType="VARCHAR"/> + <result column="object_name" property="objectName" jdbcType="VARCHAR"/> + <result column="upload_user_id" property="uploadUserId" jdbcType="BIGINT"/> + <result column="upload_user_name" property="uploadUserName" jdbcType="VARCHAR"/> + <result column="attachment_type" property="attachmentType" jdbcType="VARCHAR"/> + <result column="description" property="description" jdbcType="LONGVARCHAR"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <!-- 鍩虹瀛楁鍒楄〃 --> + <sql id="Base_Column_List"> + id, order_id, file_name, original_name, file_type, file_size, file_url, file_path, + bucket_name, object_name, upload_user_id, upload_user_name, attachment_type, + description, created_at, updated_at, deleted + </sql> + + <!-- 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟闄勪欢鍒楄〃 --> + <select id="selectByOrderId" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_attachment + WHERE deleted = 0 AND order_id = #{orderId} + ORDER BY created_at ASC + </select> + +</mapper> diff --git a/src/main/resources/mapper/OrderDetailMapper.xml b/src/main/resources/mapper/OrderDetailMapper.xml new file mode 100644 index 0000000..ccc67f5 --- /dev/null +++ b/src/main/resources/mapper/OrderDetailMapper.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.OrderDetailMapper"> + + <!-- 鍩虹缁撴灉鏄犲皠 --> + <resultMap id="BaseResultMap" type="com.webmanage.entity.OrderDetail"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="order_id" property="orderId" jdbcType="VARCHAR"/> + <result column="pricing_id" property="pricingId" jdbcType="BIGINT"/> + <result column="product_id" property="productId" jdbcType="BIGINT"/> + <result column="suite_name" property="suiteName" jdbcType="VARCHAR"/> + <result column="sales_form" property="salesForm" jdbcType="VARCHAR"/> + <result column="customer_type" property="customerType" jdbcType="VARCHAR"/> + <result column="account_limit" property="accountLimit" jdbcType="VARCHAR"/> + <result column="concurrent_nodes" property="concurrentNodes" jdbcType="VARCHAR"/> + <result column="price_type" property="priceType" jdbcType="VARCHAR"/> + <result column="price_unit" property="priceUnit" jdbcType="VARCHAR"/> + <result column="unit_price" property="unitPrice" jdbcType="NUMERIC"/> + <result column="quantity" property="quantity" jdbcType="INTEGER"/> + <result column="duration" property="duration" jdbcType="INTEGER"/> + <result column="total_price" property="totalPrice" jdbcType="NUMERIC"/> + <result column="provider_id" property="providerId" jdbcType="BIGINT"/> + <result column="provider_name" property="providerName" jdbcType="VARCHAR"/> + <result column="remarks" property="remarks" jdbcType="LONGVARCHAR"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <!-- 鍩虹瀛楁鍒楄〃 --> + <sql id="Base_Column_List"> + id, order_id, pricing_id, product_id, suite_name, sales_form, customer_type, + account_limit, concurrent_nodes, price_type, price_unit, unit_price, quantity, + duration, total_price, provider_id, provider_name, remarks, created_at, updated_at, deleted + </sql> + + <!-- 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟璇︽儏鍒楄〃 --> + <select id="selectByOrderId" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_detail + WHERE deleted = 0 AND order_id = #{orderId} + ORDER BY created_at ASC + </select> + +</mapper> diff --git a/src/main/resources/mapper/OrderEvaluationMapper.xml b/src/main/resources/mapper/OrderEvaluationMapper.xml new file mode 100644 index 0000000..8a22960 --- /dev/null +++ b/src/main/resources/mapper/OrderEvaluationMapper.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.OrderEvaluationMapper"> + + <!-- 鍩虹缁撴灉鏄犲皠 --> + <resultMap id="BaseResultMap" type="com.webmanage.entity.OrderEvaluation"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="order_id" property="orderId" jdbcType="VARCHAR"/> + <result column="evaluator_id" property="evaluatorId" jdbcType="BIGINT"/> + <result column="evaluator_name" property="evaluatorName" jdbcType="VARCHAR"/> + <result column="evaluator_type" property="evaluatorType" jdbcType="VARCHAR"/> + <result column="content" property="content" jdbcType="LONGVARCHAR"/> + <result column="rating" property="rating" jdbcType="INTEGER"/> + <result column="service_rating" property="serviceRating" jdbcType="INTEGER"/> + <result column="quality_rating" property="qualityRating" jdbcType="INTEGER"/> + <result column="delivery_rating" property="deliveryRating" jdbcType="INTEGER"/> + <result column="is_anonymous" property="isAnonymous" jdbcType="BOOLEAN"/> + <result column="reply_content" property="replyContent" jdbcType="LONGVARCHAR"/> + <result column="reply_user_id" property="replyUserId" jdbcType="BIGINT"/> + <result column="reply_time" property="replyTime" jdbcType="TIMESTAMP"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <!-- 鍩虹瀛楁鍒楄〃 --> + <sql id="Base_Column_List"> + id, order_id, evaluator_id, evaluator_name, evaluator_type, content, rating, + service_rating, quality_rating, delivery_rating, is_anonymous, reply_content, + reply_user_id, reply_time, created_at, updated_at, deleted + </sql> + + <!-- 鏍规嵁璁㈠崟ID鏌ヨ璁㈠崟璇勪环 --> + <select id="selectByOrderId" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_evaluation + WHERE deleted = 0 AND order_id = #{orderId} + LIMIT 1 + </select> + +</mapper> diff --git a/src/main/resources/mapper/OrderInfoMapper.xml b/src/main/resources/mapper/OrderInfoMapper.xml new file mode 100644 index 0000000..e1c3538 --- /dev/null +++ b/src/main/resources/mapper/OrderInfoMapper.xml @@ -0,0 +1,193 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.OrderInfoMapper"> + + <!-- 鍩虹缁撴灉鏄犲皠 --> + <resultMap id="BaseResultMap" type="com.webmanage.entity.OrderInfo"> + <id column="order_id" property="orderId" jdbcType="VARCHAR"/> + <result column="product_id" property="productId" jdbcType="BIGINT"/> + <result column="user_id" property="userId" jdbcType="BIGINT"/> + <result column="unit_id" property="unitId" jdbcType="BIGINT"/> + <result column="product_name" property="productName" jdbcType="VARCHAR"/> + <result column="provider_name" property="providerName" jdbcType="VARCHAR"/> + <result column="provider_id" property="providerId" jdbcType="BIGINT"/> + <result column="apply_time" property="applyTime" jdbcType="TIMESTAMP"/> + <result column="order_status" property="orderStatus" jdbcType="VARCHAR"/> + <result column="total_amount" property="totalAmount" jdbcType="NUMERIC"/> + <result column="payment_type" property="paymentType" jdbcType="VARCHAR"/> + <result column="payment_status" property="paymentStatus" jdbcType="VARCHAR"/> + <result column="workflow_id" property="workflowId" jdbcType="VARCHAR"/> + <result column="current_step" property="currentStep" jdbcType="VARCHAR"/> + <result column="approval_flow" property="approvalFlow" jdbcType="LONGVARCHAR"/> + <result column="buyer_remarks" property="buyerRemarks" jdbcType="LONGVARCHAR"/> + <result column="seller_remarks" property="sellerRemarks" jdbcType="LONGVARCHAR"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <!-- 鍩虹瀛楁鍒楄〃 --> + <sql id="Base_Column_List"> + order_id, product_id, user_id, unit_id, product_name, provider_name, provider_id, + apply_time, order_status, total_amount, payment_type, payment_status, workflow_id, + current_step, approval_flow, buyer_remarks, seller_remarks, created_at, updated_at, deleted + </sql> + + <!-- 鍒嗛〉鏌ヨ涔板璁㈠崟鍒楄〃 --> + <select id="selectBuyerOrderPage" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_info + WHERE deleted = 0 + <if test="userId != null"> + AND user_id = #{userId} + </if> + <if test="unitId != null"> + AND unit_id = #{unitId} + </if> + <if test="orderStatus != null and orderStatus != ''"> + AND order_status = #{orderStatus} + </if> + <if test="paymentStatus != null and paymentStatus != ''"> + AND payment_status = #{paymentStatus} + </if> + <if test="paymentType != null and paymentType != ''"> + AND payment_type = #{paymentType} + </if> + <if test="productName != null and productName != ''"> + AND product_name LIKE CONCAT('%', #{productName}, '%') + </if> + <if test="providerName != null and providerName != ''"> + AND provider_name LIKE CONCAT('%', #{providerName}, '%') + </if> + <if test="orderId != null and orderId != ''"> + AND order_id LIKE CONCAT('%', #{orderId}, '%') + </if> + <if test="applyTimeStart != null and applyTimeStart != ''"> + AND apply_time >= #{applyTimeStart}::timestamp + </if> + <if test="applyTimeEnd != null and applyTimeEnd != ''"> + AND apply_time <= #{applyTimeEnd}::timestamp + </if> + <if test="createTimeStart != null and createTimeStart != ''"> + AND created_at >= #{createTimeStart}::timestamp + </if> + <if test="createTimeEnd != null and createTimeEnd != ''"> + AND created_at <= #{createTimeEnd}::timestamp + </if> + ORDER BY + <choose> + <when test="orderBy != null and orderBy != ''"> + ${orderBy} + </when> + <otherwise> + created_at + </otherwise> + </choose> + <choose> + <when test="orderDirection != null and orderDirection == 'asc'"> + ASC + </when> + <otherwise> + DESC + </otherwise> + </choose> + </select> + + <!-- 鍒嗛〉鏌ヨ鍗栧璁㈠崟鍒楄〃 --> + <select id="selectSellerOrderPage" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_info + WHERE deleted = 0 + <if test="providerId != null"> + AND provider_id = #{providerId} + </if> + <if test="orderStatus != null and orderStatus != ''"> + AND order_status = #{orderStatus} + </if> + <if test="paymentStatus != null and paymentStatus != ''"> + AND payment_status = #{paymentStatus} + </if> + <if test="productName != null and productName != ''"> + AND product_name LIKE CONCAT('%', #{productName}, '%') + </if> + <if test="orderId != null and orderId != ''"> + AND order_id LIKE CONCAT('%', #{orderId}, '%') + </if> + <if test="applyTimeStart != null and applyTimeStart != ''"> + AND apply_time >= #{applyTimeStart}::timestamp + </if> + <if test="applyTimeEnd != null and applyTimeEnd != ''"> + AND apply_time <= #{applyTimeEnd}::timestamp + </if> + <if test="createTimeStart != null and createTimeStart != ''"> + AND created_at >= #{createTimeStart}::timestamp + </if> + <if test="createTimeEnd != null and createTimeEnd != ''"> + AND created_at <= #{createTimeEnd}::timestamp + </if> + ORDER BY + <choose> + <when test="orderBy != null and orderBy != ''"> + ${orderBy} + </when> + <otherwise> + created_at + </otherwise> + </choose> + <choose> + <when test="orderDirection != null and orderDirection == 'asc'"> + ASC + </when> + <otherwise> + DESC + </otherwise> + </choose> + </select> + + <!-- 鍒嗛〉鏌ヨ寰呭鎵硅鍗曞垪琛� --> + <select id="selectPendingApprovalOrderPage" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM order_info + WHERE deleted = 0 + AND order_status IN ('寰呭鎵�', '寰呭鎵规巿鏉�', '寰呮巿鏉�') + <if test="orderStatus != null and orderStatus != ''"> + AND order_status = #{orderStatus} + </if> + <if test="productName != null and productName != ''"> + AND product_name LIKE CONCAT('%', #{productName}, '%') + </if> + <if test="providerName != null and providerName != ''"> + AND provider_name LIKE CONCAT('%', #{providerName}, '%') + </if> + <if test="orderId != null and orderId != ''"> + AND order_id LIKE CONCAT('%', #{orderId}, '%') + </if> + <if test="applyTimeStart != null and applyTimeStart != ''"> + AND apply_time >= #{applyTimeStart}::timestamp + </if> + <if test="applyTimeEnd != null and applyTimeEnd != ''"> + AND apply_time <= #{applyTimeEnd}::timestamp + </if> + ORDER BY + <choose> + <when test="orderBy != null and orderBy != ''"> + ${orderBy} + </when> + <otherwise> + created_at + </otherwise> + </choose> + <choose> + <when test="orderDirection != null and orderDirection == 'asc'"> + ASC + </when> + <otherwise> + DESC + </otherwise> + </choose> + </select> + +</mapper> diff --git a/src/main/resources/mapper/PointsFlowMapper.xml b/src/main/resources/mapper/PointsFlowMapper.xml new file mode 100644 index 0000000..9f25c8b --- /dev/null +++ b/src/main/resources/mapper/PointsFlowMapper.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.PointsFlowMapper"> + + <!-- 鍒嗛〉鏌ヨ绉垎娴佹按锛堟敮鎸佺敤鎴�/鍗曚綅缁村害杩囨护锛� --> + <select id="selectPage" resultType="com.webmanage.entity.PointsFlow"> + SELECT * + FROM points_flow + WHERE deleted = 0 + <if test="userId != null"> + AND user_id = #{userId} + </if> + <if test="unitId != null"> + AND unit_id = #{unitId} + </if> + <if test="dataCategory != null and dataCategory != ''"> + AND data_category = #{dataCategory} + </if> + <if test="dataType != null and dataType != ''"> + AND data_type = #{dataType} + </if> + <if test="startTime != null and startTime != ''"> + AND flow_time >= #{startTime}::timestamp + </if> + <if test="endTime != null and endTime != ''"> + AND flow_time <= #{endTime}::timestamp + </if> + <if test="year != null and year != ''"> + AND EXTRACT(YEAR FROM flow_time) = #{year}::integer + </if> + <if test="month != null and month != ''"> + AND EXTRACT(MONTH FROM flow_time) = #{month}::integer + </if> + <if test="day != null and day != ''"> + AND EXTRACT(DAY FROM flow_time) = #{day}::integer + </if> + ORDER BY flow_time DESC + </select> + +</mapper> diff --git a/src/main/resources/mapper/PointsMapper.xml b/src/main/resources/mapper/PointsMapper.xml new file mode 100644 index 0000000..88988e5 --- /dev/null +++ b/src/main/resources/mapper/PointsMapper.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.PointsMapper"> + + <!-- 鍒嗛〉鏌ヨ绉垎涓昏〃 --> + <select id="selectPointsMainPage" resultType="com.webmanage.entity.Points"> + SELECT * + FROM points + WHERE deleted = 0 + <if test="queryDTO.pointsName != null and queryDTO.pointsName != ''"> + AND points_name LIKE CONCAT('%', #{queryDTO.pointsName}, '%') + </if> + <if test="queryDTO.effectiveStartTime != null"> + AND effective_start >= #{queryDTO.effectiveStartTime} + </if> + <if test="queryDTO.effectiveEndTime != null"> + AND effective_start <= #{queryDTO.effectiveEndTime} + </if> + + <if test="queryDTO.modifierName != null and queryDTO.modifierName != ''"> + AND modifier_name LIKE CONCAT('%', #{queryDTO.modifierName}, '%') + </if> + <if test="queryDTO.version != null and queryDTO.version != ''"> + AND version = #{queryDTO.version} + </if> + <if test="queryDTO.status != null and queryDTO.status != ''"> + AND status = #{queryDTO.status} + </if> + <if test="queryDTO.createdAtBegin != null"> + AND created_at >= #{queryDTO.createdAtBegin} + </if> + <if test="queryDTO.createdAtEnd != null"> + AND created_at <= #{queryDTO.createdAtEnd} + </if> + ORDER BY + <choose> + <when test="queryDTO.orderBy != null and queryDTO.orderBy != ''"> + ${queryDTO.orderBy} + </when> + <otherwise> + created_at + </otherwise> + </choose> + <choose> + <when test="queryDTO.orderDirection != null and queryDTO.orderDirection == 'asc'"> + ASC + </when> + <otherwise> + DESC + </otherwise> + </choose> + </select> + +</mapper> \ No newline at end of file diff --git a/src/main/resources/mapper/ProductPricingMapper.xml b/src/main/resources/mapper/ProductPricingMapper.xml new file mode 100644 index 0000000..a9966a7 --- /dev/null +++ b/src/main/resources/mapper/ProductPricingMapper.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.ProductPricingMapper"> + + <!-- 鍩虹缁撴灉鏄犲皠 --> + <resultMap id="BaseResultMap" type="com.webmanage.entity.ProductPricing"> + <id column="id" property="id" jdbcType="BIGINT"/> + <result column="suite_name" property="suiteName" jdbcType="VARCHAR"/> + <result column="sales_form" property="salesForm" jdbcType="VARCHAR"/> + <result column="customer_type" property="customerType" jdbcType="VARCHAR"/> + <result column="account_limit" property="accountLimit" jdbcType="VARCHAR"/> + <result column="concurrent_nodes" property="concurrentNodes" jdbcType="VARCHAR"/> + <result column="price_type" property="priceType" jdbcType="VARCHAR"/> + <result column="price_unit" property="priceUnit" jdbcType="VARCHAR"/> + <result column="price" property="price" jdbcType="NUMERIC"/> + <result column="is_active" property="isActive" jdbcType="BOOLEAN"/> + <result column="product_id" property="productId" jdbcType="BIGINT"/> + <result column="product_name" property="productName" jdbcType="VARCHAR"/> + <result column="provider_id" property="providerId" jdbcType="BIGINT"/> + <result column="provider_name" property="providerName" jdbcType="VARCHAR"/> + <result column="description" property="description" jdbcType="VARCHAR"/> + <result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/> + <result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/> + <result column="created_by" property="createdBy" jdbcType="BIGINT"/> + <result column="updated_by" property="updatedBy" jdbcType="BIGINT"/> + <result column="deleted" property="deleted" jdbcType="INTEGER"/> + </resultMap> + + <!-- 鍩虹瀛楁 --> + <sql id="Base_Column_List"> + id, suite_name, sales_form, customer_type, account_limit, concurrent_nodes, + price_type, price_unit, price, is_active, product_id, product_name, provider_id, + provider_name, description, created_at, updated_at, created_by, updated_by, deleted + </sql> + + <!-- 鍒嗛〉鏌ヨ浜у搧瀹氫环鍒楄〃 --> + <select id="selectProductPricingPage" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM product_pricing + WHERE deleted = 0 + <if test="productId != null"> + AND product_id = #{productId} + </if> + ORDER BY created_at DESC + </select> + + <!-- 鏍规嵁浜у搧ID鏌ヨ瀹氫环鍒楄〃 --> + <select id="selectByProductId" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM product_pricing + WHERE deleted = 0 AND product_id = #{productId} + ORDER BY created_at DESC + </select> + + <!-- 鏍规嵁鏉′欢鏌ヨ浜у搧瀹氫环 --> + <select id="selectByCondition" resultMap="BaseResultMap"> + SELECT + <include refid="Base_Column_List"/> + FROM product_pricing + WHERE deleted = 0 + <if test="suiteName != null and suiteName != ''"> + AND suite_name LIKE CONCAT('%', #{suiteName}, '%') + </if> + <if test="salesForm != null and salesForm != ''"> + AND sales_form = #{salesForm} + </if> + <if test="customerType != null and customerType != ''"> + AND customer_type = #{customerType} + </if> + <if test="priceType != null and priceType != ''"> + AND price_type = #{priceType} + </if> + <if test="isActive != null"> + AND is_active = #{isActive} + </if> + ORDER BY created_at DESC + </select> + +</mapper> diff --git a/src/main/resources/mapper/UserPointsMapper.xml b/src/main/resources/mapper/UserPointsMapper.xml new file mode 100644 index 0000000..081cd84 --- /dev/null +++ b/src/main/resources/mapper/UserPointsMapper.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.webmanage.mapper.UserPointsMapper"> + + <!-- 鏍规嵁鐢ㄦ埛ID鏌ヨ绉垎淇℃伅 --> + <select id="selectByUserId" resultType="com.webmanage.entity.UserPoints"> + SELECT * + FROM user_points + WHERE user_id = #{userId} + AND deleted = 0 + LIMIT 1 + </select> + + <!-- 鏍规嵁鍗曚綅ID鏌ヨ绉垎淇℃伅 --> + <select id="selectByUnitId" resultType="com.webmanage.entity.UserPoints"> + SELECT * + FROM user_points + WHERE unit_id = #{unitId} + AND deleted = 0 + LIMIT 1 + </select> + +</mapper> diff --git a/src/main/resources/sql/init.sql b/src/main/resources/sql/init.sql new file mode 100644 index 0000000..61931d9 --- /dev/null +++ b/src/main/resources/sql/init.sql @@ -0,0 +1,501 @@ +-- 浜ゆ槗妯″潡鏁版嵁搴撹〃鍒涘缓鑴氭湰 (PostgreSQL 鐗堟湰) +-- 鍒涘缓鏃堕棿: 2024-08-07 + +-- 鍒涘缓椤哄簭璋冩暣: 鍏堝垱寤哄熀纭�琛� (unit, users, product)锛屽啀鍒涘缓渚濊禆瀹冧滑鐨勮〃 + +-- 15. 鍗曚綅琛� (unit) +CREATE TABLE unit ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + unit_name TEXT NOT NULL, + unit_code TEXT UNIQUE, + unit_type TEXT, + industry TEXT, + address TEXT, + contact_person TEXT, + contact_phone TEXT, + contact_email TEXT, + business_license TEXT, + legal_person TEXT, + registered_capital NUMERIC(15,2), + establishment_date DATE, + status TEXT DEFAULT '姝e父' CHECK (status IN ('姝e父', '鍐荤粨', '娉ㄩ攢')), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE unit IS '鍗曚綅琛�'; + +-- 14. 鐢ㄦ埛琛� (users) - 閬垮厤鍏抽敭瀛楀啿绐� +CREATE TABLE users ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + username TEXT NOT NULL UNIQUE, + real_name TEXT, + email TEXT, + phone TEXT, + avatar TEXT, + user_type TEXT DEFAULT '涓汉鐢ㄦ埛' CHECK (user_type IN ('涓汉鐢ㄦ埛', '鍗曚綅鐢ㄦ埛')), + unit_id BIGINT REFERENCES unit(id), + unit_name TEXT, + status TEXT DEFAULT '姝e父' CHECK (status IN ('姝e父', '鍐荤粨', '娉ㄩ攢')), + last_login_time TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE users IS '鐢ㄦ埛琛�'; + +-- 13. 浜у搧琛� (product) +CREATE TABLE product ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + product_name TEXT NOT NULL, + product_code TEXT NOT NULL UNIQUE, + product_type TEXT, + category TEXT, + description TEXT, + provider_id BIGINT NOT NULL REFERENCES users(id), + provider_name TEXT NOT NULL, + provider_type TEXT CHECK (provider_type IN ('浼佷笟', '涓汉')), + status TEXT DEFAULT '涓婃灦' CHECK (status IN ('涓婃灦', '涓嬫灦', '瀹℃牳涓�', '宸蹭笅鏋�')), + audit_status TEXT DEFAULT '寰呭鏍�' CHECK (audit_status IN ('寰呭鏍�', '瀹℃牳閫氳繃', '瀹℃牳椹冲洖')), + tags TEXT, + cover_image TEXT, + demo_url TEXT, + doc_url TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by BIGINT REFERENCES users(id), + updated_by BIGINT REFERENCES users(id), + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE product IS '浜у搧琛�'; + +-- 1. 浜у搧瀹氫环琛� (product_pricing) +CREATE TABLE product_pricing ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + suite_name TEXT NOT NULL, + sales_form TEXT NOT NULL CHECK (sales_form IN ('涔版柇', '绉熻祦', '绉佹湁澧炲寘閲�', '鍏湁澧炲寘閲�', 'OTA鏈嶅姟', '璧勬簮鍖�', '涓汉')), + customer_type TEXT NOT NULL CHECK (customer_type IN ('浼佷笟', '涓汉', '椤圭洰閮�')), + account_limit TEXT DEFAULT '涓嶉檺', + concurrent_nodes TEXT DEFAULT '涓嶉檺', + price_type TEXT NOT NULL CHECK (price_type IN ('绉垎', '鍗忚', '璐у竵', '鍏嶈垂')), + price_unit TEXT NOT NULL CHECK (price_unit IN ('濂�', '濂�/骞�', '骞�', '涓�', '娆�')), + price NUMERIC(15,2) NOT NULL, + is_active BOOLEAN DEFAULT TRUE, + product_id BIGINT NOT NULL REFERENCES product(id), + product_name TEXT, + provider_id BIGINT REFERENCES users(id), + provider_name TEXT, + description TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by BIGINT REFERENCES users(id), + updated_by BIGINT REFERENCES users(id), + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE product_pricing IS '浜у搧瀹氫环琛�'; + +-- 绉垎琛� (points) - 闇�鍦ㄧН鍒嗚鍒欏墠鍒涘缓 +-- 绉垎琛� (points) - 涓昏〃 +CREATE TABLE points ( + id BIGSERIAL PRIMARY KEY, + points_name TEXT NOT NULL, + effective_start DATE NOT NULL, + modifier_id BIGINT NOT NULL, + modifier_name TEXT NOT NULL, + version TEXT NOT NULL, + description TEXT, + status TEXT DEFAULT '鍚敤', + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + deleted SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE points IS '绉垎涓昏〃'; +COMMENT ON COLUMN points.points_name IS '绉垎鍚嶇О'; +COMMENT ON COLUMN points.effective_start IS '鐢熸晥寮�濮嬫椂闂�'; +COMMENT ON COLUMN points.modifier_id IS '淇敼浜篒D'; +COMMENT ON COLUMN points.modifier_name IS '淇敼浜哄鍚�'; +COMMENT ON COLUMN points.version IS '鐗堟湰鍙�'; +COMMENT ON COLUMN points.description IS '绉垎鎻忚堪'; +COMMENT ON COLUMN points.status IS '鐘舵��'; +COMMENT ON COLUMN points.created_at IS '鍒涘缓鏃堕棿'; +COMMENT ON COLUMN points.updated_at IS '鏇存柊鏃堕棿'; +COMMENT ON COLUMN points.deleted IS '閫昏緫鍒犻櫎'; +ALTER TABLE points ADD CONSTRAINT chk_status CHECK (status IN ('鍚敤', '绂佺敤')); +ALTER TABLE points ADD CONSTRAINT chk_deleted CHECK (deleted IN (0,1)); + +-- 绉垎瑙勫垯琛� (points_rule) +CREATE TABLE points_rule ( + id BIGSERIAL PRIMARY KEY, + points_id BIGINT NOT NULL, + rule_type TEXT NOT NULL, + category TEXT NOT NULL, + rule_name TEXT NOT NULL, + rule_description TEXT, + status TEXT DEFAULT '鍚敤', + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + deleted SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE points_rule IS '绉垎瑙勫垯琛�'; +COMMENT ON COLUMN points_rule.points_id IS '鍏宠仈绉垎ID'; +COMMENT ON COLUMN points_rule.rule_type IS '绉垎瑙勫垯绫诲瀷'; +COMMENT ON COLUMN points_rule.category IS '绉垎绫诲埆'; +COMMENT ON COLUMN points_rule.rule_name IS '瑙勫垯鍚嶇О'; +COMMENT ON COLUMN points_rule.rule_description IS '瑙勫垯鎻忚堪'; +COMMENT ON COLUMN points_rule.status IS '瑙勫垯鐘舵��'; +COMMENT ON COLUMN points_rule.created_at IS '鍒涘缓鏃堕棿'; +COMMENT ON COLUMN points_rule.updated_at IS '鏇存柊鏃堕棿'; +COMMENT ON COLUMN points_rule.deleted IS '閫昏緫鍒犻櫎'; +ALTER TABLE points_rule ADD CONSTRAINT fk_points FOREIGN KEY (points_id) REFERENCES points(id); +ALTER TABLE points_rule ADD CONSTRAINT chk_rule_type CHECK (rule_type IN ('鑾峰彇', '娑堣��')); +ALTER TABLE points_rule ADD CONSTRAINT chk_category CHECK (category IN ('璧勬簮璐$尞', '璧勬簮浼犳挱', '璧勬簮浜ゆ槗', '浜ゆ祦绀惧尯浜掑姩')); +ALTER TABLE points_rule ADD CONSTRAINT chk_rule_status CHECK (status IN ('鍚敤', '绂佺敤')); +ALTER TABLE points_rule ADD CONSTRAINT chk_rule_deleted CHECK (deleted IN (0,1)); + +-- 绉垎瑙勫垯璇︽儏琛� (points_rule_detail) +CREATE TABLE points_rule_detail ( + id BIGSERIAL PRIMARY KEY, + rule_id BIGINT NOT NULL, + points_id BIGINT NOT NULL, + points_value INTEGER NOT NULL, + daily_limit INTEGER, + monthly_limit INTEGER, + yearly_limit INTEGER, + min_value INTEGER DEFAULT 0, + max_value INTEGER, + conversion_rate NUMERIC(10,4) DEFAULT 1.0, + effective_start DATE, + effective_end DATE, + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + deleted SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE points_rule_detail IS '绉垎瑙勫垯璇︽儏琛�'; +COMMENT ON COLUMN points_rule_detail.rule_id IS '鍏宠仈绉垎瑙勫垯ID'; +COMMENT ON COLUMN points_rule_detail.points_id IS '鍏宠仈绉垎ID'; +COMMENT ON COLUMN points_rule_detail.points_value IS '绉垎鍊�'; +COMMENT ON COLUMN points_rule_detail.daily_limit IS '姣忔棩绉垎涓婇檺鍊�'; +COMMENT ON COLUMN points_rule_detail.monthly_limit IS '姣忔湀绉垎涓婇檺鍊�'; +COMMENT ON COLUMN points_rule_detail.yearly_limit IS '姣忓勾绉垎涓婇檺鍊�'; +COMMENT ON COLUMN points_rule_detail.min_value IS '鏈�灏忓��'; +COMMENT ON COLUMN points_rule_detail.max_value IS '鏈�澶у��'; +COMMENT ON COLUMN points_rule_detail.conversion_rate IS '杞崲姣旂巼'; +COMMENT ON COLUMN points_rule_detail.effective_start IS '鐢熸晥寮�濮嬫椂闂�'; +COMMENT ON COLUMN points_rule_detail.effective_end IS '鐢熸晥缁撴潫鏃堕棿'; +COMMENT ON COLUMN points_rule_detail.created_at IS '鍒涘缓鏃堕棿'; +COMMENT ON COLUMN points_rule_detail.updated_at IS '鏇存柊鏃堕棿'; +COMMENT ON COLUMN points_rule_detail.deleted IS '閫昏緫鍒犻櫎'; +ALTER TABLE points_rule_detail ADD CONSTRAINT fk_rule FOREIGN KEY (rule_id) REFERENCES points_rule(id); +ALTER TABLE points_rule_detail ADD CONSTRAINT fk_detail_points FOREIGN KEY (points_id) REFERENCES points(id); +ALTER TABLE points_rule_detail ADD CONSTRAINT chk_detail_deleted CHECK (deleted IN (0,1)); + +-- 绉垎娴佹按琛� (points_transaction) +CREATE TABLE points_transaction ( + id BIGSERIAL PRIMARY KEY, + data_category TEXT NOT NULL, + transaction_name TEXT NOT NULL, + transaction_time TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + points_change INTEGER NOT NULL, + rule_type TEXT NOT NULL, + user_id BIGINT, + unit_id BIGINT, + user_type TEXT NOT NULL, + rule_id BIGINT, + detail_id BIGINT, + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + deleted SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE points_transaction IS '绉垎娴佹按琛�'; +COMMENT ON COLUMN points_transaction.data_category IS '鏁版嵁绫荤洰'; +COMMENT ON COLUMN points_transaction.transaction_name IS '鍚嶇О'; +COMMENT ON COLUMN points_transaction.transaction_time IS '鏃堕棿'; +COMMENT ON COLUMN points_transaction.points_change IS '绉垎鍙樺姩鍊�'; +COMMENT ON COLUMN points_transaction.rule_type IS '绉垎瑙勫垯绫诲瀷'; +COMMENT ON COLUMN points_transaction.user_id IS '鐢ㄦ埛ID'; +COMMENT ON COLUMN points_transaction.unit_id IS '浼佷笟ID'; +COMMENT ON COLUMN points_transaction.user_type IS '鐢ㄦ埛绫诲瀷'; +COMMENT ON COLUMN points_transaction.rule_id IS '鍏宠仈瑙勫垯ID'; +COMMENT ON COLUMN points_transaction.detail_id IS '鍏宠仈瑙勫垯璇︽儏ID'; +COMMENT ON COLUMN points_transaction.created_at IS '鍒涘缓鏃堕棿'; +COMMENT ON COLUMN points_transaction.deleted IS '閫昏緫鍒犻櫎'; +ALTER TABLE points_transaction ADD CONSTRAINT chk_data_category CHECK (data_category IN ('鐢ㄦ埛鍙備笌', '鍏朵粬')); +ALTER TABLE points_transaction ADD CONSTRAINT chk_trans_rule_type CHECK (rule_type IN ('鑾峰彇', '娑堣��')); +ALTER TABLE points_transaction ADD CONSTRAINT chk_user_type CHECK (user_type IN ('鍗曚綅鐢ㄦ埛', '涓汉鐢ㄦ埛')); +ALTER TABLE points_transaction ADD CONSTRAINT fk_rule_id FOREIGN KEY (rule_id) REFERENCES points_rule(id); +ALTER TABLE points_transaction ADD CONSTRAINT fk_detail_id FOREIGN KEY (detail_id) REFERENCES points_rule_detail(id); +ALTER TABLE points_transaction ADD CONSTRAINT chk_trans_deleted CHECK (deleted IN (0,1)); + +-- 绉垎璐︽埛琛� (points_account) +CREATE TABLE points_account ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + points_balance INTEGER NOT NULL DEFAULT 0, + total_earned INTEGER NOT NULL DEFAULT 0, + total_consumed INTEGER NOT NULL DEFAULT 0, + account_type TEXT NOT NULL, + account_status TEXT DEFAULT '姝e父', + last_transaction_time TIMESTAMPTZ, + created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + deleted SMALLINT DEFAULT 0 +); + +COMMENT ON TABLE points_account IS '绉垎璐︽埛琛�'; +COMMENT ON COLUMN points_account.user_id IS '鐢ㄦ埛ID'; +COMMENT ON COLUMN points_account.points_balance IS '绉垎浣欓'; +COMMENT ON COLUMN points_account.total_earned IS '绱鑾峰彇绉垎'; +COMMENT ON COLUMN points_account.total_consumed IS '绱娑堣�楃Н鍒�'; +COMMENT ON COLUMN points_account.account_type IS '璐︽埛绫诲瀷'; +COMMENT ON COLUMN points_account.account_status IS '璐︽埛鐘舵��'; +COMMENT ON COLUMN points_account.last_transaction_time IS '鏈�鍚庝氦鏄撴椂闂�'; +COMMENT ON COLUMN points_account.created_at IS '鍒涘缓鏃堕棿'; +COMMENT ON COLUMN points_account.updated_at IS '鏇存柊鏃堕棿'; +COMMENT ON COLUMN points_account.deleted IS '閫昏緫鍒犻櫎'; +ALTER TABLE points_account ADD CONSTRAINT chk_account_type CHECK (account_type IN ('涓汉绉垎', '鍗曚綅绉垎')); +ALTER TABLE points_account ADD CONSTRAINT chk_account_status CHECK (account_status IN ('姝e父', '鍐荤粨', '娉ㄩ攢')); +ALTER TABLE points_account ADD CONSTRAINT chk_account_deleted CHECK (deleted IN (0,1)); + +-- 鍒涘缓绱㈠紩 +CREATE INDEX idx_points_rule_points ON points_rule(points_id); +CREATE INDEX idx_points_rule_type ON points_rule(rule_type); +CREATE INDEX idx_points_detail_rule ON points_rule_detail(rule_id); +CREATE INDEX idx_transaction_user ON points_transaction(user_id); +CREATE INDEX idx_transaction_time ON points_transaction(transaction_time); +CREATE INDEX idx_account_user ON points_account(user_id); + +-- 2. 璐墿杞﹁〃 (shopping_cart) +-- CREATE TABLE shopping_cart ( +-- id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, +-- user_id BIGINT NOT NULL REFERENCES users(id), +-- unit_id BIGINT REFERENCES unit(id), +-- suite_name TEXT NOT NULL, +-- sales_form TEXT NOT NULL CHECK (sales_form IN ('涔版柇', '绉熻祦', '绉佹湁澧炲寘閲�', '鍏湁澧炲寘閲�', 'OTA鏈嶅姟', '璧勬簮鍖�', '涓汉')), +-- customer_type TEXT NOT NULL CHECK (customer_type IN ('浼佷笟', '涓汉', '椤圭洰閮�')), +-- account_limit TEXT DEFAULT '涓嶉檺', +-- concurrent_nodes TEXT DEFAULT '涓嶉檺', +-- price_type TEXT NOT NULL CHECK (price_type IN ('绉垎', '鍗忚', '璐у竵', '鍏嶈垂')), +-- price_unit TEXT NOT NULL CHECK (price_unit IN ('濂�', '濂�/骞�', '骞�', '涓�', '娆�')), +-- unit_price NUMERIC(15,2) NOT NULL, +-- quantity INTEGER NOT NULL DEFAULT 1, +-- duration INTEGER, +-- product_id BIGINT NOT NULL REFERENCES product(id), +-- product_name TEXT, +-- provider_id BIGINT REFERENCES users(id), +-- provider_name TEXT, +-- total_amount NUMERIC(15,2), +-- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +-- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +-- deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +-- ); +-- +-- COMMENT ON TABLE shopping_cart IS '璐墿杞﹁〃'; + +-- 璐墿杞﹁〃 (cart) +CREATE TABLE cart ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + user_id BIGINT NOT NULL REFERENCES users(id), + unit_id BIGINT NOT NULL REFERENCES unit(id), + pricing_id BIGINT NOT NULL REFERENCES product_pricing(id), + product_id BIGINT NOT NULL REFERENCES product(id), + product_name TEXT, + suite_name TEXT, + sales_form TEXT, + customer_type TEXT, + account_limit TEXT, + concurrent_nodes TEXT, + price_type TEXT, + price_unit TEXT, + unit_price DECIMAL(15,2) NOT NULL, + quantity INTEGER NOT NULL DEFAULT 1, + duration INTEGER, + total_price DECIMAL(15,2), + provider_id BIGINT REFERENCES users(id), + provider_name TEXT, + remarks TEXT, + add_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)), + UNIQUE (user_id, unit_id, pricing_id, deleted) +); + +COMMENT ON TABLE cart IS '璐墿杞﹁〃'; + +-- 3. 璁㈠崟琛� (order_info) +CREATE TABLE order_info ( + order_id TEXT PRIMARY KEY, + product_id BIGINT NOT NULL REFERENCES product(id), + user_id BIGINT NOT NULL REFERENCES users(id), + unit_id BIGINT REFERENCES unit(id), + product_name TEXT NOT NULL, + provider_name TEXT NOT NULL, + provider_id BIGINT NOT NULL REFERENCES users(id), + apply_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + order_status TEXT NOT NULL DEFAULT '寰呭鎵�' CHECK (order_status IN ('寰呭鎵�', '寰呭鎵规巿鏉�', '寰呮巿鏉�', '寰呬笂浼犳枃浠�', '寰呬氦鏄撶‘璁�', '宸插畬鎴�', '宸插彇娑�', '宸查┏鍥�')), + total_amount NUMERIC(15,2) NOT NULL, + payment_type TEXT CHECK (payment_type IN ('绉垎', '璐у竵', '鍗忚')), + payment_status TEXT DEFAULT '鏈敮浠�' CHECK (payment_status IN ('鏈敮浠�', '宸叉敮浠�', '鏀粯澶辫触', '宸查��娆�')), + workflow_id TEXT, + current_step TEXT, + approval_flow TEXT, + buyer_remarks TEXT, + seller_remarks TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE order_info IS '璁㈠崟琛�'; + +-- 4. 璁㈠崟璇︽儏琛� (order_detail) +CREATE TABLE order_detail ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + order_id TEXT NOT NULL REFERENCES order_info(order_id), + pricing_id BIGINT NOT NULL REFERENCES product_pricing(id), + product_id BIGINT NOT NULL REFERENCES product(id), + suite_name TEXT NOT NULL, + sales_form TEXT NOT NULL, + customer_type TEXT NOT NULL, + account_limit TEXT, + concurrent_nodes TEXT, + price_type TEXT NOT NULL, + price_unit TEXT NOT NULL, + unit_price NUMERIC(15,2) NOT NULL, + quantity INTEGER NOT NULL, + duration INTEGER, + total_price NUMERIC(15,2) NOT NULL, + provider_id BIGINT NOT NULL REFERENCES users(id), + provider_name TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + remarks TEXT, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE order_detail IS '璁㈠崟璇︽儏琛�'; + +-- 5. 璁㈠崟闄勪欢琛� (order_attachment) +CREATE TABLE order_attachment ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + order_id TEXT NOT NULL REFERENCES order_info(order_id), + file_name TEXT NOT NULL, + original_name TEXT, + file_type TEXT NOT NULL, + file_size BIGINT NOT NULL, + file_url TEXT NOT NULL, + file_path TEXT, + bucket_name TEXT, + object_name TEXT, + upload_user_id BIGINT REFERENCES users(id), + upload_user_name TEXT, + attachment_type TEXT CHECK (attachment_type IN ('鍚堝悓', '鍙戠エ', '鍏朵粬')), + description TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE order_attachment IS '璁㈠崟闄勪欢琛�'; + +-- 6. 璁㈠崟瀹℃牳琛� (order_approval) +CREATE TABLE order_approval ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + order_id TEXT NOT NULL REFERENCES order_info(order_id), + approval_step TEXT NOT NULL, + approval_type TEXT NOT NULL CHECK (approval_type IN ('瀹℃壒', '鎺堟潈')), + approval_opinion TEXT, + approval_result TEXT NOT NULL CHECK (approval_result IN ('閫氳繃', '椹冲洖', '寰呭鐞�')), + approver_id BIGINT NOT NULL REFERENCES users(id), + approver_name TEXT NOT NULL, + approver_role TEXT, + approval_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + next_approver_id BIGINT REFERENCES users(id), + next_approver_name TEXT, + workflow_status TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE order_approval IS '璁㈠崟瀹℃牳琛�'; + +-- 7. 璁㈠崟璇勪环琛� (order_evaluation) +CREATE TABLE order_evaluation ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + order_id TEXT NOT NULL REFERENCES order_info(order_id), + evaluator_id BIGINT NOT NULL REFERENCES users(id), + evaluator_name TEXT NOT NULL, + evaluator_type TEXT NOT NULL CHECK (evaluator_type IN ('涔板', '鍗栧')), + content TEXT NOT NULL, + rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5), + service_rating INTEGER CHECK (service_rating >= 1 AND service_rating <= 5), + quality_rating INTEGER CHECK (quality_rating >= 1 AND quality_rating <= 5), + delivery_rating INTEGER CHECK (delivery_rating >= 1 AND delivery_rating <= 5), + is_anonymous BOOLEAN DEFAULT FALSE, + reply_content TEXT, + reply_user_id BIGINT REFERENCES users(id), + reply_time TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + deleted INTEGER DEFAULT 0 CHECK (deleted IN (0,1)) +); + +COMMENT ON TABLE order_evaluation IS '璁㈠崟璇勪环琛�'; + +-- 鍒涘缓绱㈠紩 (PostgreSQL 璇硶) +CREATE INDEX idx_product_pricing_product_id ON product_pricing(product_id); +CREATE INDEX idx_product_pricing_status ON product_pricing(is_active); +CREATE INDEX idx_order_info_user_id ON order_info(user_id); +CREATE INDEX idx_order_info_provider_id ON order_info(provider_id); +CREATE INDEX idx_order_info_status ON order_info(order_status); +CREATE INDEX idx_order_info_apply_time ON order_info(apply_time); +CREATE INDEX idx_order_detail_order_id ON order_detail(order_id); +CREATE INDEX idx_order_attachment_order_id ON order_attachment(order_id); +CREATE INDEX idx_order_approval_order_id ON order_approval(order_id); +CREATE INDEX idx_order_approval_approver_id ON order_approval(approver_id); +CREATE INDEX idx_order_evaluation_order_id ON order_evaluation(order_id); +CREATE INDEX idx_order_evaluation_evaluator_id ON order_evaluation(evaluator_id); +CREATE INDEX idx_points_rule_points_id ON points_rule(points_id); +CREATE INDEX idx_points_rule_detail_rule_id ON points_rule_detail(rule_id); +CREATE INDEX idx_product_provider_id ON product(provider_id); +CREATE INDEX idx_product_status ON product(status); +CREATE INDEX idx_users_unit_id ON users(unit_id); +CREATE INDEX idx_users_status ON users(status); + +-- 璐墿杞﹁〃绱㈠紩 +CREATE INDEX idx_cart_user_unit ON cart(user_id, unit_id, deleted); +CREATE INDEX idx_cart_pricing ON cart(pricing_id, deleted); +CREATE INDEX idx_cart_product ON cart(product_id, deleted); +CREATE INDEX idx_cart_provider ON cart(provider_id, deleted); +CREATE INDEX idx_cart_add_time ON cart(add_time, deleted); + +-- 娣诲姞鍒楁敞閲� (PostgreSQL 鏂瑰紡) +COMMENT ON COLUMN product_pricing.suite_name IS '浜у搧濂椾欢鍚嶇О'; +COMMENT ON COLUMN product_pricing.sales_form IS '閿�鍞舰寮�'; +-- 鍏朵粬鍒楁敞閲婃寜鐩稿悓鏍煎紡琛ュ厖... + + +INSERT INTO unit (unit_name, unit_code, unit_type, industry, status) VALUES +('娴嬭瘯浼佷笟', 'TEST_ENTERPRISE', '浼佷笟', '淇℃伅鎶�鏈�', '姝e父'), +('娴嬭瘯鍗曚綅', 'TEST_UNIT', '浜嬩笟鍗曚綅', '鏁欒偛', '姝e父'); + +INSERT INTO users (username, real_name, user_type, unit_id, status) VALUES +('admin', '绯荤粺绠$悊鍛�', '涓汉鐢ㄦ埛', NULL, '姝e父'), +('test_user', '娴嬭瘯鐢ㄦ埛', '涓汉鐢ㄦ埛', 1, '姝e父'), +('test_provider', '娴嬭瘯鎻愪緵鑰�', '鍗曚綅鐢ㄦ埛', 1, '姝e父'); + +INSERT INTO product (product_name, product_code, product_type, category, description, provider_id, provider_name, status, audit_status) VALUES +('娴嬭瘯浜у搧1', 'TEST_PRODUCT_001', '杞欢浜у搧', '浼佷笟绠$悊', '杩欐槸涓�涓祴璇曚骇鍝�', 3, '娴嬭瘯鎻愪緵鑰�', '涓婃灦', '瀹℃牳閫氳繃'), +('娴嬭瘯浜у搧2', 'TEST_PRODUCT_002', '鏈嶅姟浜у搧', '鎶�鏈湇鍔�', '杩欐槸鍙︿竴涓祴璇曚骇鍝�', 3, '娴嬭瘯鎻愪緵鑰�', '涓婃灦', '瀹℃牳閫氳繃'); + +INSERT INTO product_pricing (suite_name, sales_form, customer_type, price_type, price_unit, price, product_id, product_name, provider_id, provider_name, is_active) VALUES +('鍩虹鐗�', '涔版柇', '浼佷笟', '绉垎', '濂�', 1000, 1, '娴嬭瘯浜у搧1', 3, '娴嬭瘯鎻愪緵鑰�', true), +('涓撲笟鐗�', '绉熻祦', '浼佷笟', '绉垎', '濂�/骞�', 500, 1, '娴嬭瘯浜у搧1', 3, '娴嬭瘯鎻愪緵鑰�', true), +('浼佷笟鐗�', '涔版柇', '浼佷笟', '璐у竵', '濂�', 10000, 2, '娴嬭瘯浜у搧2', 3, '娴嬭瘯鎻愪緵鑰�', true); diff --git a/src/main/resources/sql/trade_module.sql b/src/main/resources/sql/trade_module.sql new file mode 100644 index 0000000..93e02a5 --- /dev/null +++ b/src/main/resources/sql/trade_module.sql @@ -0,0 +1,403 @@ +-- 浜ゆ槗妯″潡鏁版嵁搴撹〃鍒涘缓鑴氭湰 +-- 鍒涘缓鏃堕棿: 2024-08-07 +-- 鏁版嵁搴�: PostgreSQL + +-- 1. 浜у搧瀹氫环琛� (product_pricing) +CREATE TABLE product_pricing ( + id BIGSERIAL PRIMARY KEY, + suite_name VARCHAR(100) NOT NULL COMMENT '浜у搧濂椾欢鍚嶇О', + sales_form VARCHAR(20) NOT NULL CHECK (sales_form IN ('涔版柇', '绉熻祦', '绉佹湁澧炲寘閲�', '鍏湁澧炲寘閲�', 'OTA鏈嶅姟', '璧勬簮鍖�', '涓汉')) COMMENT '閿�鍞舰寮�', + customer_type VARCHAR(10) NOT NULL CHECK (customer_type IN ('浼佷笟', '涓汉', '椤圭洰閮�')) COMMENT '瀹㈡埛瀵硅薄', + account_limit VARCHAR(20) DEFAULT '涓嶉檺' COMMENT '璐︽埛鏁伴噺', + concurrent_nodes VARCHAR(20) DEFAULT '涓嶉檺' COMMENT '骞跺彂鑺傜偣鏁�', + price_type VARCHAR(10) NOT NULL CHECK (price_type IN ('绉垎', '鍗忚', '璐у竵', '鍏嶈垂')) COMMENT '浠锋牸璁剧疆', + price_unit VARCHAR(20) NOT NULL CHECK (price_unit IN ('濂�', '濂�/骞�', '骞�', '涓�', '娆�')) COMMENT '浠锋牸鍗曚綅', + price NUMERIC(15,2) NOT NULL COMMENT '浠锋牸鍊�', + is_active BOOLEAN DEFAULT TRUE COMMENT '鍚敤鐘舵��', + product_id BIGINT NOT NULL COMMENT '鍏宠仈浜у搧ID', + product_name VARCHAR(100) COMMENT '浜у搧鍚嶇О', + provider_id BIGINT COMMENT '浜у搧鎻愪緵鑰匢D', + provider_name VARCHAR(100) COMMENT '浜у搧鎻愪緵鑰呭悕绉�', + description TEXT COMMENT '浜у搧鎻忚堪', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + created_by BIGINT COMMENT '鍒涘缓浜篒D', + updated_by BIGINT COMMENT '鏇存柊浜篒D', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 2. 璐墿杞﹁〃 (shopping_cart) +CREATE TABLE shopping_cart ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL COMMENT '鐢ㄦ埛ID', + unit_id BIGINT COMMENT '鍗曚綅ID', + suite_name VARCHAR(100) NOT NULL COMMENT '浜у搧濂椾欢鍚嶇О', + sales_form VARCHAR(20) NOT NULL CHECK (sales_form IN ('涔版柇', '绉熻祦', '绉佹湁澧炲寘閲�', '鍏湁澧炲寘閲�', 'OTA鏈嶅姟', '璧勬簮鍖�', '涓汉')) COMMENT '閿�鍞舰寮�', + customer_type VARCHAR(10) NOT NULL CHECK (customer_type IN ('浼佷笟', '涓汉', '椤圭洰閮�')) COMMENT '瀹㈡埛瀵硅薄', + account_limit VARCHAR(20) DEFAULT '涓嶉檺' COMMENT '璐︽埛鏁伴噺', + concurrent_nodes VARCHAR(20) DEFAULT '涓嶉檺' COMMENT '骞跺彂鑺傜偣鏁�', + price_type VARCHAR(10) NOT NULL CHECK (price_type IN ('绉垎', '鍗忚', '璐у竵', '鍏嶈垂')) COMMENT '浠锋牸绫诲瀷', + price_unit VARCHAR(20) NOT NULL CHECK (price_unit IN ('濂�', '濂�/骞�', '骞�', '涓�', '娆�')) COMMENT '浠锋牸鍗曚綅', + unit_price NUMERIC(15,2) NOT NULL COMMENT '鍗曚环', + quantity INTEGER NOT NULL DEFAULT 1 COMMENT '鏁伴噺', + duration INTEGER COMMENT '鏈熼檺(骞�)', + product_id BIGINT NOT NULL COMMENT '浜у搧ID', + product_name VARCHAR(100) COMMENT '浜у搧鍚嶇О', + provider_id BIGINT COMMENT '浜у搧鎻愪緵鑰匢D', + provider_name VARCHAR(100) COMMENT '浜у搧鎻愪緵鑰呭悕绉�', + total_amount NUMERIC(15,2) COMMENT '鎬婚噾棰�', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 璐墿杞﹁〃 +CREATE TABLE IF NOT EXISTS cart ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL COMMENT '鐢ㄦ埛ID', + unit_id BIGINT NOT NULL COMMENT '鍗曚綅ID', + pricing_id BIGINT NOT NULL COMMENT '鍟嗗搧瀹氫环ID', + product_id BIGINT NOT NULL COMMENT '鍟嗗搧ID', + product_name VARCHAR(255) COMMENT '鍟嗗搧鍚嶇О', + suite_name VARCHAR(255) COMMENT '鍟嗗搧濂椾欢鍚嶇О', + sales_form VARCHAR(100) COMMENT '閿�鍞舰寮�', + customer_type VARCHAR(100) COMMENT '瀹㈡埛瀵硅薄', + account_limit VARCHAR(100) COMMENT '璐︽埛鏁伴噺', + concurrent_nodes VARCHAR(100) COMMENT '骞跺彂鑺傜偣鏁�', + price_type VARCHAR(100) COMMENT '浠锋牸绫诲瀷', + price_unit VARCHAR(100) COMMENT '浠锋牸鍗曚綅', + unit_price DECIMAL(15,2) NOT NULL COMMENT '鍗曚环', + quantity INTEGER NOT NULL DEFAULT 1 COMMENT '鏁伴噺', + duration INTEGER COMMENT '骞撮檺', + total_price DECIMAL(15,2) COMMENT '灏忚閲戦', + provider_id BIGINT COMMENT '浜у搧鎻愪緵鑰匢D', + provider_name VARCHAR(255) COMMENT '浜у搧鎻愪緵鑰呭悕绉�', + remarks TEXT COMMENT '澶囨敞', + add_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '娣诲姞鏃堕棿', + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�', + UNIQUE KEY uk_user_unit_pricing (user_id, unit_id, pricing_id, deleted) +); + +-- 3. 璁㈠崟琛� (order_info) +CREATE TABLE order_info ( + order_id VARCHAR(50) PRIMARY KEY COMMENT '璁㈠崟缂栧彿', + product_id BIGINT NOT NULL COMMENT '浜у搧ID', + user_id BIGINT NOT NULL COMMENT '鐢ㄦ埛ID', + unit_id BIGINT COMMENT '鍗曚綅ID', + product_name VARCHAR(100) NOT NULL COMMENT '浜у搧鍚嶇О', + provider_name VARCHAR(100) NOT NULL COMMENT '浜у搧鎻愪緵鑰呭悕绉�', + provider_id BIGINT NOT NULL COMMENT '鎻愪緵鑰匢D', + apply_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鐢宠鏃堕棿', + order_status VARCHAR(20) NOT NULL DEFAULT '寰呭鎵�' CHECK (order_status IN ('寰呭鎵�', '寰呭鎵规巿鏉�', '寰呮巿鏉�', '寰呬笂浼犳枃浠�', '寰呬氦鏄撶‘璁�', '宸插畬鎴�', '宸插彇娑�', '宸查┏鍥�')) COMMENT '璁㈠崟鐘舵��', + total_amount NUMERIC(15,2) NOT NULL COMMENT '璁㈠崟鎬婚噾棰�', + payment_type VARCHAR(20) COMMENT '鏀粯鏂瑰紡(绉垎/璐у竵/鍗忚)', + payment_status VARCHAR(20) DEFAULT '鏈敮浠�' CHECK (payment_status IN ('鏈敮浠�', '宸叉敮浠�', '鏀粯澶辫触', '宸查��娆�')) COMMENT '鏀粯鐘舵��', + workflow_id VARCHAR(50) COMMENT '宸ヤ綔娴両D', + current_step VARCHAR(50) COMMENT '褰撳墠瀹℃壒姝ラ', + approval_flow TEXT COMMENT '瀹℃壒娴佺▼閰嶇疆', + buyer_remarks TEXT COMMENT '涔板澶囨敞', + seller_remarks TEXT COMMENT '鍗栧澶囨敞', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 4. 璁㈠崟璇︽儏琛� (order_detail) +CREATE TABLE order_detail ( + id BIGSERIAL PRIMARY KEY, + order_id VARCHAR(50) NOT NULL COMMENT '鍏宠仈璁㈠崟ID', + pricing_id BIGINT NOT NULL COMMENT '鍏宠仈浜у搧瀹氫环ID', + product_id BIGINT NOT NULL COMMENT '浜у搧ID', + suite_name VARCHAR(100) NOT NULL COMMENT '浜у搧濂椾欢鍚嶇О', + sales_form VARCHAR(20) NOT NULL COMMENT '閿�鍞舰寮�', + customer_type VARCHAR(10) NOT NULL COMMENT '瀹㈡埛瀵硅薄', + account_limit VARCHAR(20) COMMENT '璐︽埛鏁伴噺', + concurrent_nodes VARCHAR(20) COMMENT '骞跺彂鑺傜偣鏁�', + price_type VARCHAR(10) NOT NULL COMMENT '浠锋牸绫诲瀷', + price_unit VARCHAR(20) NOT NULL COMMENT '浠锋牸鍗曚綅', + unit_price NUMERIC(15,2) NOT NULL COMMENT '鍗曚环', + quantity INTEGER NOT NULL COMMENT '鏁伴噺', + duration INTEGER COMMENT '骞撮檺', + total_price NUMERIC(15,2) NOT NULL COMMENT '灏忚閲戦', + provider_id BIGINT NOT NULL COMMENT '浜у搧鎻愪緵鑰匢D', + provider_name VARCHAR(100) COMMENT '浜у搧鎻愪緵鑰呭悕绉�', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + remarks TEXT COMMENT '澶囨敞', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 5. 璁㈠崟闄勪欢琛� (order_attachment) +CREATE TABLE order_attachment ( + id BIGSERIAL PRIMARY KEY, + order_id VARCHAR(50) NOT NULL COMMENT '鍏宠仈璁㈠崟ID', + file_name VARCHAR(255) NOT NULL COMMENT '闄勪欢鍚嶇О', + original_name VARCHAR(255) COMMENT '鍘熷鏂囦欢鍚�', + file_type VARCHAR(50) NOT NULL COMMENT '闄勪欢绫诲瀷', + file_size BIGINT NOT NULL COMMENT '闄勪欢澶у皬(瀛楄妭)', + file_url VARCHAR(500) NOT NULL COMMENT '闄勪欢鍦板潃', + file_path VARCHAR(500) COMMENT '鏂囦欢瀛樺偍璺緞', + bucket_name VARCHAR(100) COMMENT 'MinIO瀛樺偍妗跺悕绉�', + object_name VARCHAR(500) COMMENT 'MinIO瀵硅薄鍚嶇О', + upload_user_id BIGINT COMMENT '涓婁紶鐢ㄦ埛ID', + upload_user_name VARCHAR(100) COMMENT '涓婁紶鐢ㄦ埛鍚�', + attachment_type VARCHAR(50) COMMENT '闄勪欢绫诲瀷(鍚堝悓/鍙戠エ/鍏朵粬)', + description TEXT COMMENT '闄勪欢鎻忚堪', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 6. 璁㈠崟瀹℃牳琛� (order_approval) +CREATE TABLE order_approval ( + id BIGSERIAL PRIMARY KEY, + order_id VARCHAR(50) NOT NULL COMMENT '鍏宠仈璁㈠崟ID', + approval_step VARCHAR(50) NOT NULL COMMENT '瀹℃壒姝ラ', + approval_type VARCHAR(20) NOT NULL CHECK (approval_type IN ('瀹℃壒', '鎺堟潈')) COMMENT '瀹℃壒绫诲瀷', + approval_opinion TEXT COMMENT '瀹℃牳鎰忚', + approval_result VARCHAR(20) NOT NULL CHECK (approval_result IN ('閫氳繃', '椹冲洖', '寰呭鐞�')) COMMENT '瀹℃壒缁撴灉', + approver_id BIGINT NOT NULL COMMENT '瀹℃牳浜篒D', + approver_name VARCHAR(100) NOT NULL COMMENT '瀹℃牳浜哄鍚�', + approver_role VARCHAR(100) COMMENT '瀹℃牳浜鸿鑹�', + approval_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '瀹℃牳鏃堕棿', + next_approver_id BIGINT COMMENT '涓嬩竴瀹℃壒浜篒D', + next_approver_name VARCHAR(100) COMMENT '涓嬩竴瀹℃壒浜哄鍚�', + workflow_status VARCHAR(20) COMMENT '宸ヤ綔娴佺姸鎬�', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 7. 璁㈠崟璇勪环琛� (order_evaluation) +CREATE TABLE order_evaluation ( + id BIGSERIAL PRIMARY KEY, + order_id VARCHAR(50) NOT NULL COMMENT '鍏宠仈璁㈠崟ID', + evaluator_id BIGINT NOT NULL COMMENT '璇勪环浜篒D', + evaluator_name VARCHAR(100) NOT NULL COMMENT '璇勪环浜哄鍚�', + evaluator_type VARCHAR(20) NOT NULL CHECK (evaluator_type IN ('涔板', '鍗栧')) COMMENT '璇勪环浜虹被鍨�', + content TEXT NOT NULL COMMENT '璇勪环鍐呭', + rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5) COMMENT '璇勫垎(1-5)', + service_rating INTEGER CHECK (service_rating >= 1 AND service_rating <= 5) COMMENT '鏈嶅姟璇勫垎', + quality_rating INTEGER CHECK (quality_rating >= 1 AND quality_rating <= 5) COMMENT '璐ㄩ噺璇勫垎', + delivery_rating INTEGER CHECK (delivery_rating >= 1 AND delivery_rating <= 5) COMMENT '浜や粯璇勫垎', + is_anonymous BOOLEAN DEFAULT FALSE COMMENT '鏄惁鍖垮悕璇勪环', + reply_content TEXT COMMENT '鍥炲鍐呭', + reply_user_id BIGINT COMMENT '鍥炲鐢ㄦ埛ID', + reply_time TIMESTAMP COMMENT '鍥炲鏃堕棿', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 8. 绉垎琛� (points) +CREATE TABLE points ( + id BIGSERIAL PRIMARY KEY, + points_name VARCHAR(100) NOT NULL COMMENT '绉垎鍚嶇О', + points_code VARCHAR(50) NOT NULL UNIQUE COMMENT '绉垎缂栫爜', + points_type VARCHAR(20) NOT NULL CHECK (points_type IN ('涓汉绉垎', '鍗曚綅绉垎', '浜у搧绉垎')) COMMENT '绉垎绫诲瀷', + effective_start DATE NOT NULL COMMENT '鐢熸晥寮�濮嬫椂闂�', + effective_end DATE COMMENT '鐢熸晥缁撴潫鏃堕棿', + modifier_id BIGINT NOT NULL COMMENT '淇敼浜篒D', + modifier_name VARCHAR(100) NOT NULL COMMENT '淇敼浜哄鍚�', + version VARCHAR(20) NOT NULL COMMENT '鐗堟湰鍙�', + description TEXT COMMENT '绉垎鎻忚堪', + status VARCHAR(10) DEFAULT '鍚敤' CHECK (status IN ('鍚敤', '绂佺敤')) COMMENT '鐘舵��', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 9. 绉垎瑙勫垯琛� (points_rule) - 鏇存柊鐜版湁琛ㄧ粨鏋� +ALTER TABLE points_rule ADD COLUMN IF NOT EXISTS points_id BIGINT COMMENT '鍏宠仈绉垎ID'; +ALTER TABLE points_rule ADD COLUMN IF NOT EXISTS rule_code VARCHAR(50) COMMENT '瑙勫垯缂栫爜'; +ALTER TABLE points_rule ADD COLUMN IF NOT EXISTS effective_start DATE COMMENT '鐢熸晥寮�濮嬫椂闂�'; +ALTER TABLE points_rule ADD COLUMN IF NOT EXISTS effective_end DATE COMMENT '鐢熸晥缁撴潫鏃堕棿'; +ALTER TABLE points_rule ADD COLUMN IF NOT EXISTS priority INTEGER DEFAULT 0 COMMENT '浼樺厛绾�'; + +-- 10. 绉垎瑙勫垯璇︽儏琛� (points_rule_detail) +CREATE TABLE points_rule_detail ( + id BIGSERIAL PRIMARY KEY, + rule_id BIGINT NOT NULL COMMENT '鍏宠仈绉垎瑙勫垯ID', + points_id BIGINT NOT NULL COMMENT '鍏宠仈绉垎ID', + points_value INTEGER NOT NULL COMMENT '绉垎鍊�', + daily_limit INTEGER COMMENT '姣忔棩绉垎涓婇檺鍊�', + monthly_limit INTEGER COMMENT '姣忔湀绉垎涓婇檺鍊�', + yearly_limit INTEGER COMMENT '姣忓勾绉垎涓婇檺鍊�', + min_value INTEGER DEFAULT 0 COMMENT '鏈�灏忓��', + max_value INTEGER COMMENT '鏈�澶у��', + conversion_rate NUMERIC(10,4) DEFAULT 1.0 COMMENT '杞崲姣旂巼', + effective_start DATE COMMENT '鐢熸晥寮�濮嬫椂闂�', + effective_end DATE COMMENT '鐢熸晥缁撴潫鏃堕棿', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 11. 绉垎娴佹按琛� (points_transaction) - 鏂板瀛楁 +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS transaction_type VARCHAR(20) COMMENT '浜ゆ槗绫诲瀷(鑾峰彇/娑堣��/杞崲)'; +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS related_id VARCHAR(50) COMMENT '鍏宠仈涓氬姟ID'; +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS related_type VARCHAR(50) COMMENT '鍏宠仈涓氬姟绫诲瀷'; +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS balance_after INTEGER COMMENT '鍙樺姩鍚庝綑棰�'; +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS operator_id BIGINT COMMENT '鎿嶄綔浜篒D'; +ALTER TABLE points_flow ADD COLUMN IF NOT EXISTS operator_name VARCHAR(100) COMMENT '鎿嶄綔浜哄鍚�'; + +-- 12. 绉垎璐︽埛琛� (points_account) - 鏇存柊鐜版湁琛ㄧ粨鏋� +ALTER TABLE user_points ADD COLUMN IF NOT EXISTS account_type VARCHAR(20) DEFAULT '涓汉绉垎' COMMENT '璐︽埛绫诲瀷(涓汉绉垎/鍗曚綅绉垎)'; +ALTER TABLE user_points ADD COLUMN IF NOT EXISTS account_status VARCHAR(20) DEFAULT '姝e父' COMMENT '璐︽埛鐘舵��(姝e父/鍐荤粨/娉ㄩ攢)'; +ALTER TABLE user_points ADD COLUMN IF NOT EXISTS last_transaction_time TIMESTAMP COMMENT '鏈�鍚庝氦鏄撴椂闂�'; + +-- 13. 浜у搧琛� (product) - 鏂板浜у搧鍩虹琛� +CREATE TABLE product ( + id BIGSERIAL PRIMARY KEY, + product_name VARCHAR(100) NOT NULL COMMENT '浜у搧鍚嶇О', + product_code VARCHAR(50) NOT NULL UNIQUE COMMENT '浜у搧缂栫爜', + product_type VARCHAR(50) COMMENT '浜у搧绫诲瀷', + category VARCHAR(100) COMMENT '浜у搧鍒嗙被', + description TEXT COMMENT '浜у搧鎻忚堪', + provider_id BIGINT NOT NULL COMMENT '鎻愪緵鑰匢D', + provider_name VARCHAR(100) NOT NULL COMMENT '鎻愪緵鑰呭悕绉�', + provider_type VARCHAR(20) COMMENT '鎻愪緵鑰呯被鍨�(浼佷笟/涓汉)', + status VARCHAR(20) DEFAULT '涓婃灦' CHECK (status IN ('涓婃灦', '涓嬫灦', '瀹℃牳涓�', '宸蹭笅鏋�')) COMMENT '浜у搧鐘舵��', + audit_status VARCHAR(20) DEFAULT '寰呭鏍�' CHECK (audit_status IN ('寰呭鏍�', '瀹℃牳閫氳繃', '瀹℃牳椹冲洖')) COMMENT '瀹℃牳鐘舵��', + tags TEXT COMMENT '浜у搧鏍囩(JSON鏍煎紡)', + cover_image VARCHAR(500) COMMENT '灏侀潰鍥剧墖', + demo_url VARCHAR(500) COMMENT '婕旂ず鍦板潃', + doc_url VARCHAR(500) COMMENT '鏂囨。鍦板潃', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + created_by BIGINT COMMENT '鍒涘缓浜篒D', + updated_by BIGINT COMMENT '鏇存柊浜篒D', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 14. 鐢ㄦ埛琛� (user) - 鏂板鐢ㄦ埛鍩虹琛� +CREATE TABLE user ( + id BIGSERIAL PRIMARY KEY, + username VARCHAR(100) NOT NULL UNIQUE COMMENT '鐢ㄦ埛鍚�', + real_name VARCHAR(100) COMMENT '鐪熷疄濮撳悕', + email VARCHAR(100) COMMENT '閭', + phone VARCHAR(20) COMMENT '鎵嬫満鍙�', + avatar VARCHAR(500) COMMENT '澶村儚', + user_type VARCHAR(20) DEFAULT '涓汉鐢ㄦ埛' CHECK (user_type IN ('涓汉鐢ㄦ埛', '鍗曚綅鐢ㄦ埛')) COMMENT '鐢ㄦ埛绫诲瀷', + unit_id BIGINT COMMENT '鍗曚綅ID', + unit_name VARCHAR(100) COMMENT '鍗曚綅鍚嶇О', + status VARCHAR(20) DEFAULT '姝e父' CHECK (status IN ('姝e父', '鍐荤粨', '娉ㄩ攢')) COMMENT '鐢ㄦ埛鐘舵��', + last_login_time TIMESTAMP COMMENT '鏈�鍚庣櫥褰曟椂闂�', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 15. 鍗曚綅琛� (unit) - 鏂板鍗曚綅鍩虹琛� +CREATE TABLE unit ( + id BIGSERIAL PRIMARY KEY, + unit_name VARCHAR(100) NOT NULL COMMENT '鍗曚綅鍚嶇О', + unit_code VARCHAR(50) UNIQUE COMMENT '鍗曚綅缂栫爜', + unit_type VARCHAR(50) COMMENT '鍗曚綅绫诲瀷', + industry VARCHAR(100) COMMENT '鎵�灞炶涓�', + address TEXT COMMENT '鍗曚綅鍦板潃', + contact_person VARCHAR(100) COMMENT '鑱旂郴浜�', + contact_phone VARCHAR(20) COMMENT '鑱旂郴鐢佃瘽', + contact_email VARCHAR(100) COMMENT '鑱旂郴閭', + business_license VARCHAR(500) COMMENT '钀ヤ笟鎵х収', + legal_person VARCHAR(100) COMMENT '娉曚汉浠h〃', + registered_capital NUMERIC(15,2) COMMENT '娉ㄥ唽璧勬湰', + establishment_date DATE COMMENT '鎴愮珛鏃ユ湡', + status VARCHAR(20) DEFAULT '姝e父' CHECK (status IN ('姝e父', '鍐荤粨', '娉ㄩ攢')) COMMENT '鍗曚綅鐘舵��', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿', + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿', + deleted INTEGER DEFAULT 0 COMMENT '閫昏緫鍒犻櫎锛�1-宸插垹闄わ紝0-鏈垹闄�' +); + +-- 鍒涘缓绱㈠紩 +CREATE INDEX idx_product_pricing_product_id ON product_pricing(product_id); +CREATE INDEX idx_product_pricing_status ON product_pricing(is_active); +CREATE INDEX idx_shopping_cart_user_id ON shopping_cart(user_id); +CREATE INDEX idx_shopping_cart_product_id ON shopping_cart(product_id); +CREATE INDEX idx_order_info_user_id ON order_info(user_id); +CREATE INDEX idx_order_info_provider_id ON order_info(provider_id); +CREATE INDEX idx_order_info_status ON order_info(order_status); +CREATE INDEX idx_order_info_apply_time ON order_info(apply_time); +CREATE INDEX idx_order_detail_order_id ON order_detail(order_id); +CREATE INDEX idx_order_attachment_order_id ON order_attachment(order_id); +CREATE INDEX idx_order_approval_order_id ON order_approval(order_id); +CREATE INDEX idx_order_approval_approver_id ON order_approval(approver_id); +CREATE INDEX idx_order_evaluation_order_id ON order_evaluation(order_id); +CREATE INDEX idx_order_evaluation_evaluator_id ON order_evaluation(evaluator_id); +CREATE INDEX idx_points_rule_points_id ON points_rule(points_id); +CREATE INDEX idx_points_rule_detail_rule_id ON points_rule_detail(rule_id); +CREATE INDEX idx_product_provider_id ON product(provider_id); +CREATE INDEX idx_product_status ON product(status); +CREATE INDEX idx_user_unit_id ON user(unit_id); +CREATE INDEX idx_user_status ON user(status); + +-- 璐墿杞﹁〃绱㈠紩 +CREATE INDEX idx_cart_user_unit ON cart(user_id, unit_id, deleted); +CREATE INDEX idx_cart_pricing ON cart(pricing_id, deleted); +CREATE INDEX idx_cart_product ON cart(product_id, deleted); +CREATE INDEX idx_cart_provider ON cart(provider_id, deleted); +CREATE INDEX idx_cart_add_time ON cart(add_time, deleted); + +-- 娣诲姞澶栭敭绾︽潫 +ALTER TABLE product_pricing ADD CONSTRAINT fk_product_pricing_product_id FOREIGN KEY (product_id) REFERENCES product(id); +ALTER TABLE shopping_cart ADD CONSTRAINT fk_shopping_cart_user_id FOREIGN KEY (user_id) REFERENCES user(id); +ALTER TABLE shopping_cart ADD CONSTRAINT fk_shopping_cart_product_id FOREIGN KEY (product_id) REFERENCES product(id); +ALTER TABLE order_info ADD CONSTRAINT fk_order_info_product_id FOREIGN KEY (product_id) REFERENCES product(id); +ALTER TABLE order_info ADD CONSTRAINT fk_order_info_user_id FOREIGN KEY (user_id) REFERENCES user(id); +ALTER TABLE order_info ADD CONSTRAINT fk_order_info_provider_id FOREIGN KEY (provider_id) REFERENCES user(id); +ALTER TABLE order_detail ADD CONSTRAINT fk_order_detail_order_id FOREIGN KEY (order_id) REFERENCES order_info(order_id); +ALTER TABLE order_detail ADD CONSTRAINT fk_order_detail_pricing_id FOREIGN KEY (pricing_id) REFERENCES product_pricing(id); +ALTER TABLE order_attachment ADD CONSTRAINT fk_order_attachment_order_id FOREIGN KEY (order_id) REFERENCES order_info(order_id); +ALTER TABLE order_approval ADD CONSTRAINT fk_order_approval_order_id FOREIGN KEY (order_id) REFERENCES order_info(order_id); +ALTER TABLE order_evaluation ADD CONSTRAINT fk_order_evaluation_order_id FOREIGN KEY (order_id) REFERENCES order_info(order_id); +ALTER TABLE points_rule ADD CONSTRAINT fk_points_rule_points_id FOREIGN KEY (points_id) REFERENCES points(id); +ALTER TABLE points_rule_detail ADD CONSTRAINT fk_points_rule_detail_rule_id FOREIGN KEY (points_rule_id) REFERENCES points_rule(id); +ALTER TABLE points_rule_detail ADD CONSTRAINT fk_points_rule_detail_points_id FOREIGN KEY (points_id) REFERENCES points(id); +ALTER TABLE product ADD CONSTRAINT fk_product_provider_id FOREIGN KEY (provider_id) REFERENCES user(id); +ALTER TABLE user ADD CONSTRAINT fk_user_unit_id FOREIGN KEY (unit_id) REFERENCES unit(id); + +-- 娣诲姞琛ㄦ敞閲� +COMMENT ON TABLE product_pricing IS '浜у搧瀹氫环琛�'; +COMMENT ON TABLE shopping_cart IS '璐墿杞﹁〃'; +COMMENT ON TABLE order_info IS '璁㈠崟琛�'; +COMMENT ON TABLE order_detail IS '璁㈠崟璇︽儏琛�'; +COMMENT ON TABLE order_attachment IS '璁㈠崟闄勪欢琛�'; +COMMENT ON TABLE order_approval IS '璁㈠崟瀹℃牳琛�'; +COMMENT ON TABLE order_evaluation IS '璁㈠崟璇勪环琛�'; +COMMENT ON TABLE points IS '绉垎琛�'; +COMMENT ON TABLE points_rule_detail IS '绉垎瑙勫垯璇︽儏琛�'; +COMMENT ON TABLE product IS '浜у搧琛�'; +COMMENT ON TABLE user IS '鐢ㄦ埛琛�'; +COMMENT ON TABLE unit IS '鍗曚綅琛�'; + +-- 鎻掑叆鍒濆鏁版嵁 +INSERT INTO points (points_name, points_code, points_type, effective_start, modifier_id, modifier_name, version, description, status) VALUES +('鏁板瓧鍖栨爣鏉嗕釜浜虹Н鍒�', 'BENCHMARK_PERSONAL', '涓汉绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栨爣鏉嗕釜浜虹Н鍒嗕綋绯�', '鍚敤'), +('鏁板瓧鍖栨爣鏉嗗崟浣嶇Н鍒�', 'BENCHMARK_UNIT', '鍗曚綅绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栨爣鏉嗗崟浣嶇Н鍒嗕綋绯�', '鍚敤'), +('鏁板瓧鍖栫煡璇嗕釜浜虹Н鍒�', 'KNOWLEDGE_PERSONAL', '涓汉绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栫煡璇嗕釜浜虹Н鍒嗕綋绯�', '鍚敤'), +('鏁板瓧鍖栫煡璇嗗崟浣嶇Н鍒�', 'KNOWLEDGE_UNIT', '鍗曚綅绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栫煡璇嗗崟浣嶇Н鍒嗕綋绯�', '鍚敤'), +('鏁板瓧鍖栦骇鍝佷釜浜虹Н鍒�', 'PRODUCT_PERSONAL', '涓汉绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栦骇鍝佷釜浜虹Н鍒嗕綋绯�', '鍚敤'), +('鏁板瓧鍖栦骇鍝佸崟浣嶇Н鍒�', 'PRODUCT_UNIT', '鍗曚綅绉垎', '2024-01-01', 1, '绯荤粺绠$悊鍛�', '1.0.0', '鏁板瓧鍖栦骇鍝佸崟浣嶇Н鍒嗕綋绯�', '鍚敤'); + +-- 鎻掑叆娴嬭瘯鍗曚綅鏁版嵁 +INSERT INTO unit (unit_name, unit_code, unit_type, industry, status) VALUES +('娴嬭瘯浼佷笟', 'TEST_ENTERPRISE', '浼佷笟', '淇℃伅鎶�鏈�', '姝e父'), +('娴嬭瘯鍗曚綅', 'TEST_UNIT', '浜嬩笟鍗曚綅', '鏁欒偛', '姝e父'); + +-- 鎻掑叆娴嬭瘯鐢ㄦ埛鏁版嵁 +INSERT INTO user (username, real_name, user_type, unit_id, status) VALUES +('admin', '绯荤粺绠$悊鍛�', '涓汉鐢ㄦ埛', NULL, '姝e父'), +('test_user', '娴嬭瘯鐢ㄦ埛', '涓汉鐢ㄦ埛', 1, '姝e父'), +('test_provider', '娴嬭瘯鎻愪緵鑰�', '鍗曚綅鐢ㄦ埛', 1, '姝e父'); + +-- 鎻掑叆娴嬭瘯浜у搧鏁版嵁 +INSERT INTO product (product_name, product_code, product_type, category, description, provider_id, provider_name, status, audit_status) VALUES +('娴嬭瘯浜у搧1', 'TEST_PRODUCT_001', '杞欢浜у搧', '浼佷笟绠$悊', '杩欐槸涓�涓祴璇曚骇鍝�', 3, '娴嬭瘯鎻愪緵鑰�', '涓婃灦', '瀹℃牳閫氳繃'), +('娴嬭瘯浜у搧2', 'TEST_PRODUCT_002', '鏈嶅姟浜у搧', '鎶�鏈湇鍔�', '杩欐槸鍙︿竴涓祴璇曚骇鍝�', 3, '娴嬭瘯鎻愪緵鑰�', '涓婃灦', '瀹℃牳閫氳繃'); + +-- 鎻掑叆娴嬭瘯浜у搧瀹氫环鏁版嵁 +INSERT INTO product_pricing (suite_name, sales_form, customer_type, price_type, price_unit, price, product_id, product_name, provider_id, provider_name, is_active) VALUES +('鍩虹鐗�', '涔版柇', '浼佷笟', '绉垎', '濂�', 1000, 1, '娴嬭瘯浜у搧1', 3, '娴嬭瘯鎻愪緵鑰�', true), +('涓撲笟鐗�', '绉熻祦', '浼佷笟', '绉垎', '濂�/骞�', 500, 1, '娴嬭瘯浜у搧1', 3, '娴嬭瘯鎻愪緵鑰�', true), +('浼佷笟鐗�', '涔版柇', '浼佷笟', '璐у竵', '濂�', 10000, 2, '娴嬭瘯浜у搧2', 3, '娴嬭瘯鎻愪緵鑰�', true); diff --git "a/src/main/resources/sql/\346\225\260\346\215\256\345\272\223\350\241\250\350\257\264\346\230\216.md" "b/src/main/resources/sql/\346\225\260\346\215\256\345\272\223\350\241\250\350\257\264\346\230\216.md" new file mode 100644 index 0000000..d86f74a --- /dev/null +++ "b/src/main/resources/sql/\346\225\260\346\215\256\345\272\223\350\241\250\350\257\264\346\230\216.md" @@ -0,0 +1,142 @@ +琛ㄧ粨鏋勬瑙� +鏍规嵁闇�姹傛枃妗o紝鎴戜滑闇�瑕佸垱寤轰互涓嬫暟鎹簱琛ㄦ潵鏀寔浜ゆ槗妯″潡锛� + +琛ㄥ悕 鎻忚堪 涓昏鍔熻兘 +浜у搧瀹氫环琛� 浜у搧瀹氫环淇℃伅 瀛樺偍浜у搧瀹氫环鏂规鍙婇攢鍞舰寮� +璐墿杞� 鐢ㄦ埛璐墿杞︿俊鎭� 瀛樺偍鐢ㄦ埛寰呰喘涔扮殑鍟嗗搧淇℃伅 +璁㈠崟琛� 璁㈠崟涓讳俊鎭� 瀛樺偍璁㈠崟鍩烘湰淇℃伅鍙婄姸鎬� +璁㈠崟璇︽儏琛� 璁㈠崟璇︾粏鏉$洰淇℃伅 瀛樺偍璁㈠崟涓瘡涓骇鍝佺殑璇︾粏淇℃伅 +璁㈠崟闄勪欢琛� 璁㈠崟鐩稿叧闄勪欢淇℃伅 瀛樺偍璁㈠崟瀹℃壒杩囩▼涓殑鐩稿叧鏂囦欢 +璁㈠崟瀹℃牳琛� 璁㈠崟瀹℃牳璁板綍 瀛樺偍璁㈠崟瀹℃壒娴佺▼涓殑瀹℃牳鎰忚 +璁㈠崟璇勪环琛� 璁㈠崟璇勪环淇℃伅 瀛樺偍鐢ㄦ埛瀵瑰凡瀹屾垚璁㈠崟鐨勮瘎浠� +绉垎琛� 绉垎浣撶郴鍩烘湰淇℃伅 瀛樺偍绉垎浣撶郴鐨勫熀鏈厤缃� +绉垎瑙勫垯琛� 绉垎瑙勫垯瀹氫箟 瀛樺偍绉垎鑾峰彇鍜屾秷鑰楃殑瑙勫垯 +绉垎瑙勫垯璇︽儏琛� 绉垎瑙勫垯璇︾粏鍙傛暟 瀛樺偍绉垎瑙勫垯鐨勫叿浣撳弬鏁� +绉垎娴佹按琛� 绉垎鍙樺姩璁板綍 璁板綍鐢ㄦ埛绉垎鐨勫彉鍔ㄥ巻鍙� +绉垎璐︽埛琛� 鐢ㄦ埛绉垎璐︽埛淇℃伅 瀛樺偍鐢ㄦ埛褰撳墠鐨勭Н鍒嗙姸鎬� +璇︾粏琛ㄧ粨鏋勮璁� +1. 浜у搧瀹氫环琛� (product_pricing) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +suite_name VARCHAR(100) NOT NULL 浜у搧濂椾欢鍚嶇О +sales_form VARCHAR(20) CHECK (values) 閿�鍞舰寮�(涔版柇/绉熻祦/绉佹湁澧炲寘閲�/鍏湁澧炲寘閲�/OTA鏈嶅姟/璧勬簮鍖�/涓汉) +customer_type VARCHAR(10) CHECK (values) 瀹㈡埛瀵硅薄(浼佷笟/涓汉/椤圭洰閮�) +account_limit VARCHAR(20) 璐︽埛鏁伴噺 +concurrent_nodes VARCHAR(20) 骞跺彂鑺傜偣鏁� +price_type VARCHAR(10) CHECK (values) 浠锋牸璁剧疆(绉垎/鍗忚/璐у竵/鍏嶈垂) +price_unit VARCHAR(20) CHECK (values) 浠锋牸鍗曚綅(濂�/濂�/骞�/骞�) +price NUMERIC(15,2) NOT NULL 浠锋牸鍊� +is_active BOOLEAN DEFAULT TRUE 鍚敤鐘舵�� +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鏇存柊鏃堕棿 +product_id INT NOT NULL 鍏宠仈浜у搧ID +2. 璐墿杞� (shopping_cart) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +user_id INT NOT NULL 鐢ㄦ埛ID +suite_name VARCHAR(100) NOT NULL 浜у搧濂椾欢鍚嶇О +sales_form VARCHAR(20) CHECK (values) 閿�鍞舰寮�(涔版柇/绉熻祦/绉佹湁澧炲寘閲�/鍏湁澧炲寘閲�/OTA鏈嶅姟/璧勬簮鍖�/涓汉) +customer_type VARCHAR(10) CHECK (values) 瀹㈡埛瀵硅薄(浼佷笟/涓汉/椤圭洰閮�) +account_limit VARCHAR(20) DEFAULT '涓嶉檺' 璐︽埛鏁伴噺 +concurrent_nodes VARCHAR(20) DEFAULT '涓嶉檺' 骞跺彂鑺傜偣鏁� +price_type VARCHAR(10) CHECK (values) 浠锋牸绫诲瀷(绉垎/鍗忚/璐у竵/鍏嶈垂) +price_unit VARCHAR(20) CHECK (values) 浠锋牸鍗曚綅(濂�/濂�/骞�/骞�) +unit_price NUMERIC(15,2) NOT NULL 鍗曚环 +quantity INT NOT NULL 鏁伴噺 +duration INT 鏈熼檺(骞�) +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鏇存柊鏃堕棿 +3. 璁㈠崟琛� (order_info) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +order_id VARCHAR(50) PRIMARY KEY 璁㈠崟缂栧彿 +product_id INT NOT NULL 浜у搧ID +user_id INT NOT NULL 鐢ㄦ埛ID +product_name VARCHAR(100) NOT NULL 浜у搧鍚嶇О +provider_name VARCHAR(100) NOT NULL 浜у搧鎻愪緵鑰呭悕绉� +provider_id INT NOT NULL 鎻愪緵鑰匢D +apply_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鐢宠鏃堕棿 +order_status VARCHAR(20) CHECK (values) 璁㈠崟鐘舵��(寰呭鎵�/寰呭鎵规巿鏉�/寰呮巿鏉�/寰呬笂浼犳枃浠�/寰呬氦鏄撶‘璁�/宸插畬鎴�/宸插彇娑�) +total_amount NUMERIC(15,2) NOT NULL 璁㈠崟鎬婚噾棰� +workflow_id VARCHAR(50) 宸ヤ綔娴両D +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +4. 璁㈠崟璇︽儏琛� (order_detail) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +order_id VARCHAR(50) FOREIGN KEY 鍏宠仈璁㈠崟ID +pricing_id INT FOREIGN KEY 鍏宠仈浜у搧瀹氫环ID +unit_price NUMERIC(15,2) NOT NULL 鍗曚环 +quantity INT NOT NULL 鏁伴噺 +duration INT 骞撮檺 +provider_id INT NOT NULL 浜у搧鎻愪緵鑰匢D +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +remarks TEXT 澶囨敞 +5. 璁㈠崟闄勪欢琛� (order_attachment) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +order_id VARCHAR(50) FOREIGN KEY 鍏宠仈璁㈠崟ID +file_name VARCHAR(255) NOT NULL 闄勪欢鍚嶇О +file_type VARCHAR(50) NOT NULL 闄勪欢绫诲瀷 +file_size BIGINT NOT NULL 闄勪欢澶у皬(瀛楄妭) +file_url VARCHAR(255) NOT NULL 闄勪欢鍦板潃 +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +6. 璁㈠崟瀹℃牳琛� (order_approval) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +order_id VARCHAR(50) FOREIGN KEY 鍏宠仈璁㈠崟ID +approval_opinion TEXT NOT NULL 瀹℃牳鎰忚 +approver VARCHAR(100) NOT NULL 瀹℃牳浜� +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +7. 璁㈠崟璇勪环琛� (order_evaluation) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +order_id VARCHAR(50) FOREIGN KEY 鍏宠仈璁㈠崟ID +content TEXT NOT NULL 璇勪环鍐呭 +rating INT CHECK (1-5) 璇勫垎(1-5) +evaluator VARCHAR(100) NOT NULL 璇勪环浜� +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +8. 绉垎琛� (points) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +points_name VARCHAR(100) NOT NULL 绉垎鍚嶇О +effective_start DATE NOT NULL 鐢熸晥寮�濮嬫椂闂� +modifier VARCHAR(100) NOT NULL 淇敼浜� +version VARCHAR(20) NOT NULL 鐗堟湰鍙� +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +9. 绉垎瑙勫垯琛� (points_rule) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +points_id INT FOREIGN KEY 鍏宠仈绉垎ID +rule_type VARCHAR(10) CHECK (values) 绉垎瑙勫垯绫诲瀷(鑾峰彇/娑堣��) +category VARCHAR(50) CHECK (values) 绉垎绫诲埆(璧勬簮璐$尞/璧勬簮浼犳挱/璧勬簮浜ゆ槗/浜ゆ祦绀惧尯浜掑姩) +rule_name VARCHAR(100) NOT NULL 瑙勫垯鍚嶇О +description TEXT 瑙勫垯鎻忚堪 +status VARCHAR(10) CHECK (values) 鐘舵��(鍚敤/绂佺敤) +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 +updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鏇存柊鏃堕棿 +is_deleted BOOLEAN DEFAULT FALSE 閫昏緫鍒犻櫎鏍囧織 +10. 绉垎瑙勫垯璇︽儏琛� (points_rule_detail) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +rule_id INT FOREIGN KEY 鍏宠仈绉垎瑙勫垯ID +points_id INT FOREIGN KEY 鍏宠仈绉垎ID +points_value INT NOT NULL 绉垎鍊� +daily_limit INT 姣忔棩绉垎涓婇檺鍊� +11. 绉垎娴佹按琛� (points_transaction) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +data_category VARCHAR(50) CHECK (values) 鏁版嵁绫荤洰(鐢ㄦ埛鍙備笌/鍏朵粬) +transaction_name VARCHAR(100) NOT NULL 鍚嶇О +transaction_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鏃堕棿 +points_change INT NOT NULL 绉垎鍙樺姩鍊� +rule_type VARCHAR(10) CHECK (values) 绉垎瑙勫垯绫诲瀷(鑾峰彇/娑堣��) +user_id INT NOT NULL 鐢ㄦ埛ID +enterprise_id INT 浼佷笟ID +user_type VARCHAR(10) CHECK (values) 鐢ㄦ埛绫诲瀷(鍗曚綅鐢ㄦ埛/涓汉鐢ㄦ埛) +12. 绉垎璐︽埛琛� (points_account) +瀛楁鍚� 鏁版嵁绫诲瀷 绾︽潫 璇存槑 +id SERIAL PRIMARY KEY 涓婚敭ID +user_id INT NOT NULL UNIQUE 鐢ㄦ埛ID +points_balance INT DEFAULT 0 绉垎浣欓 +total_earned INT DEFAULT 0 绱鑾峰彇绉垎 +total_spent INT DEFAULT 0 绱娑堣�楃Н鍒� +created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 鍒涘缓鏃堕棿 \ No newline at end of file -- Gitblit v1.8.0