diff --git a/sql/dm/patch.sql b/sql/dm/patch.sql index 1455f2bb..d97f7849 100644 --- a/sql/dm/patch.sql +++ b/sql/dm/patch.sql @@ -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'); diff --git a/sql/dm/ruoyi-vue-pro-dm8.sql b/sql/dm/ruoyi-vue-pro-dm8.sql index 09f8caaa..20121426 100644 --- a/sql/dm/ruoyi-vue-pro-dm8.sql +++ b/sql/dm/ruoyi-vue-pro-dm8.sql @@ -4934,4 +4934,4 @@ COMMENT ON COLUMN system_seq_rcd.create_time IS '创建时间'; COMMENT ON COLUMN system_seq_rcd.updater IS '更新者'; COMMENT ON COLUMN system_seq_rcd.update_time IS '更新时间'; COMMENT ON COLUMN system_seq_rcd.deleted IS '是否删除'; -COMMENT ON TABLE system_seq_rcd IS '系统序列号记录表'; \ No newline at end of file +COMMENT ON TABLE system_seq_rcd IS '系统序列号记录表'; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/sequence/SequenceCommonApi.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/sequence/SequenceCommonApi.java new file mode 100644 index 00000000..c171115f --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/sequence/SequenceCommonApi.java @@ -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 getNextSequence(@RequestParam("sequenceCode") String sequenceCode, + @RequestParam(value = "circulationValue", required = false) String circulationValue, + @RequestParam(value = "inputStrs", required = false) List inputStrs); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-business/src/main/java/cn/iocoder/yudao/framework/business/annotation/BusinessCode.java b/yudao-framework/yudao-spring-boot-starter-biz-business/src/main/java/cn/iocoder/yudao/framework/business/annotation/BusinessCode.java deleted file mode 100644 index 6b21bdfd..00000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-business/src/main/java/cn/iocoder/yudao/framework/business/annotation/BusinessCode.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.framework.business.annotation; - -/** - * @author chenbowen - * - * 业务代码自动补全的注解,在 DO filed 中与 @TableField(fill = FieldFill.INSERT) 一起标注后自动新增时生成 Code chenbowen - */ -public @interface BusinessCode { - -} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 2ee30399..8f010033 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -103,6 +103,11 @@ cn.iocoder.cloud yudao-spring-boot-starter-security + + + org.springframework.cloud + spring-cloud-starter-openfeign + diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java index 879a19aa..2e922294 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java @@ -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 { /** diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/annotation/BusinessCode.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/annotation/BusinessCode.java new file mode 100644 index 00000000..75fd3c6c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/annotation/BusinessCode.java @@ -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 ""; +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BusinessBaseDO.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BusinessBaseDO.java index 25738488..c346dd57 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BusinessBaseDO.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BusinessBaseDO.java @@ -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 inputStrs; + /** * 清除 creator、createTime、updateTime、updater 等字段,避免前端直接传递这些字段,导致被更新 */ diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java index 596c2514..ccd2fe3d 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java @@ -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,26 +61,10 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BusinessBaseDO businessBaseDO) { // 公司编号、公司名称、部门编号、部门名称、岗位编号等字段,默认不填充 // 需要在业务层手动设置 - LoginUser loginUser = getLoginUser(); - Long visitCompanyId = loginUser.getVisitCompanyId(); - Long visitDeptId = loginUser.getVisitDeptId(); - loginUser.getInfo().getOrDefault(LoginUser.INFO_KEY_POST_IDS,"[]"); - // 更加合理的写法 - Set postIds = new HashSet<>(JSONUtil.parseArray( - loginUser.getInfo().getOrDefault(LoginUser.INFO_KEY_POST_IDS, "[]") - ).toList(Long.class)); - // 如果 visitCompanyId 不存在,不能进行业务办理 - if (Objects.isNull(visitCompanyId) || Objects.isNull(visitDeptId)) { - throw exception(USER_NOT_SET_DEPT); - } - businessBaseDO.setCompanyId(visitCompanyId); - businessBaseDO.setCompanyName(loginUser.getVisitCompanyName()); - businessBaseDO.setDeptId(visitDeptId); - businessBaseDO.setDeptName(loginUser.getVisitDeptName()); - // 暂时没有具体业务要求,岗位默认当前用户第一个 todo chenbowen - businessBaseDO.setPostId(postIds.isEmpty() ? 0L : postIds.iterator().next()); - // 多租户编号,默认不填充 - businessBaseDO.setTenantId(loginUser.getTenantId()); + autoFillDeptInfo(businessBaseDO); + + // 自动填充带 @BusinessCode 注解的字段序列 + autoFillBusinessCode(businessBaseDO); } } @@ -93,4 +83,64 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { 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 inputStrs = Optional.ofNullable(businessBaseDO.getInputStrs()).orElse(new ArrayList<>()); + // 调用远程服务获取序列号 + if (sequenceCommonApi != null) { + CommonResult 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(); + loginUser.getInfo().getOrDefault(LoginUser.INFO_KEY_POST_IDS,"[]"); + // 更加合理的写法 + Set postIds = new HashSet<>(JSONUtil.parseArray( + loginUser.getInfo().getOrDefault(LoginUser.INFO_KEY_POST_IDS, "[]") + ).toList(Long.class)); + // 如果 visitCompanyId 不存在,不能进行业务办理 + if (Objects.isNull(visitCompanyId) || Objects.isNull(visitDeptId)) { + throw exception(USER_NOT_SET_DEPT); + } + businessBaseDO.setCompanyId(visitCompanyId); + businessBaseDO.setCompanyName(loginUser.getVisitCompanyName()); + businessBaseDO.setDeptId(visitDeptId); + businessBaseDO.setDeptName(loginUser.getVisitDeptName()); + // 暂时没有具体业务要求,岗位默认当前用户第一个 todo chenbowen + businessBaseDO.setPostId(postIds.isEmpty() ? 0L : postIds.iterator().next()); + // 多租户编号,默认不填充 + businessBaseDO.setTenantId(loginUser.getTenantId()); + } } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApi.java index 2f851b39..99ed1083 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApi.java @@ -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 getNextSequence(@RequestParam("sequenceCode") String sequenceCode, + @RequestParam(value = "circulationValue", required = false) String circulationValue, + @RequestParam(value = "inputStrs", required = false) List inputStrs); + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailRuleEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailRuleEnum.java new file mode 100644 index 00000000..8a9f89de --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailRuleEnum.java @@ -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; +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailTypeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailTypeEnum.java new file mode 100644 index 00000000..c98235a5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sequence/SequenceDetailTypeEnum.java @@ -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; + } +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApiImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApiImpl.java new file mode 100644 index 00000000..a18866f5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/api/sequence/SequenceApiImpl.java @@ -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 getNextSequence(String sequenceCode, String circulationValue, List inputStrs) { + String result = sequenceService.getNextSeq(sequenceCode, circulationValue, inputStrs); + return success(result); + } + +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/SequenceController.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/SequenceController.java new file mode 100644 index 00000000..80d3f1c0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/SequenceController.java @@ -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 createSequence(@Valid @RequestBody SequenceSaveReqVO createReqVO) { + return success(sequenceService.createSequence(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新系统序列号") + @PreAuthorize("@ss.hasPermission('system:sequence:update')") + public CommonResult 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 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 deleteSequenceList(@RequestParam("ids") List 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 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> getSequencePage(@Valid SequencePageReqVO pageReqVO) { + PageResult 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 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> 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> 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 generateSequence(@RequestBody SequenceGenerateReqVO reqVO) { + String result = sequenceService.getNextSeq(reqVO.getSequenceCode(), reqVO.getCirculationValue(), reqVO.getInputStrs()); + return success(result); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceGenerateReqVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceGenerateReqVO.java new file mode 100644 index 00000000..67b321e5 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceGenerateReqVO.java @@ -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 inputStrs; + +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequencePageReqVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequencePageReqVO.java new file mode 100644 index 00000000..2be764c4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequencePageReqVO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceRespVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceRespVO.java new file mode 100644 index 00000000..cdfd715f --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceRespVO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceSaveReqVO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceSaveReqVO.java new file mode 100644 index 00000000..1463af35 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sequence/vo/SequenceSaveReqVO.java @@ -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 sequenceDetails; + + @Schema(description = "系统序列号记录列表") + private List sequenceRecords; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDO.java new file mode 100644 index 00000000..5d492a13 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDetailDO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDetailDO.java new file mode 100644 index 00000000..de954f81 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceDetailDO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceRecordDO.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceRecordDO.java new file mode 100644 index 00000000..c5903138 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sequence/SequenceRecordDO.java @@ -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; + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceDetailMapper.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceDetailMapper.java new file mode 100644 index 00000000..6c3fecf0 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceDetailMapper.java @@ -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 { + + default List selectListBySequenceId(Long sequenceId) { + return selectList(SequenceDetailDO::getSequenceId, sequenceId); + } + + default int deleteBySequenceId(Long sequenceId) { + return delete(SequenceDetailDO::getSequenceId, sequenceId); + } + + default int deleteBySequenceIds(List sequenceIds) { + return deleteBatch(SequenceDetailDO::getSequenceId, sequenceIds); + } + +} diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceMapper.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceMapper.java new file mode 100644 index 00000000..f01ac431 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceMapper.java @@ -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 { + + default PageResult selectPage(SequencePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .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); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceRecordMapper.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceRecordMapper.java new file mode 100644 index 00000000..a529d70b --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sequence/SequenceRecordMapper.java @@ -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 { + + default List selectListBySequenceId(Long sequenceId) { + return selectList(SequenceRecordDO::getSequenceId, sequenceId); + } + + default int deleteBySequenceId(Long sequenceId) { + return delete(SequenceRecordDO::getSequenceId, sequenceId); + } + + default int deleteBySequenceIds(List sequenceIds) { + return deleteBatch(SequenceRecordDO::getSequenceId, sequenceIds); + } + + default SequenceRecordDO selectBySeqIdAndDetailNoAndCycleValue(Long sequenceId, String sequenceDetailNo, String cycleValue) { + return selectOne(new LambdaQueryWrapperX() + .eq(SequenceRecordDO::getSequenceId, sequenceId) + .eq(SequenceRecordDO::getSequenceDetailNo, sequenceDetailNo) + .eq(SequenceRecordDO::getCycleValue, cycleValue)); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceService.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceService.java new file mode 100644 index 00000000..6bd5c662 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceService.java @@ -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 ids); + + /** + * 获得系统序列号 + * + * @param id 编号 + * @return 系统序列号 + */ + SequenceDO getSequence(Long id); + + /** + * 获得系统序列号分页 + * + * @param pageReqVO 分页查询 + * @return 系统序列号分页 + */ + PageResult getSequencePage(SequencePageReqVO pageReqVO); + + // ==================== 子表(系统序列号分段明细) ==================== + + /** + * 获得系统序列号分段明细列表 + * + * @param sequenceId 序列Id + * @return 系统序列号分段明细列表 + */ + List getSequenceDetailListBySequenceId(Long sequenceId); + + // ==================== 子表(系统序列号记录) ==================== + + /** + * 获得系统序列号记录列表 + * + * @param sequenceId 序列Id + * @return 系统序列号记录列表 + */ + List getSequenceRecordListBySequenceId(Long sequenceId); + + // ==================== 序列号生成方法 ==================== + /** + * 根据序列号编码生成下一个序列号 + * + * @param sequenceCode 序列号编码 + * @param circulationValue 序列号循环类型条件值 + * @param inputStrs 自定义字符串数组 + * @return 最新序列号 + */ + String getNextSeq(String sequenceCode, String circulationValue, List inputStrs); + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceServiceImpl.java b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceServiceImpl.java new file mode 100644 index 00000000..df52443a --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/sequence/SequenceServiceImpl.java @@ -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 ids) { + // 校验存在 + validateSequenceExists(ids); + // 删除 + sequenceMapper.deleteByIds(ids); + + // 删除子表 + deleteSequenceDetailBySequenceIds(ids); + deleteSequenceRecordBySequenceIds(ids); + } + + private void validateSequenceExists(List ids) { + List 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 getSequencePage(SequencePageReqVO pageReqVO) { + return sequenceMapper.selectPage(pageReqVO); + } + + // ==================== 子表(系统序列号分段明细) ==================== + + @Override + public List getSequenceDetailListBySequenceId(Long sequenceId) { + return sequenceDetailMapper.selectListBySequenceId(sequenceId); + } + + private void createSequenceDetailList(Long sequenceId, String sequenceCode, List 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 list) { + list.forEach(o -> o.setSequenceId(sequenceId).clean()); + list.forEach(o -> o.setSequenceCode(sequenceCode).clean()); + List oldList = sequenceDetailMapper.selectListBySequenceId(sequenceId); + List> 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 sequenceIds) { + sequenceDetailMapper.deleteBySequenceIds(sequenceIds); + } + + // ==================== 子表(系统序列号记录) ==================== + + @Override + public List getSequenceRecordListBySequenceId(Long sequenceId) { + return sequenceRecordMapper.selectListBySequenceId(sequenceId); + } + + private void createSequenceRecordList(Long sequenceId, String sequenceCode, List 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 list) { + list.forEach(o -> o.setSequenceId(sequenceId).clean()); + list.forEach(o -> o.setSequenceCode(sequenceCode).clean()); + List oldList = sequenceRecordMapper.selectListBySequenceId(sequenceId); + List> 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 sequenceIds) { + sequenceRecordMapper.deleteBySequenceIds(sequenceIds); + } + + @Override + public String getNextSeq(String sequenceCode, String circulationValue, List inputStrs) { + StringBuilder seqValue = new StringBuilder(); + // 1-获取序列号配置 + SequenceDO sequence = sequenceMapper.selectBySequenceCode(sequenceCode); + if (sequence == null) { + throw exception(SEQUENCE_NOT_EXISTS); + } + + // 2-获取序列号分段明细 + List 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 sequenceDetails, + String circulationValue, + List inputStrs, + StringBuilder seqValue) { + // 4-生成序列号 + AtomicReference 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; + }; + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-server/src/main/resources/mapper/sequence/SequenceMapper.xml b/yudao-module-system/yudao-module-system-server/src/main/resources/mapper/sequence/SequenceMapper.xml new file mode 100644 index 00000000..b79dd3e4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-server/src/main/resources/mapper/sequence/SequenceMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/controller/admin/contract/vo/DemoContractSaveReqVO.java b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/controller/admin/contract/vo/DemoContractSaveReqVO.java index fef50cb3..1f85c049 100644 --- a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/controller/admin/contract/vo/DemoContractSaveReqVO.java +++ b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/controller/admin/contract/vo/DemoContractSaveReqVO.java @@ -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") diff --git a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/dal/dataobject/contract/DemoContractDO.java b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/dal/dataobject/contract/DemoContractDO.java index 8003a5c2..3e8390f6 100644 --- a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/dal/dataobject/contract/DemoContractDO.java +++ b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/dal/dataobject/contract/DemoContractDO.java @@ -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; } \ No newline at end of file diff --git a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/service/contract/DemoContractServiceImpl.java b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/service/contract/DemoContractServiceImpl.java index 0e9d0cdf..4ae1edf0 100644 --- a/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/service/contract/DemoContractServiceImpl.java +++ b/yudao-module-template/yudao-module-template-server/src/main/java/cn/iocoder/yudao/module/template/service/contract/DemoContractServiceImpl.java @@ -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 inputStrs = Arrays.asList("a", "b", "c", "d", "e", "f"); + demoContract.setInputStrs(inputStrs); demoContractMapper.insert(demoContract); // 返回 return BeanUtils.toBean(demoContract, DemoContractRespVO.class);