1.优化物料大类编码维护功能,新增编码唯一性校验、自动生成逻辑及错误码,并完善前端表单校验与界面字段调整;

2.新增物料管理根据物料大类自动生成物料编码功能;
3.修复项目订单详情页辅助项校验逻辑及供应商表单税率必填校验;
This commit is contained in:
zxy 2026-03-20 10:17:26 +08:00
parent a7f5647b67
commit dad15fb31e
16 changed files with 155 additions and 59 deletions

View File

@ -176,7 +176,10 @@ public interface ErrorCodeConstants {
ErrorCode YEAR_NUM_NOT_EXISTS = new ErrorCode(1_013_011, "数据已过期,请重新修改");
ErrorCode PROCESS_DETAIL_NOT_EXISTS = new ErrorCode(1_013_012, "数据已过期,请重新修改");
// ========== 物料大类编码维护 TODO 补充编号 ==========
ErrorCode MAT_CODE_NOT_EXISTS = new ErrorCode(1_014_001, "物料大类编码维护不存在");
// ========== 物料大类编码维护 ==========
ErrorCode MAT_CODE_NOT_EXISTS = new ErrorCode(1_014_001, "该物料大类不存在");
ErrorCode MAT_CAT_CODE_REPEAT = new ErrorCode(1_014_002, "该物料大类已存在");
ErrorCode MAT_CAT_CODE_DISABLED = new ErrorCode(1_014_003, "该物料大类没有维护物料大类编码,请维护!");
ErrorCode MAT_CAT_CODE_ERROR = new ErrorCode(1_014_004, "该物料大类编码不正确,请检查!");
}

View File

@ -14,20 +14,13 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import com.chanko.yunxi.mes.framework.common.pojo.PageParam;
import com.chanko.yunxi.mes.framework.common.pojo.PageResult;
import com.chanko.yunxi.mes.framework.common.pojo.CommonResult;
import com.chanko.yunxi.mes.framework.common.util.object.BeanUtils;
import static com.chanko.yunxi.mes.framework.common.pojo.CommonResult.success;
import com.chanko.yunxi.mes.framework.excel.core.util.ExcelUtils;
import com.chanko.yunxi.mes.framework.operatelog.core.annotations.OperateLog;
import static com.chanko.yunxi.mes.framework.operatelog.core.enums.OperateTypeEnum.*;
@ -73,6 +66,15 @@ public class MatCodeController {
return success(BeanUtils.toBean(matCode, MatCodeRespVO.class));
}
@GetMapping("/getMatCatCode")
@Operation(summary = "获得物料大类编码维护")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('base:mat-code:query')")
public CommonResult<String> getMatCatCode(@RequestParam("matCatCode") String matCatCode) {
String code = matCodeService.getMatCatCode(matCatCode);
return success(code);
}
@GetMapping("/page")
@Operation(summary = "获得物料大类编码维护分页")
@PreAuthorize("@ss.hasPermission('base:mat-code:query')")

View File

@ -2,9 +2,6 @@ package com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;

View File

@ -136,4 +136,7 @@ public class MaterialRespVO {
@ExcelProperty("首选供应商名称")
private String mainSupplierName;
private String matCate;
}

View File

@ -94,4 +94,7 @@ public class MaterialSaveReqVO {
@Schema(description = "物料logo地址")
private String logo;
@Schema(description = "物料大类")
private String matCate;
}

View File

@ -1,9 +1,6 @@
package com.chanko.yunxi.mes.module.heli.dal.dataobject.matcode;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import com.chanko.yunxi.mes.framework.mybatis.core.dataobject.BaseDO;

View File

@ -194,4 +194,7 @@ public class MaterialDO extends TenantBaseDO {
private Long purchaseOrderNoDetailId;
@TableField(exist = false)
private Long purchaseOrderNoId;
private String matCate;
}

View File

@ -28,4 +28,15 @@ public interface MatCodeMapper extends BaseMapperX<MatCodeDO> {
.orderByDesc(MatCodeDO::getId));
}
default MatCodeDO selectByMatCatCode(String matCatCode) {
return selectOne(new LambdaQueryWrapperX<MatCodeDO>()
.eq(MatCodeDO::getMatCatCode, matCatCode));
}
default MatCodeDO selectByMatCatCodeAndIdNot(String matCatCode, Long id) {
return selectOne(new LambdaQueryWrapperX<MatCodeDO>()
.eq(MatCodeDO::getMatCatCode, matCatCode)
.ne(MatCodeDO::getId, id));
}
}

View File

@ -2,11 +2,10 @@ package com.chanko.yunxi.mes.module.heli.service.matcode;
import com.chanko.yunxi.mes.framework.common.pojo.PageResult;
import com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo.MatCodePageReqVO;
import com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo.MatCodeRespVO;
import com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo.MatCodeSaveReqVO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.matcode.MatCodeDO;
import javax.validation.*;
import javax.validation.Valid;
/**
@ -54,4 +53,9 @@ public interface MatCodeService {
*/
PageResult<MatCodeDO> getMatCodePage(MatCodePageReqVO pageReqVO);
MatCodeDO getByMatCatCode(String matCatCode);
String getMatCatCode(String matCatCode);
}

View File

@ -6,6 +6,7 @@ import com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo.MatCodePageR
import com.chanko.yunxi.mes.module.heli.controller.admin.matcode.vo.MatCodeSaveReqVO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.matcode.MatCodeDO;
import com.chanko.yunxi.mes.module.heli.dal.mysql.matcode.MatCodeMapper;
import com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants;
import com.chanko.yunxi.mes.module.system.dal.dataobject.user.AdminUserDO;
import com.chanko.yunxi.mes.module.system.dal.mysql.user.AdminUserMapper;
import org.springframework.stereotype.Service;
@ -14,6 +15,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import static com.chanko.yunxi.mes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.MAT_CAT_CODE_DISABLED;
import static com.chanko.yunxi.mes.module.heli.enums.ErrorCodeConstants.MAT_CODE_NOT_EXISTS;
/**
@ -27,11 +29,29 @@ public class MatCodeServiceImpl implements MatCodeService {
@Resource
private MatCodeMapper matCodeMapper;
@Resource
private AdminUserMapper userMapper;
public static String generateMaterialCode(String matTypeCode, String curMaxSeq) {
try {
int matCode = Integer.parseInt(matTypeCode);
// curMaxSeq 转换为数字
int curMaxSeqNum = Integer.parseInt(curMaxSeq) + 1;
int ss = matCode + curMaxSeqNum;
// ss 转为字符串不足 5 位补 前面补充0
return String.format("%05d", ss);
} catch (Exception e) {
throw exception(ErrorCodeConstants.MAT_CAT_CODE_ERROR);
}
}
@Override
public Long createMatCode(MatCodeSaveReqVO createReqVO) {
// 校验 matCatCode 唯一性
validateMatCatCodeUnique(null, createReqVO.getMatCatCode());
// 插入
MatCodeDO matCode = BeanUtils.toBean(createReqVO, MatCodeDO.class);
matCodeMapper.insert(matCode);
@ -43,11 +63,33 @@ public class MatCodeServiceImpl implements MatCodeService {
public void updateMatCode(MatCodeSaveReqVO updateReqVO) {
// 校验存在
validateMatCodeExists(updateReqVO.getId());
// 校验 matCatCode 唯一性更新时允许更新自己
validateMatCatCodeUnique(updateReqVO.getId(), updateReqVO.getMatCatCode());
// 更新
MatCodeDO updateObj = BeanUtils.toBean(updateReqVO, MatCodeDO.class);
matCodeMapper.updateById(updateObj);
}
/**
* 校验物料大类编码唯一性
*
* @param id ID创建时传 null更新时传当前记录 ID
* @param matCatCode 物料大类编码
*/
private void validateMatCatCodeUnique(Long id, String matCatCode) {
MatCodeDO existing;
if (id == null) {
// 创建检查是否存在相同的 matCatCode
existing = matCodeMapper.selectByMatCatCode(matCatCode);
} else {
// 更新检查是否存在其他记录使用了相同的 matCatCode
existing = matCodeMapper.selectByMatCatCodeAndIdNot(matCatCode, id);
}
if (existing != null) {
throw exception(ErrorCodeConstants.MAT_CAT_CODE_REPEAT);
}
}
@Override
public void deleteMatCode(Long id) {
// 校验存在
@ -67,11 +109,33 @@ public class MatCodeServiceImpl implements MatCodeService {
return matCodeMapper.selectById(id);
}
@Override
public MatCodeDO getByMatCatCode(String matCatCode) {
MatCodeDO matCodeDO = matCodeMapper.selectByMatCatCode(matCatCode);
if (matCodeDO == null) {
throw exception(MAT_CODE_NOT_EXISTS);
}
return matCodeDO;
}
@Override
public String getMatCatCode(String matCatCode) {
MatCodeDO matCodeDO = matCodeMapper.selectByMatCatCode(matCatCode);
if (matCodeDO == null) {
throw exception(MAT_CAT_CODE_DISABLED);
}
if (Boolean.FALSE.equals(matCodeDO.getStatus())) {
throw exception(MAT_CAT_CODE_DISABLED);
}
return generateMaterialCode(matCodeDO.getMatTypeCode(), matCodeDO.getCurMaxSeq());
}
@Override
public PageResult<MatCodeDO> getMatCodePage(MatCodePageReqVO pageReqVO) {
PageResult<MatCodeDO> matCodeDOPageResult = matCodeMapper.selectPage(pageReqVO);
PageResult<MatCodeDO> pageResult = matCodeMapper.selectPage(pageReqVO);
// 查询创建人根据creator字段,查询用户信息
matCodeDOPageResult.getList().forEach(matCodeDO -> {
pageResult.getList().forEach(matCodeDO -> {
if (matCodeDO.getCreator() != null) {
AdminUserDO user = userMapper.selectById(matCodeDO.getCreator());
if (user != null) {
@ -79,7 +143,7 @@ public class MatCodeServiceImpl implements MatCodeService {
}
}
});
return matCodeDOPageResult;
return pageResult;
}
}

View File

@ -19,6 +19,11 @@ export const getMatCode = async (id: number) => {
return await request.get({ url: `/heli/matcode/get?id=` + id })
}
// 查询物料大类编码维护详情
export const getMatCatCode = async (id: number) => {
return await request.get({ url: `/heli/matcode/getMatCatCode?matCatCode=` + id })
}
// 新增物料大类编码维护
export const createMatCode = async (data: MatCodeVO) => {
return await request.post({ url: `/heli/matcode/create`, data })

View File

@ -9,7 +9,7 @@
v-loading="formLoading"
>
<el-form-item label="物料大类" prop="matCatCode">
<el-select v-model="formData.matCatCode" clearable placeholder="请选择物料大类" @change="handleMatCatChange">
<el-select v-model="formData.matCatCode" clearable placeholder="请选择物料大类" @change="handleMatCatChange" >
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)"
:key="dict.value"
@ -19,10 +19,10 @@
</el-select>
</el-form-item>
<el-form-item label="物料分类编码" prop="matTypeCode" >
<el-input v-model="formData.matTypeCode" placeholder="请输入物料分类编码" />
<el-input v-model="formData.matTypeCode" placeholder="请输入物料分类编码" maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item label="最大流水号" prop="curMaxSeq" >
<el-input v-model="formData.curMaxSeq" placeholder="请输入当前最大流水号" />
<el-input v-model="formData.curMaxSeq" placeholder="请输入当前最大流水号" maxlength="5" show-word-limit/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
@ -58,8 +58,14 @@ const formData = ref({
})
const formRules = reactive({
matCatCode: [{ required: true, message: '物料大类不能为空', trigger: 'blur' }],
matTypeCode: [{ required: true, message: '物料分类编码不能为空', trigger: 'blur' }],
curMaxSeq: [{ required: true, message: '最大流水号不能为空', trigger: 'blur' }],
matTypeCode: [
{ required: true, message: '物料分类编码不能为空', trigger: 'blur' },
{ max: 10, message: '物料分类编码最多10个字符', trigger: 'blur' }
],
curMaxSeq: [
{ required: true, message: '最大流水号不能为空', trigger: 'blur' },
{ max: 5, message: '最大流水号最多5个字符', trigger: 'blur' }
],
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref

View File

@ -6,9 +6,9 @@
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="80px"
label-width="90px"
>
<el-form-item label="编码" prop="matCatCode">
<el-form-item label="物料大类" prop="matCatCode">
<el-select v-model="queryParams.matCatCode" clearable placeholder="请选择物料大类" class="!w-250px">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)"
@ -18,7 +18,7 @@
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-form-item label="启用状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
@ -41,15 +41,6 @@
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<!-- <el-button-->
<!-- type="success"-->
<!-- plain-->
<!-- @click="handleExport"-->
<!-- :loading="exportLoading"-->
<!-- v-hasPermi="['heli:mat-code:export']"-->
<!-- >-->
<!-- <Icon icon="ep:download" class="mr-5px" /> 导出-->
<!-- </el-button>-->
</el-form-item>
</el-form>
</ContentWrap>
@ -61,7 +52,7 @@
<el-table-column label="物料大类编码" align="center" prop="matCatCode" />
<el-table-column label="物料大类名称" align="center" prop="matCatName" />
<el-table-column label="物料分类编码" align="center" prop="matTypeCode" />
<el-table-column label="当前最大编码" align="center" prop="curMaxSeq" />
<el-table-column label="当前最大流水号" align="center" prop="curMaxSeq" />
<el-table-column label="启用状态" align="center" prop="status" width="100px">
<template #default="scope">
<el-tag :type="scope.row.status === true ? 'success' : 'danger'">
@ -118,7 +109,7 @@ import * as MatCodeApi from '@/api/heli/matcode'
import MatCodeForm from './MatCodeForm.vue'
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
defineOptions({ name: 'MatCode' })
defineOptions({ name: 'Matcode' })
const message = useMessage() //
const { t } = useI18n() //
@ -182,21 +173,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await MatCodeApi.exportMatCode(queryParams)
download.excel(data, '物料大类编码维护.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()

View File

@ -11,7 +11,7 @@
<UploadImg v-model="formData.logo" />
</el-form-item>
<el-form-item label="物料编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入物料编码" class="!w-250px" />
<el-input v-model="formData.code" placeholder="请输入物料编码" class="!w-250px"/>
</el-form-item>
<el-form-item label="物料名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入物料名称" class="!w-250px" />
@ -124,6 +124,7 @@ import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } f
import * as MaterialApi from '@/api/heli/material'
import {getSupplierPage} from "@/api/heli/supplier";
import SupplierSelect from '@/views/heli/hlvuestyle/supplierSelect.vue'
import { getMatCatCode} from "@/api/heli/matcode";
const { t } = useI18n() //
const message = useMessage() //
@ -277,4 +278,26 @@ const handleSelectedSupplier = (newValue: any) => {
formData.value.mainSupplierId = newValue?.id
}
/** 监听物料类型变化查询matcode并更新code */
watch(() => formData.value.matCate, async (newVal) => {
if (!newVal) {
formData.value.code = undefined
return
}
try {
const allData = await getMatCatCode(newVal)
if (allData != null) {
formData.value.code = allData
} else {
formData.value.code = null
}
} catch (error) {
console.error('查询matcode失败:', error)
formData.value.code = null
//
// message.error('')
}
})
</script>

View File

@ -1009,13 +1009,12 @@ type="textarea" v-model="formData.activeOpinion" placeholder="请输入打回原
}],
auItem: [{
validator: (rule, value, callback) => {
if (value === null || value === undefined) {
if (value === null || value === undefined || value === '') {
callback(new Error('辅助项必须跟新中大一致,请确认!'))
} else {
callback()
}
},
trigger: 'blur'
}
}],
projectStartTime: [{
required: true,

View File

@ -362,7 +362,7 @@ const formRules = reactive({
{
validator: (rule, value, callback) => {
if (value === '' || value === null || value === undefined) {
callback()
callback(new Error('税率不能为空'))
return
}
// 1