@@ -205,3 +205,58 @@ VALUES (
|
||||
'1953702581324398598', '系统序列号导出', 'system:sequence:export', 3, 5, 1953701540574969857,
|
||||
'', '', '', 0
|
||||
);
|
||||
|
||||
-- 系统序列号相关字典数据初始化脚本(达梦8版)
|
||||
|
||||
-- ========================================
|
||||
-- 1. 系统序列号循环类型字典
|
||||
-- ========================================
|
||||
|
||||
-- 插入字典类型
|
||||
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||
VALUES (500, '系统序列号循环类型', 'system_sequence_cycle_type', 0, '系统序列号循环类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||
|
||||
-- 插入字典数据
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
VALUES
|
||||
(5001, 1, '年循环', 'Y', 'system_sequence_cycle_type', 0, 'primary', '', '年循环。示例: 2025', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5002, 2, '年-月循环', 'Y-M', 'system_sequence_cycle_type', 0, 'success', '', '年-月循环。示例: 2025-08', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5003, 3, '年月紧凑', 'YM', 'system_sequence_cycle_type', 0, 'info', '', '年月紧凑。示例: 202508', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5004, 4, '两位年+月', 'yM', 'system_sequence_cycle_type', 0, 'warning', '', '两位年+月。示例: 2508', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5005, 5, '年-月-日循环', 'Y-M-D', 'system_sequence_cycle_type', 0, 'primary', '', '年-月-日循环。示例: 2025-08-08', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5006, 6, '年月日紧凑', 'YMD', 'system_sequence_cycle_type', 0, 'success', '', '年月日紧凑。示例: 20250808', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5007, 7, '两位年+月日', 'yMD', 'system_sequence_cycle_type', 0, 'info', '', '两位年+月日。示例: 250808', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5008, 8, '自定义循环值', 'CUST', 'system_sequence_cycle_type', 0, 'warning', '', '自定义循环值;若未传 circulationValue,则默认用 seqId', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5009, 9, '仅前缀', 'PFX', 'system_sequence_cycle_type', 0, 'danger', '', '仅前缀,不需要时间循环值(不设置则不抛错)', 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||
|
||||
-- ========================================
|
||||
-- 2. 系统序列号分段类型字典
|
||||
-- ========================================
|
||||
|
||||
-- 插入字典类型
|
||||
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||
VALUES (501, '系统序列号分段类型', 'system_sequence_detail_type', 0, '系统序列号分段类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||
|
||||
-- 插入字典数据
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
VALUES
|
||||
(5011, 1, '默认字符分段', 'STR', 'system_sequence_detail_type', 0, 'primary', '', '固定字符串分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5012, 2, '给定字符分段', 'INPUT', 'system_sequence_detail_type', 0, 'success', '', '根据输入参数动态生成的字符分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5013, 3, '日期分段', 'DATE', 'system_sequence_detail_type', 0, 'info', '', '基于日期格式的分段', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5014, 4, '流水号分段', 'SEQ', 'system_sequence_detail_type', 0, 'warning', '', '自增流水号分段', 'admin', SYSDATE, 'admin', SYSDATE, 0);
|
||||
|
||||
-- ========================================
|
||||
-- 3. 系统序列号分段规则类型字典
|
||||
-- ========================================
|
||||
|
||||
-- 插入字典类型
|
||||
INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time)
|
||||
VALUES (502, '系统序列号分段规则类型', 'system_sequence_detail_rule_type', 0, '系统序列号分段规则类型枚举', 'admin', SYSDATE, 'admin', SYSDATE, 0, NULL);
|
||||
|
||||
-- 插入字典数据
|
||||
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
|
||||
VALUES
|
||||
(5021, 1, '固定值', 'FIXED', 'system_sequence_detail_rule_type', 0, 'primary', '', '固定字符串值', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5022, 2, '日期格式', 'DATE', 'system_sequence_detail_rule_type', 0, 'success', '', '日期格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5023, 3, '数字格式', 'NUMBER', 'system_sequence_detail_rule_type', 0, 'info', '', '数字格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0),
|
||||
(5024, 4, '自定义格式', 'CUSTOM', 'system_sequence_detail_rule_type', 0, 'warning', '', '自定义格式规则', 'admin', SYSDATE, 'admin', SYSDATE, 0); (5024, 4, '自定义格式', 'CUSTOM', 'system_sequence_detail_rule_type', 0, 'warning', '', '自定义格式规则', 'admin', NOW(), 'admin', NOW(), b'0');
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.framework.common.biz.system.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author chenbowen
|
||||
*/
|
||||
@FeignClient(name = RpcConstants.SYSTEM_NAME)
|
||||
@Tag(name = "序列管理 Api")
|
||||
public interface SequenceCommonApi {
|
||||
|
||||
String PREFIX = RpcConstants.SYSTEM_PREFIX + "/sequence";
|
||||
|
||||
@PostMapping(PREFIX + "/next-sequence")
|
||||
@Operation(summary = "获取下一个序列号")
|
||||
@Parameters({
|
||||
@Parameter(name = "sequenceCode", description = "序列编码", example = "ORDER_NO", required = true),
|
||||
@Parameter(name = "circulationValue", description = "循环值", example = "20250811"),
|
||||
@Parameter(name = "inputStrs", description = "输入参数", example = "[\"A\",\"B\"]")
|
||||
})
|
||||
CommonResult<String> getNextSequence(@RequestParam("sequenceCode") String sequenceCode,
|
||||
@RequestParam(value = "circulationValue", required = false) String circulationValue,
|
||||
@RequestParam(value = "inputStrs", required = false) List<String> inputStrs);
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package cn.iocoder.yudao.framework.business.annotation;
|
||||
|
||||
/**
|
||||
* @author chenbowen
|
||||
*
|
||||
* 业务代码自动补全的注解,在 DO filed 中与 @TableField(fill = FieldFill.INSERT) 一起标注后自动新增时生成 Code chenbowen
|
||||
*/
|
||||
public @interface BusinessCode {
|
||||
|
||||
}
|
||||
@@ -103,6 +103,11 @@
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package cn.iocoder.yudao.framework.datasource.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.biz.system.sequence.SequenceCommonApi;
|
||||
import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter;
|
||||
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@@ -17,6 +19,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@AutoConfiguration
|
||||
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理
|
||||
@EnableConfigurationProperties(DruidStatProperties.class)
|
||||
@EnableFeignClients(clients = SequenceCommonApi.class)
|
||||
public class YudaoDataSourceAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.framework.mybatis.core.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author chenbowen
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface BusinessCode {
|
||||
String value();
|
||||
String circulationValueField() default "";
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author chenbowen
|
||||
*/
|
||||
@@ -33,6 +35,9 @@ public class BusinessBaseDO extends BaseDO {
|
||||
*/
|
||||
private Long tenantId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<String> inputStrs;
|
||||
|
||||
/**
|
||||
* 清除 creator、createTime、updateTime、updater 等字段,避免前端直接传递这些字段,导致被更新
|
||||
*/
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
package cn.iocoder.yudao.framework.mybatis.core.handler;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.biz.system.sequence.SequenceCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.annotation.BusinessCode;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BusinessBaseDO;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.USER_NOT_SET_DEPT;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@@ -26,8 +28,12 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
||||
*
|
||||
* @author hexiaowu
|
||||
*/
|
||||
@Component
|
||||
public class DefaultDBFieldHandler implements MetaObjectHandler {
|
||||
|
||||
@Autowired
|
||||
private SequenceCommonApi sequenceCommonApi;
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO baseDO) {
|
||||
@@ -55,6 +61,67 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
|
||||
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BusinessBaseDO businessBaseDO) {
|
||||
// 公司编号、公司名称、部门编号、部门名称、岗位编号等字段,默认不填充
|
||||
// 需要在业务层手动设置
|
||||
autoFillDeptInfo(businessBaseDO);
|
||||
|
||||
// 自动填充带 @BusinessCode 注解的字段序列
|
||||
autoFillBusinessCode(businessBaseDO);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
// 更新时间为空,则以当前时间为更新时间
|
||||
Object modifyTime = getFieldValByName("updateTime", metaObject);
|
||||
if (Objects.isNull(modifyTime)) {
|
||||
setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
|
||||
}
|
||||
|
||||
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
|
||||
Object modifier = getFieldValByName("updater", metaObject);
|
||||
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
|
||||
setFieldValByName("updater", userId.toString(), metaObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void autoFillBusinessCode(BusinessBaseDO businessBaseDO) {
|
||||
Class<?> clazz = businessBaseDO.getClass();
|
||||
ReflectionUtils.doWithFields(clazz, field -> {
|
||||
BusinessCode businessCode = field.getAnnotation(BusinessCode.class);
|
||||
if (businessCode == null) {
|
||||
return;
|
||||
}
|
||||
field.setAccessible(true);
|
||||
Object codeVal = field.get(businessBaseDO);
|
||||
// 如果已经手动设置了 code 字段,则不再自动填充
|
||||
if (codeVal != null && !codeVal.toString().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 获取 sequenceCode
|
||||
String sequenceCode = businessCode.value();
|
||||
// 获取 circulationValue
|
||||
String circulationValue = null;
|
||||
if (!businessCode.circulationValueField().isEmpty()) {
|
||||
Field cvField = ReflectionUtils.findField(clazz, businessCode.circulationValueField());
|
||||
if (cvField != null) {
|
||||
cvField.setAccessible(true);
|
||||
Object cvVal = cvField.get(businessBaseDO);
|
||||
circulationValue = cvVal != null ? cvVal.toString() : null;
|
||||
}
|
||||
}
|
||||
// 直接获取 inputStrs 属性
|
||||
List<String> inputStrs = Optional.ofNullable(businessBaseDO.getInputStrs()).orElse(new ArrayList<>());
|
||||
// 调用远程服务获取序列号
|
||||
if (sequenceCommonApi != null) {
|
||||
CommonResult<String> result = sequenceCommonApi.getNextSequence(sequenceCode, circulationValue, inputStrs);
|
||||
if (result != null && result.isSuccess() && result.getData() != null) {
|
||||
field.set(businessBaseDO, result.getData());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void autoFillDeptInfo(BusinessBaseDO businessBaseDO) {
|
||||
LoginUser loginUser = getLoginUser();
|
||||
Long visitCompanyId = loginUser.getVisitCompanyId();
|
||||
Long visitDeptId = loginUser.getVisitDeptId();
|
||||
@@ -76,21 +143,4 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
|
||||
// 多租户编号,默认不填充
|
||||
businessBaseDO.setTenantId(loginUser.getTenantId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
// 更新时间为空,则以当前时间为更新时间
|
||||
Object modifyTime = getFieldValByName("updateTime", metaObject);
|
||||
if (Objects.isNull(modifyTime)) {
|
||||
setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
|
||||
}
|
||||
|
||||
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人
|
||||
Object modifier = getFieldValByName("updater", metaObject);
|
||||
Long userId = WebFrameworkUtils.getLoginUserId();
|
||||
if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
|
||||
setFieldValByName("updater", userId.toString(), metaObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
package cn.iocoder.yudao.module.system.api.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.biz.system.sequence.SequenceCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author chenbowen
|
||||
*/
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "序列管理 Api")
|
||||
public interface SequenceApi {
|
||||
@FeignClient(name = ApiConstants.NAME, primary = false) // TODO 芋艿:fallbackFactory =
|
||||
@Tag(name = "RPC 服务 - 序列号")
|
||||
public interface SequenceApi extends SequenceCommonApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/sequence";
|
||||
|
||||
@PostMapping(PREFIX + "/next-sequence")
|
||||
@Operation(summary = "获取下一个序列号")
|
||||
@Override
|
||||
CommonResult<String> getNextSequence(@RequestParam("sequenceCode") String sequenceCode,
|
||||
@RequestParam(value = "circulationValue", required = false) String circulationValue,
|
||||
@RequestParam(value = "inputStrs", required = false) List<String> inputStrs);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.system.enums.sequence;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 序列号分段规则类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SequenceDetailRuleEnum {
|
||||
// 示例规则类型
|
||||
FIXED("FIXED", "固定值"),
|
||||
DATE("DATE", "日期格式"),
|
||||
NUMBER("NUMBER", "数字格式"),
|
||||
CUSTOM("CUSTOM", "自定义格式");
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.enums.sequence;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 序列号分段类型枚举
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SequenceDetailTypeEnum {
|
||||
|
||||
// 默认字符分段
|
||||
SEQ_DETAIL_TYPE_STR("STR", "默认字符分段"),
|
||||
// 给定字符分段
|
||||
SEQ_DETAIL_TYPE_INPUT("INPUT", "给定字符分段"),
|
||||
// 日期分段
|
||||
SEQ_DETAIL_TYPE_DATE("DATE", "日期分段"),
|
||||
// 流水号分段
|
||||
SEQ_DETAIL_TYPE_SEQ("SEQ", "流水号分段");
|
||||
|
||||
/**
|
||||
* 类型编码
|
||||
*/
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
public static SequenceDetailTypeEnum getByCode(String code) {
|
||||
if (code == null) {
|
||||
return null;
|
||||
}
|
||||
for (SequenceDetailTypeEnum value : SequenceDetailTypeEnum.values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.system.api.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.service.sequence.SequenceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
public class SequenceApiImpl implements SequenceApi {
|
||||
|
||||
@Resource
|
||||
private SequenceService sequenceService;
|
||||
|
||||
@Override
|
||||
public CommonResult<String> getNextSequence(String sequenceCode, String circulationValue, List<String> inputStrs) {
|
||||
String result = sequenceService.getNextSeq(sequenceCode, circulationValue, inputStrs);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceGenerateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequencePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDetailDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceRecordDO;
|
||||
import cn.iocoder.yudao.module.system.service.sequence.SequenceService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 系统序列号")
|
||||
@RestController
|
||||
@RequestMapping("/system/sequence")
|
||||
@Validated
|
||||
public class SequenceController {
|
||||
|
||||
|
||||
@Resource
|
||||
private SequenceService sequenceService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建系统序列号")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:create')")
|
||||
public CommonResult<SequenceRespVO> createSequence(@Valid @RequestBody SequenceSaveReqVO createReqVO) {
|
||||
return success(sequenceService.createSequence(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新系统序列号")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:update')")
|
||||
public CommonResult<Boolean> updateSequence(@Valid @RequestBody SequenceSaveReqVO updateReqVO) {
|
||||
sequenceService.updateSequence(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除系统序列号")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:delete')")
|
||||
public CommonResult<Boolean> deleteSequence(@RequestParam("id") Long id) {
|
||||
sequenceService.deleteSequence(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-list")
|
||||
@Parameter(name = "ids", description = "编号", required = true)
|
||||
@Operation(summary = "批量删除系统序列号")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:delete')")
|
||||
public CommonResult<Boolean> deleteSequenceList(@RequestParam("ids") List<Long> ids) {
|
||||
sequenceService.deleteSequenceListByIds(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得系统序列号")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:query')")
|
||||
public CommonResult<SequenceRespVO> getSequence(@RequestParam("id") Long id) {
|
||||
SequenceDO sequence = sequenceService.getSequence(id);
|
||||
return success(BeanUtils.toBean(sequence, SequenceRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得系统序列号分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:query')")
|
||||
public CommonResult<PageResult<SequenceRespVO>> getSequencePage(@Valid SequencePageReqVO pageReqVO) {
|
||||
PageResult<SequenceDO> pageResult = sequenceService.getSequencePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, SequenceRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出系统序列号 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportSequenceExcel(@Valid SequencePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<SequenceDO> list = sequenceService.getSequencePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "系统序列号.xls", "数据", SequenceRespVO.class,
|
||||
BeanUtils.toBean(list, SequenceRespVO.class));
|
||||
}
|
||||
|
||||
// ==================== 子表(系统序列号分段明细) ====================
|
||||
|
||||
@GetMapping("/sequence-detail/list-by-sequence-id")
|
||||
@Operation(summary = "获得系统序列号分段明细列表")
|
||||
@Parameter(name = "sequenceId", description = "序列Id")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:query')")
|
||||
public CommonResult<List<SequenceDetailDO>> getSequenceDetailListBySequenceId(@RequestParam("sequenceId") Long sequenceId) {
|
||||
return success(sequenceService.getSequenceDetailListBySequenceId(sequenceId));
|
||||
}
|
||||
|
||||
// ==================== 子表(系统序列号记录) ====================
|
||||
|
||||
@GetMapping("/sequence-record/list-by-sequence-id")
|
||||
@Operation(summary = "获得系统序列号记录列表")
|
||||
@Parameter(name = "sequenceId", description = "序列Id")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:query')")
|
||||
public CommonResult<List<SequenceRecordDO>> getSequenceRecordListBySequenceId(@RequestParam("sequenceId") Long sequenceId) {
|
||||
return success(sequenceService.getSequenceRecordListBySequenceId(sequenceId));
|
||||
}
|
||||
|
||||
// ==================== 序列号生成接口 ====================
|
||||
|
||||
/**
|
||||
* 生成下一个序列号(支持 sequenceCode、circulationValue、inputStrs 参数,兼容所有场景)
|
||||
*/
|
||||
@PostMapping("/generate")
|
||||
@Operation(summary = "生成下一个序列号")
|
||||
@PreAuthorize("@ss.hasPermission('system:sequence:generate')")
|
||||
public CommonResult<String> generateSequence(@RequestBody SequenceGenerateReqVO reqVO) {
|
||||
String result = sequenceService.getNextSeq(reqVO.getSequenceCode(), reqVO.getCirculationValue(), reqVO.getInputStrs());
|
||||
return success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sequence.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 序列号生成 Request VO")
|
||||
@Data
|
||||
public class SequenceGenerateReqVO {
|
||||
|
||||
@Schema(description = "序列号编码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "序列号编码不能为空")
|
||||
private String sequenceCode;
|
||||
|
||||
@Schema(description = "循环值")
|
||||
private String circulationValue;
|
||||
|
||||
@Schema(description = "输入参数数组")
|
||||
private List<String> inputStrs;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sequence.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 系统序列号分页 Request VO")
|
||||
@Data
|
||||
public class SequencePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "序列号编码")
|
||||
private String sequenceCode;
|
||||
|
||||
@Schema(description = "序列号名称", example = "张三")
|
||||
private String sequenceName;
|
||||
|
||||
@Schema(description = "循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)", example = "1")
|
||||
private String cycleType;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sequence.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 系统序列号 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class SequenceRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "23537")
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "序列号编码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("序列号编码")
|
||||
private String sequenceCode;
|
||||
|
||||
@Schema(description = "序列号名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@ExcelProperty("序列号名称")
|
||||
private String sequenceName;
|
||||
|
||||
@Schema(description = "循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)")
|
||||
private String cycleType;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.sequence.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDetailDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceRecordDO;
|
||||
|
||||
@Schema(description = "管理后台 - 系统序列号新增/修改 Request VO")
|
||||
@Data
|
||||
public class SequenceSaveReqVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "23537")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "序列号编码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "序列号编码不能为空")
|
||||
private String sequenceCode;
|
||||
|
||||
@Schema(description = "序列号名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
|
||||
@NotEmpty(message = "序列号名称不能为空")
|
||||
private String sequenceName;
|
||||
|
||||
@Schema(description = "循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotEmpty(message = "循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)不能为空")
|
||||
private String cycleType;
|
||||
|
||||
@Schema(description = "系统序列号分段明细列表")
|
||||
private List<SequenceDetailDO> sequenceDetails;
|
||||
|
||||
@Schema(description = "系统序列号记录列表")
|
||||
private List<SequenceRecordDO> sequenceRecords;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.sequence;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
/**
|
||||
* 系统序列号 DO
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@TableName("system_seq")
|
||||
@KeySequence("system_seq_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
/**
|
||||
* 支持业务基类继承:isBusiness=true 时继承 BusinessBaseDO,否则继承 BaseDO
|
||||
*/
|
||||
public class SequenceDO extends BaseDO {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/**
|
||||
* 序列号编码
|
||||
*/
|
||||
@TableField("seq_cd")
|
||||
private String sequenceCode;
|
||||
/**
|
||||
* 序列号名称
|
||||
*/
|
||||
@TableField("seq_name")
|
||||
private String sequenceName;
|
||||
/**
|
||||
* 循环类型(yyyy-年/yyyy-MM-dd-日/XXX-自定义)
|
||||
*/
|
||||
@TableField("cycl_tp")
|
||||
private String cycleType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 系统序列号分段明细 DO
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@TableName("system_seq_dtl")
|
||||
@KeySequence("system_seq_dtl_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SequenceDetailDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/**
|
||||
* 序列号编码
|
||||
*/
|
||||
@TableField("seq_cd")
|
||||
private String sequenceCode;
|
||||
/**
|
||||
* 序列Id
|
||||
*/
|
||||
@TableField("seq_id")
|
||||
private Long sequenceId;
|
||||
/**
|
||||
* 分段编号
|
||||
*/
|
||||
@TableField("seq_dtl_no")
|
||||
private String sequenceDetailNo;
|
||||
/**
|
||||
* 分段类型
|
||||
*/
|
||||
@TableField("seq_dtl_tp")
|
||||
private String sequenceDetailType;
|
||||
/**
|
||||
* 分段规则
|
||||
*/
|
||||
@TableField("seq_dtl_rul")
|
||||
private String sequenceDetailRule;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 系统序列号记录 DO
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@TableName("system_seq_rcd")
|
||||
@KeySequence("system_seq_rcd_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SequenceRecordDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/**
|
||||
* 序列号编码
|
||||
*/
|
||||
@TableField("seq_cd")
|
||||
private String sequenceCode;
|
||||
/**
|
||||
* 序列Id
|
||||
*/
|
||||
@TableField("seq_id")
|
||||
private Long sequenceId;
|
||||
/**
|
||||
* 分段编号
|
||||
*/
|
||||
@TableField("seq_dtl_no")
|
||||
private String sequenceDetailNo;
|
||||
/**
|
||||
* 当前值
|
||||
*/
|
||||
@TableField("crnt_val")
|
||||
private String currentValue;
|
||||
/**
|
||||
* 循环值
|
||||
*/
|
||||
@TableField("cycl_val")
|
||||
private String cycleValue;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.sequence;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDetailDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 系统序列号分段明细 Mapper
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@Mapper
|
||||
public interface SequenceDetailMapper extends BaseMapperX<SequenceDetailDO> {
|
||||
|
||||
default List<SequenceDetailDO> selectListBySequenceId(Long sequenceId) {
|
||||
return selectList(SequenceDetailDO::getSequenceId, sequenceId);
|
||||
}
|
||||
|
||||
default int deleteBySequenceId(Long sequenceId) {
|
||||
return delete(SequenceDetailDO::getSequenceId, sequenceId);
|
||||
}
|
||||
|
||||
default int deleteBySequenceIds(List<Long> sequenceIds) {
|
||||
return deleteBatch(SequenceDetailDO::getSequenceId, sequenceIds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.sequence;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.*;
|
||||
|
||||
/**
|
||||
* 系统序列号 Mapper
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@Mapper
|
||||
public interface SequenceMapper extends BaseMapperX<SequenceDO> {
|
||||
|
||||
default PageResult<SequenceDO> selectPage(SequencePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<SequenceDO>()
|
||||
.likeIfPresent(SequenceDO::getSequenceCode, reqVO.getSequenceCode())
|
||||
.likeIfPresent(SequenceDO::getSequenceName, reqVO.getSequenceName())
|
||||
.eqIfPresent(SequenceDO::getCycleType, reqVO.getCycleType())
|
||||
.betweenIfPresent(SequenceDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(SequenceDO::getId));
|
||||
}
|
||||
|
||||
default SequenceDO selectBySequenceCode(String sequenceCode) {
|
||||
return selectOne(SequenceDO::getSequenceCode, sequenceCode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.sequence;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceRecordDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 系统序列号记录 Mapper
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@Mapper
|
||||
public interface SequenceRecordMapper extends BaseMapperX<SequenceRecordDO> {
|
||||
|
||||
default List<SequenceRecordDO> selectListBySequenceId(Long sequenceId) {
|
||||
return selectList(SequenceRecordDO::getSequenceId, sequenceId);
|
||||
}
|
||||
|
||||
default int deleteBySequenceId(Long sequenceId) {
|
||||
return delete(SequenceRecordDO::getSequenceId, sequenceId);
|
||||
}
|
||||
|
||||
default int deleteBySequenceIds(List<Long> sequenceIds) {
|
||||
return deleteBatch(SequenceRecordDO::getSequenceId, sequenceIds);
|
||||
}
|
||||
|
||||
default SequenceRecordDO selectBySeqIdAndDetailNoAndCycleValue(Long sequenceId, String sequenceDetailNo, String cycleValue) {
|
||||
return selectOne(new LambdaQueryWrapperX<SequenceRecordDO>()
|
||||
.eq(SequenceRecordDO::getSequenceId, sequenceId)
|
||||
.eq(SequenceRecordDO::getSequenceDetailNo, sequenceDetailNo)
|
||||
.eq(SequenceRecordDO::getCycleValue, cycleValue));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package cn.iocoder.yudao.module.system.service.sequence;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequencePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDetailDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceRecordDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统序列号 Service 接口
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
public interface SequenceService {
|
||||
|
||||
/**
|
||||
* 创建系统序列号
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
SequenceRespVO createSequence(@Valid SequenceSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新系统序列号
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateSequence(@Valid SequenceSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除系统序列号
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteSequence(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除系统序列号
|
||||
*
|
||||
* @param ids 编号
|
||||
*/
|
||||
void deleteSequenceListByIds(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得系统序列号
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 系统序列号
|
||||
*/
|
||||
SequenceDO getSequence(Long id);
|
||||
|
||||
/**
|
||||
* 获得系统序列号分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 系统序列号分页
|
||||
*/
|
||||
PageResult<SequenceDO> getSequencePage(SequencePageReqVO pageReqVO);
|
||||
|
||||
// ==================== 子表(系统序列号分段明细) ====================
|
||||
|
||||
/**
|
||||
* 获得系统序列号分段明细列表
|
||||
*
|
||||
* @param sequenceId 序列Id
|
||||
* @return 系统序列号分段明细列表
|
||||
*/
|
||||
List<SequenceDetailDO> getSequenceDetailListBySequenceId(Long sequenceId);
|
||||
|
||||
// ==================== 子表(系统序列号记录) ====================
|
||||
|
||||
/**
|
||||
* 获得系统序列号记录列表
|
||||
*
|
||||
* @param sequenceId 序列Id
|
||||
* @return 系统序列号记录列表
|
||||
*/
|
||||
List<SequenceRecordDO> getSequenceRecordListBySequenceId(Long sequenceId);
|
||||
|
||||
// ==================== 序列号生成方法 ====================
|
||||
/**
|
||||
* 根据序列号编码生成下一个序列号
|
||||
*
|
||||
* @param sequenceCode 序列号编码
|
||||
* @param circulationValue 序列号循环类型条件值
|
||||
* @param inputStrs 自定义字符串数组
|
||||
* @return 最新序列号
|
||||
*/
|
||||
String getNextSeq(String sequenceCode, String circulationValue, List<String> inputStrs);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
package cn.iocoder.yudao.module.system.service.sequence;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequencePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.sequence.vo.SequenceSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceDetailDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sequence.SequenceRecordDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.sequence.SequenceDetailMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.sequence.SequenceMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.sequence.SequenceRecordMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.sequence.SequenceCycleTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.sequence.SequenceDetailTypeEnum;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 系统序列号 Service 实现类
|
||||
*
|
||||
* @author 后台管理
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class SequenceServiceImpl implements SequenceService {
|
||||
|
||||
@Resource
|
||||
private SequenceMapper sequenceMapper;
|
||||
@Resource
|
||||
private SequenceDetailMapper sequenceDetailMapper;
|
||||
@Resource
|
||||
private SequenceRecordMapper sequenceRecordMapper;
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SequenceRespVO createSequence(SequenceSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
SequenceDO sequence = BeanUtils.toBean(createReqVO, SequenceDO.class);
|
||||
sequenceMapper.insert(sequence);
|
||||
|
||||
// 插入子表
|
||||
createSequenceDetailList(sequence.getId(), sequence.getSequenceCode(), createReqVO.getSequenceDetails());
|
||||
// 移除 createSequenceRecordList,记录表仅系统自动生成
|
||||
// 返回
|
||||
return BeanUtils.toBean(sequence, SequenceRespVO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateSequence(SequenceSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateSequenceExists(updateReqVO.getId());
|
||||
// 更新
|
||||
SequenceDO updateObj = BeanUtils.toBean(updateReqVO, SequenceDO.class);
|
||||
sequenceMapper.updateById(updateObj);
|
||||
|
||||
// 更新子表
|
||||
updateSequenceDetailList(updateReqVO.getId(), updateReqVO.getSequenceCode(), updateReqVO.getSequenceDetails());
|
||||
// 移除 updateSequenceRecordList,记录表仅系统自动生成
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteSequence(Long id) {
|
||||
// 校验存在
|
||||
validateSequenceExists(id);
|
||||
// 删除
|
||||
sequenceMapper.deleteById(id);
|
||||
|
||||
// 删除子表
|
||||
deleteSequenceDetailBySequenceId(id);
|
||||
deleteSequenceRecordBySequenceId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteSequenceListByIds(List<Long> ids) {
|
||||
// 校验存在
|
||||
validateSequenceExists(ids);
|
||||
// 删除
|
||||
sequenceMapper.deleteByIds(ids);
|
||||
|
||||
// 删除子表
|
||||
deleteSequenceDetailBySequenceIds(ids);
|
||||
deleteSequenceRecordBySequenceIds(ids);
|
||||
}
|
||||
|
||||
private void validateSequenceExists(List<Long> ids) {
|
||||
List<SequenceDO> list = sequenceMapper.selectByIds(ids);
|
||||
if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
|
||||
throw exception(SEQUENCE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateSequenceExists(Long id) {
|
||||
if (sequenceMapper.selectById(id) == null) {
|
||||
throw exception(SEQUENCE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceDO getSequence(Long id) {
|
||||
return sequenceMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SequenceDO> getSequencePage(SequencePageReqVO pageReqVO) {
|
||||
return sequenceMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
// ==================== 子表(系统序列号分段明细) ====================
|
||||
|
||||
@Override
|
||||
public List<SequenceDetailDO> getSequenceDetailListBySequenceId(Long sequenceId) {
|
||||
return sequenceDetailMapper.selectListBySequenceId(sequenceId);
|
||||
}
|
||||
|
||||
private void createSequenceDetailList(Long sequenceId, String sequenceCode, List<SequenceDetailDO> list) {
|
||||
list.forEach(o -> o.setSequenceId(sequenceId).clean());
|
||||
list.forEach(o -> o.setSequenceCode(sequenceCode).clean());
|
||||
sequenceDetailMapper.insertBatch(list);
|
||||
}
|
||||
|
||||
private void updateSequenceDetailList(Long sequenceId, String sequenceCode, List<SequenceDetailDO> list) {
|
||||
list.forEach(o -> o.setSequenceId(sequenceId).clean());
|
||||
list.forEach(o -> o.setSequenceCode(sequenceCode).clean());
|
||||
List<SequenceDetailDO> oldList = sequenceDetailMapper.selectListBySequenceId(sequenceId);
|
||||
List<List<SequenceDetailDO>> diffList = diffList(oldList, list, (oldVal, newVal) -> {
|
||||
boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId());
|
||||
if (same) {
|
||||
newVal.setId(oldVal.getId()).clean(); // 解决更新情况下:updateTime 不更新
|
||||
}
|
||||
return same;
|
||||
});
|
||||
|
||||
// 第二步,批量添加、修改、删除
|
||||
if (CollUtil.isNotEmpty(diffList.get(0))) {
|
||||
sequenceDetailMapper.insertBatch(diffList.get(0));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(1))) {
|
||||
sequenceDetailMapper.updateBatch(diffList.get(1));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||
sequenceDetailMapper.deleteByIds(convertList(diffList.get(2), SequenceDetailDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSequenceDetailBySequenceId(Long sequenceId) {
|
||||
sequenceDetailMapper.deleteBySequenceId(sequenceId);
|
||||
}
|
||||
|
||||
private void deleteSequenceDetailBySequenceIds(List<Long> sequenceIds) {
|
||||
sequenceDetailMapper.deleteBySequenceIds(sequenceIds);
|
||||
}
|
||||
|
||||
// ==================== 子表(系统序列号记录) ====================
|
||||
|
||||
@Override
|
||||
public List<SequenceRecordDO> getSequenceRecordListBySequenceId(Long sequenceId) {
|
||||
return sequenceRecordMapper.selectListBySequenceId(sequenceId);
|
||||
}
|
||||
|
||||
private void createSequenceRecordList(Long sequenceId, String sequenceCode, List<SequenceRecordDO> list) {
|
||||
list.forEach(o -> o.setSequenceId(sequenceId).clean());
|
||||
list.forEach(o -> o.setSequenceCode(sequenceCode).clean());
|
||||
sequenceRecordMapper.insertBatch(list);
|
||||
}
|
||||
|
||||
private void updateSequenceRecordList(Long sequenceId, String sequenceCode, List<SequenceRecordDO> list) {
|
||||
list.forEach(o -> o.setSequenceId(sequenceId).clean());
|
||||
list.forEach(o -> o.setSequenceCode(sequenceCode).clean());
|
||||
List<SequenceRecordDO> oldList = sequenceRecordMapper.selectListBySequenceId(sequenceId);
|
||||
List<List<SequenceRecordDO>> diffList = diffList(oldList, list, (oldVal, newVal) -> {
|
||||
boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId());
|
||||
if (same) {
|
||||
newVal.setId(oldVal.getId()).clean(); // 解决更新情况下:updateTime 不更新
|
||||
}
|
||||
return same;
|
||||
});
|
||||
|
||||
// 第二步,批量添加、修改、删除
|
||||
if (CollUtil.isNotEmpty(diffList.get(0))) {
|
||||
sequenceRecordMapper.insertBatch(diffList.get(0));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(1))) {
|
||||
sequenceRecordMapper.updateBatch(diffList.get(1));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||
sequenceRecordMapper.deleteByIds(convertList(diffList.get(2), SequenceRecordDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSequenceRecordBySequenceId(Long sequenceId) {
|
||||
sequenceRecordMapper.deleteBySequenceId(sequenceId);
|
||||
}
|
||||
|
||||
private void deleteSequenceRecordBySequenceIds(List<Long> sequenceIds) {
|
||||
sequenceRecordMapper.deleteBySequenceIds(sequenceIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextSeq(String sequenceCode, String circulationValue, List<String> inputStrs) {
|
||||
StringBuilder seqValue = new StringBuilder();
|
||||
// 1-获取序列号配置
|
||||
SequenceDO sequence = sequenceMapper.selectBySequenceCode(sequenceCode);
|
||||
if (sequence == null) {
|
||||
throw exception(SEQUENCE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 2-获取序列号分段明细
|
||||
List<SequenceDetailDO> sequenceDetails = sequenceDetailMapper.selectListBySequenceId(sequence.getId());
|
||||
if (CollUtil.isEmpty(sequenceDetails)) {
|
||||
throw exception(SEQUENCE_DETAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 3-根据循环类型,获取记录循环字符
|
||||
circulationValue = this.getCirculationValue(circulationValue, sequence);
|
||||
this.generateSeqValue(sequence, sequenceDetails, circulationValue, inputStrs, seqValue);
|
||||
|
||||
return seqValue.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成序列号
|
||||
*
|
||||
* @param sequence 序列号配置对象
|
||||
* @param sequenceDetails 序列号规则明细集合
|
||||
* @param circulationValue 循环值
|
||||
* @param inputStrs 输入参数
|
||||
* @param seqValue 生成的序列号值
|
||||
*/
|
||||
private void generateSeqValue(
|
||||
SequenceDO sequence,
|
||||
List<SequenceDetailDO> sequenceDetails,
|
||||
String circulationValue,
|
||||
List<String> inputStrs,
|
||||
StringBuilder seqValue) {
|
||||
// 4-生成序列号
|
||||
AtomicReference<String> circulationValueAtomic = new AtomicReference<>(circulationValue);
|
||||
for (SequenceDetailDO sequenceDetail : sequenceDetails) {
|
||||
// 4-1-默认字符分段处理
|
||||
if (Objects.equals(sequenceDetail.getSequenceDetailType(), SequenceDetailTypeEnum.SEQ_DETAIL_TYPE_STR.getCode())) {
|
||||
String seqDetailRule = sequenceDetail.getSequenceDetailRule();
|
||||
if (StrUtil.isBlank(seqDetailRule)) {
|
||||
throw exception(SEQUENCE_DETAIL_RULE_INVALID, "默认字符分段缺少默认字符");
|
||||
}
|
||||
seqValue.append(seqDetailRule);
|
||||
}
|
||||
// 4-2-给定字符分段处理
|
||||
else if (Objects.equals(sequenceDetail.getSequenceDetailType(), SequenceDetailTypeEnum.SEQ_DETAIL_TYPE_INPUT.getCode())) {
|
||||
String seqDetailRule = sequenceDetail.getSequenceDetailRule();
|
||||
if (StrUtil.isBlank(seqDetailRule)) {
|
||||
throw exception(SEQUENCE_DETAIL_RULE_INVALID, "给定字符分段未指定取数索引");
|
||||
}
|
||||
if (inputStrs != null && Integer.parseInt(seqDetailRule) < inputStrs.size()) {
|
||||
seqValue.append(inputStrs.get(Integer.parseInt(seqDetailRule)));
|
||||
}
|
||||
}
|
||||
// 4-3-日期分段处理
|
||||
else if (Objects.equals(sequenceDetail.getSequenceDetailType(), SequenceDetailTypeEnum.SEQ_DETAIL_TYPE_DATE.getCode())) {
|
||||
try {
|
||||
seqValue.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern(sequenceDetail.getSequenceDetailRule())));
|
||||
} catch (Exception e) {
|
||||
throw exception(SEQUENCE_DETAIL_RULE_INVALID, "日期分段的日期格式有误");
|
||||
}
|
||||
}
|
||||
// 4-4-流水号分段处理
|
||||
else if (Objects.equals(sequenceDetail.getSequenceDetailType(), SequenceDetailTypeEnum.SEQ_DETAIL_TYPE_SEQ.getCode())) {
|
||||
if (Objects.equals(sequence.getCycleType(), SequenceCycleTypeEnum.SEQUENCE_CYCLE_PREFIX_ONLY.getCode())) {
|
||||
// 特定的循环-按序列号构成前缀组合PREFIX循环
|
||||
circulationValueAtomic.set(seqValue.toString());
|
||||
}
|
||||
|
||||
/* 定义分布式锁 */
|
||||
String lockKey = sequence.getSequenceCode() + circulationValueAtomic.get();
|
||||
RLock lock = redissonClient.getLock(lockKey);
|
||||
|
||||
try {
|
||||
// 尝试获取锁,最多等待10秒,锁过期时间60秒
|
||||
if (lock.tryLock(10, 60, java.util.concurrent.TimeUnit.SECONDS)) {
|
||||
try {
|
||||
/* 获取历史记录信息 */
|
||||
SequenceRecordDO sequenceRecord = sequenceRecordMapper.selectBySeqIdAndDetailNoAndCycleValue(
|
||||
sequence.getId(), sequenceDetail.getSequenceDetailNo(), circulationValueAtomic.get());
|
||||
int length = Integer.parseInt(sequenceDetail.getSequenceDetailRule());
|
||||
if (length <= 0) {
|
||||
throw exception(SEQUENCE_DETAIL_RULE_INVALID, "流水号分段的长度有误");
|
||||
}
|
||||
if (sequenceRecord == null) {
|
||||
seqValue.append(String.format("%0" + length + "d", 1));
|
||||
sequenceRecord = new SequenceRecordDO()
|
||||
.setSequenceId(sequence.getId())
|
||||
.setSequenceCode(sequence.getSequenceCode())
|
||||
.setSequenceDetailNo(sequenceDetail.getSequenceDetailNo())
|
||||
.setCycleValue(circulationValueAtomic.get())
|
||||
.setCurrentValue("1");
|
||||
sequenceRecordMapper.insert(sequenceRecord);
|
||||
} else {
|
||||
int nextValue = Integer.parseInt(sequenceRecord.getCurrentValue()) + 1;
|
||||
seqValue.append(String.format("%0" + length + "d", nextValue));
|
||||
sequenceRecord.setCurrentValue(String.valueOf(nextValue));
|
||||
sequenceRecordMapper.updateById(sequenceRecord);
|
||||
}
|
||||
} finally {
|
||||
/* 解除分布式锁 */
|
||||
lock.unlock();
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("获取分布式锁超时");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("获取分布式锁被中断", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取循环值
|
||||
*
|
||||
* @param circulationValue 自定义循环值
|
||||
* @param sequence 序列号主信息
|
||||
* @return 循环值
|
||||
*/
|
||||
private String getCirculationValue(String circulationValue, SequenceDO sequence) {
|
||||
SequenceCycleTypeEnum cycleType = SequenceCycleTypeEnum.getByCode(sequence.getCycleType());
|
||||
if (cycleType == null) {
|
||||
return circulationValue;
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return switch (cycleType) {
|
||||
case SEQUENCE_CYCLE_YEAR -> now.format(DateTimeFormatter.ofPattern("yyyy"));
|
||||
case SEQUENCE_CYCLE_YEAR_MONTH -> now.format(DateTimeFormatter.ofPattern("yyyy-MM"));
|
||||
case SEQUENCE_CYCLE_YEAR_MONTH_COMPACT -> now.format(DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
case SEQUENCE_CYCLE_SHORT_YEAR_MONTH -> now.format(DateTimeFormatter.ofPattern("yyMM"));
|
||||
case SEQUENCE_CYCLE_YEAR_MONTH_DAY -> now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
case SEQUENCE_CYCLE_YEAR_MONTH_DAY_COMPACT -> now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
case SEQUENCE_CYCLE_SHORT_YEAR_MONTH_DAY -> now.format(DateTimeFormatter.ofPattern("yyMMdd"));
|
||||
case SEQUENCE_CYCLE_CUSTOM ->
|
||||
circulationValue != null ? circulationValue : String.valueOf(sequence.getId());
|
||||
case SEQUENCE_CYCLE_PREFIX_ONLY ->
|
||||
// 在 generateSeqValue 中处理
|
||||
"";
|
||||
default -> circulationValue;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.sequence.SequenceMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
||||
@@ -1,11 +1,11 @@
|
||||
package cn.iocoder.yudao.module.template.controller.admin.contract.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 合同新增/修改 Request VO")
|
||||
@@ -16,7 +16,6 @@ public class DemoContractSaveReqVO {
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "合同编号不能为空")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
@@ -24,7 +23,6 @@ public class DemoContractSaveReqVO {
|
||||
private String name;
|
||||
|
||||
@Schema(description = "合同状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "合同状态不能为空")
|
||||
private Short status;
|
||||
|
||||
@Schema(description = "流程实例ID", example = "10492")
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package cn.iocoder.yudao.module.template.dal.dataobject.contract;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.annotation.BusinessCode;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BusinessBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.*;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 合同 DO
|
||||
*
|
||||
@@ -26,9 +25,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
/**
|
||||
* 支持业务基类继承:isBusiness=true 时继承 BusinessBaseDO,否则继承 BaseDO
|
||||
*/
|
||||
public class DemoContractDO extends BaseDO {
|
||||
|
||||
|
||||
public class DemoContractDO extends BusinessBaseDO {
|
||||
|
||||
/**
|
||||
* 合同ID
|
||||
@@ -38,6 +35,8 @@ public class DemoContractDO extends BaseDO {
|
||||
/**
|
||||
* 合同编号
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
|
||||
@BusinessCode("SEQ")
|
||||
private String code;
|
||||
/**
|
||||
* 合同名称
|
||||
@@ -71,25 +70,5 @@ public class DemoContractDO extends BaseDO {
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 公司ID
|
||||
*/
|
||||
private Long companyId;
|
||||
/**
|
||||
* 公司名称
|
||||
*/
|
||||
private String companyName;
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
/**
|
||||
* 岗位ID
|
||||
*/
|
||||
private Long postId;
|
||||
|
||||
}
|
||||
@@ -1,24 +1,22 @@
|
||||
package cn.iocoder.yudao.module.template.service.contract;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.template.controller.admin.contract.vo.*;
|
||||
import cn.iocoder.yudao.module.template.dal.dataobject.contract.DemoContractDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.template.controller.admin.contract.vo.DemoContractPageReqVO;
|
||||
import cn.iocoder.yudao.module.template.controller.admin.contract.vo.DemoContractRespVO;
|
||||
import cn.iocoder.yudao.module.template.controller.admin.contract.vo.DemoContractSaveReqVO;
|
||||
import cn.iocoder.yudao.module.template.dal.dataobject.contract.DemoContractDO;
|
||||
import cn.iocoder.yudao.module.template.dal.mysql.contract.DemoContractMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
|
||||
import static cn.iocoder.yudao.module.template.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.template.enums.ErrorCodeConstants.DEMO_CONTRACT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 合同 Service 实现类
|
||||
@@ -36,6 +34,9 @@ public class DemoContractServiceImpl implements DemoContractService {
|
||||
public DemoContractRespVO createDemoContract(DemoContractSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
DemoContractDO demoContract = BeanUtils.toBean(createReqVO, DemoContractDO.class);
|
||||
// 生成 a,d,f,h,y,yy,t,gg,ggdd
|
||||
List<String> inputStrs = Arrays.asList("a", "b", "c", "d", "e", "f");
|
||||
demoContract.setInputStrs(inputStrs);
|
||||
demoContractMapper.insert(demoContract);
|
||||
// 返回
|
||||
return BeanUtils.toBean(demoContract, DemoContractRespVO.class);
|
||||
|
||||
Reference in New Issue
Block a user