Просмотр исходного кода

fix(s0): restore number type create with domain validation

YY968XX 1 день назад
Родитель
Сommit
5ec6a04ede

+ 1 - 1
Web/package.json

@@ -1,7 +1,7 @@
 {
 	"name": "admin.net",
 	"type": "module",
-	"version": "2.4.190",
+	"version": "2.4.191",
 	"packageManager": "pnpm@10.32.1",
 	"lastBuildTime": "2026.03.15",
 	"description": "Admin.NET 站在巨人肩膀上的 .NET 通用权限开发框架",

+ 2 - 1
Web/src/views/aidop/s0/warehouse/NbrTypeList.vue

@@ -64,7 +64,7 @@
 				<el-form-item label="类型描述"><el-input v-model="form.descr1" /></el-form-item>
 				<el-form-item label="单号分类"><el-input v-model="form.nbrClass" /></el-form-item>
 				<el-form-item label="部门"><el-input v-model="form.dept" /></el-form-item>
-				<el-form-item label="域编码"><el-input v-model="form.domainCode" /></el-form-item>
+				<el-form-item label="域编码" prop="domainCode"><el-input v-model="form.domainCode" /></el-form-item>
 				<el-form-item label="启用"><el-switch v-model="form.isActive" /></el-form-item>
 			</el-form>
 			<template #footer>
@@ -115,6 +115,7 @@ const formFactoryOptions = computed(() => {
 
 const rules: FormRules = {
 	nbrType: [{ required: true, message: '请填写单号类型编码', trigger: 'blur' }],
+	domainCode: [{ required: true, message: '请填写域编码', trigger: 'blur' }],
 };
 
 watch(

+ 6 - 3
server/Admin.NET.Web.Entry/Admin.NET.Web.Entry.csproj

@@ -11,9 +11,9 @@
     <GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
     <Copyright>Admin.NET</Copyright>
     <Description>Admin.NET 通用权限开发平台</Description>
-    <AssemblyVersion>1.0.184</AssemblyVersion>
-    <FileVersion>1.0.184</FileVersion>
-    <Version>1.0.184</Version>
+    <AssemblyVersion>1.0.185</AssemblyVersion>
+    <FileVersion>1.0.185</FileVersion>
+    <Version>1.0.185</Version>
   </PropertyGroup>
 
   <ItemGroup>
@@ -163,6 +163,9 @@
     <None Update="UpdateScripts\1.0.182.sql">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="UpdateScripts\1.0.185.sql">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 
   <ItemGroup>

+ 92 - 0
server/Admin.NET.Web.Entry/UpdateScripts/1.0.185.sql

@@ -0,0 +1,92 @@
+-- ============================================================
+-- 1.0.185.sql
+-- S0-NBRTYPE-CREATE-RECID-SCHEMA-AND-DOMAINCODE-REQUIRED-FIX-1
+--
+-- 业务目标:修复 NbrTypeMaster(单号类型)合法新增对任意输入返回 500/S01999 的根因。
+--   NbrTypeMaster 表存在新旧两套列:业务真实数据落在旧 PascalCase 列(RecID / Domain / NbrType / IsActive 等);
+--   snake_case 列为历史 CodeFirst 阶段补加、当前 70 行业务列全空(rec_id=0 / domain_code='' / nbr_type='' / is_active=0)的孤立列。
+--   实体 AdoS0NbrTypeMaster 仅映射 PascalCase 业务列 + 组织 snake 列(company_ref_id/factory_ref_id),
+--   未映射孤立列 rec_id(bigint) / domain_code(varchar(50)) / nbr_type(varchar(100)) / is_active(tinyint(1))。
+--   这 4 列为 NOT NULL 且无默认值,INSERT 时无值 → 违反 NOT NULL 约束 → 落库失败 → 接口 500/S01999
+--   (MySQL 原文 Field 'rec_id' doesn't have a default value;rec_id 仅因列序最先报错,修复需 4 列一并放开)。
+--   本脚本将这 4 个已确认孤立的 NOT NULL 列改为可空,使新增可正常落库。
+--   (与 1.0.174.sql 对 BarCodeNbr 的同类修复同范式。)
+--
+-- 授权范围(用户拍板方案 A):
+--   - 仅将 rec_id、domain_code、nbr_type、is_active 改为 NULL。
+--   - 不删除任何列。
+--   - 不修改 PascalCase 真实业务列(RecID / Domain / NbrType / NbrClass / IsActive / CreateUser 等)。
+--   - 不修改 company_ref_id / factory_ref_id(NOT NULL 但实体已写入,不阻断 INSERT)。
+--   - 不更新任何业务数据。
+--
+-- 安全保证(阶段 0 实测 aidopdev 依据):
+--   - 4 列均不在任何索引/PK(PK=RecID,唯一键=IX_NbrTypeMaster(Domain,NbrClass,NbrType))。
+--   - 70 行该 4 列全为默认值(rec_id=0 / domain_code='' / nbr_type='' / is_active=0),零业务数据。
+--   - 全仓无任何代码引用这 4 个 snake 列;仅 1.0.176.sql 历史 UPDATE 过 company_ref_id/factory_ref_id(不涉本 4 列)。
+--   - 幂等:通过 information_schema.COLUMNS 前置判断「列存在且当前为 NOT NULL」才执行 ALTER,
+--     再次执行(列已可空或列不存在)自动降级为 SELECT 1,0 变更。
+--   - 不 INSERT / UPDATE / DELETE / DROP / TRUNCATE 业务数据;不动其他表、其他列、索引、唯一约束。
+--   - 列类型与注释保持原样,仅放开 NULL 约束。
+--
+-- 回滚 SQL(仅在需要恢复 NOT NULL 时人工执行,不默认运行;
+--   回滚前必须确认列内无 NULL 行,否则 ALTER 会失败):
+--   ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `rec_id` bigint NOT NULL COMMENT '主键';
+--   ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `domain_code` varchar(50) NOT NULL COMMENT '工厂域编码';
+--   ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `nbr_type` varchar(100) NOT NULL COMMENT '单号类型编码';
+--   ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `is_active` tinyint(1) NOT NULL COMMENT '是否启用';
+-- ============================================================
+
+-- ─── 1) 幂等放开 rec_id NOT NULL(仅当列存在且当前为 NOT NULL 时执行) ───
+SET @need_rec_id := (
+  SELECT COUNT(*) FROM information_schema.COLUMNS
+   WHERE TABLE_SCHEMA = DATABASE()
+     AND TABLE_NAME = 'NbrTypeMaster'
+     AND COLUMN_NAME = 'rec_id'
+     AND IS_NULLABLE = 'NO'
+);
+SET @sql := IF(@need_rec_id = 1,
+  'ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `rec_id` bigint NULL COMMENT ''主键''',
+  'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+
+-- ─── 2) 幂等放开 domain_code NOT NULL(仅当列存在且当前为 NOT NULL 时执行) ───
+SET @need_domain_code := (
+  SELECT COUNT(*) FROM information_schema.COLUMNS
+   WHERE TABLE_SCHEMA = DATABASE()
+     AND TABLE_NAME = 'NbrTypeMaster'
+     AND COLUMN_NAME = 'domain_code'
+     AND IS_NULLABLE = 'NO'
+);
+SET @sql := IF(@need_domain_code = 1,
+  'ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `domain_code` varchar(50) NULL COMMENT ''工厂域编码''',
+  'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+
+-- ─── 3) 幂等放开 nbr_type NOT NULL(仅当列存在且当前为 NOT NULL 时执行) ───
+SET @need_nbr_type := (
+  SELECT COUNT(*) FROM information_schema.COLUMNS
+   WHERE TABLE_SCHEMA = DATABASE()
+     AND TABLE_NAME = 'NbrTypeMaster'
+     AND COLUMN_NAME = 'nbr_type'
+     AND IS_NULLABLE = 'NO'
+);
+SET @sql := IF(@need_nbr_type = 1,
+  'ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `nbr_type` varchar(100) NULL COMMENT ''单号类型编码''',
+  'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+
+-- ─── 4) 幂等放开 is_active NOT NULL(仅当列存在且当前为 NOT NULL 时执行) ───
+SET @need_is_active := (
+  SELECT COUNT(*) FROM information_schema.COLUMNS
+   WHERE TABLE_SCHEMA = DATABASE()
+     AND TABLE_NAME = 'NbrTypeMaster'
+     AND COLUMN_NAME = 'is_active'
+     AND IS_NULLABLE = 'NO'
+);
+SET @sql := IF(@need_is_active = 1,
+  'ALTER TABLE `NbrTypeMaster` MODIFY COLUMN `is_active` tinyint(1) NULL COMMENT ''是否启用''',
+  'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

+ 3 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Controllers/S0/Warehouse/AdoS0NbrTypesController.cs

@@ -66,6 +66,9 @@ public class AdoS0NbrTypesController : ControllerBase
     [HttpPost]
     public async Task<IActionResult> CreateAsync([FromBody] AdoS0NbrTypeUpsertDto dto)
     {
+        if (string.IsNullOrWhiteSpace(dto.DomainCode))
+            return AdoS0ApiErrors.InvalidRequest("请填写域编码");
+
         if (await _rep.IsAnyAsync(x => x.FactoryRefId == dto.FactoryRefId && x.NbrType == dto.NbrType))
             return AdoS0ApiErrors.Conflict(AdoS0ErrorCodes.DuplicateCode, "单号类型编码已存在");