feat(customer): 新增客户代码和税率字段

- 在CustomerDO中新增custCode和taxRate字段
- 在CustomerRespVO和CustomerSaveReqVO中新增custCode字段
- 在CustomerForm.vue中新增客户代码表单项
- 在index.vue中新增客户代码表格列
- 将客户简称验证注解从@NotEmpty改为@NotBlank
- 更新API接口定义以包含custCode字段

feat(projectorder): 新增辅助项字段

- 在ProjectOrderDO中新增auItem字段
- 在ProjectOrderRespVO和ProjectOrderSaveReqVO中新增auItem字段
- 在项目订单详情页面中新增辅助项表单项
- 添加辅助项字段验证规则

feat(storage): 新增供应商信息关联功能

- 在StorageDO中新增supplierId、brief、name字段
- 在StorageRespVO和StorageSaveReqVO中新增供应商相关字段
- 在StorageForm.vue中新增供应商下拉选择组件
- 实现采购订单选择时自动带出供应商信息功能
- 集成供应商列表查询和显示功能
- 在入库单保存时同步供应商信息

feat(supplier): 新增税率字段

- 在SupplierDO中新增taxRate字段
- 在SupplierRespVO和SupplierSaveReqVO中新增taxRate字段
- 在SupplierForm.vue中新增税率输入框并添加百分号后缀
This commit is contained in:
zxy 2026-03-17 15:47:27 +08:00
parent 117d9f50a5
commit 41428661ea
20 changed files with 163 additions and 23 deletions

View File

@ -23,6 +23,10 @@ public class CustomerRespVO {
@ExcelProperty("客户编码") @ExcelProperty("客户编码")
private String code; private String code;
@Schema(description = "客户代码", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("客户代码")
private String custCode;
@Schema(description = "简码", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "简码", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("简码") @ExcelProperty("简码")
private String brief; private String brief;
@ -155,5 +159,4 @@ public class CustomerRespVO {
@Schema(description = "公司税号") @Schema(description = "公司税号")
@ExcelProperty("公司税号") @ExcelProperty("公司税号")
private String taxNo; private String taxNo;
}
}

View File

@ -21,9 +21,13 @@ public class CustomerSaveReqVO {
private String brief; private String brief;
@Schema(description = "客户简称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") @Schema(description = "客户简称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotEmpty(message = "客户简称不能为空") @NotBlank(message = "客户简称不能为空")
private String name; private String name;
@Schema(description = "客户代码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "客户代码不能为空")
private String custCode;
@Schema(description = "客户全称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") @Schema(description = "客户全称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@NotEmpty(message = "客户全称不能为空") @NotEmpty(message = "客户全称不能为空")
private String fullName; private String fullName;
@ -107,4 +111,7 @@ public class CustomerSaveReqVO {
@Schema(description = "公司税号") @Schema(description = "公司税号")
private String taxNo; private String taxNo;
@Schema(description = "税率")
private Integer taxRate;
} }

View File

@ -254,4 +254,8 @@ public class ProjectOrderRespVO {
@ExcelProperty("六次付款 保留四位小数") @ExcelProperty("六次付款 保留四位小数")
private LocalDateTime sixFuKuanTime; private LocalDateTime sixFuKuanTime;
@Schema(description = "辅助项")
@ExcelProperty("辅助项")
private String auItem;
} }

View File

@ -197,4 +197,7 @@ public class ProjectOrderSaveReqVO {
@Schema(description = "六次付款时间") @Schema(description = "六次付款时间")
private LocalDateTime sixFuKuanTime; private LocalDateTime sixFuKuanTime;
@Schema(description = "辅助项")
private String auItem;
} }

View File

@ -114,4 +114,10 @@ public class StorageRespVO {
@ExcelProperty("即入即出标志 1 是0不是") @ExcelProperty("即入即出标志 1 是0不是")
private Boolean inOutFlag; private Boolean inOutFlag;
// 供应商信息
private Long supplierId;
private String brief;
private String name;
} }

View File

@ -87,4 +87,6 @@ public class StorageSaveReqVO {
private Boolean inOutFlag; private Boolean inOutFlag;
private Long supplierId;
} }

View File

@ -158,4 +158,8 @@ public class SupplierRespVO {
@ExcelProperty("公司税号") @ExcelProperty("公司税号")
private String taxNo; private String taxNo;
} @Schema(description = "税率")
@ExcelProperty("税率")
private String taxRate;
}

View File

@ -106,4 +106,7 @@ public class SupplierSaveReqVO {
@Schema(description = "公司税号") @Schema(description = "公司税号")
private String taxNo; private String taxNo;
@Schema(description = "税率")
private Integer taxRate;
} }

View File

@ -31,6 +31,8 @@ public class CustomerDO extends BaseDO {
* 客户编码 * 客户编码
*/ */
private String code; private String code;
private String custCode;
/** /**
* 简码 * 简码
*/ */
@ -153,4 +155,6 @@ public class CustomerDO extends BaseDO {
*/ */
private String taxNo; private String taxNo;
private Integer taxRate;
} }

View File

@ -316,6 +316,8 @@ public class ProjectOrderDO extends BaseDO {
@TableField(exist = false) @TableField(exist = false)
private Set<String> alterFieldNames; private Set<String> alterFieldNames;
private String auItem;
public boolean canSave(){ public boolean canSave(){
return this.orderStatus.intValue() <= ProjectOrderStatusEnum.SAVE.getCode(); return this.orderStatus.intValue() <= ProjectOrderStatusEnum.SAVE.getCode();
} }

View File

@ -148,4 +148,9 @@ public class StorageDO extends BaseDO {
private Long headerId; private Long headerId;
@TableField(exist = false) @TableField(exist = false)
private String type; private String type;
// 供应商信息
private Long supplierId;
private String brief;
private String name;
} }

View File

@ -153,4 +153,6 @@ public class SupplierDO extends BaseDO {
*/ */
private String taxNo; private String taxNo;
private Integer taxRate;
} }

View File

@ -14,6 +14,7 @@ import com.chanko.yunxi.mes.module.heli.controller.admin.storageinventory.Storag
import com.chanko.yunxi.mes.module.heli.controller.admin.storagemat.vo.StorageMatSaveReqVO; import com.chanko.yunxi.mes.module.heli.controller.admin.storagemat.vo.StorageMatSaveReqVO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.bdgzsomthing.bdgzsomthingDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.bdgzsomthing.bdgzsomthingDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.composition.CompositionDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.composition.CompositionDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.deliverorder.DeliverOrderDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.material.MaterialDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.material.MaterialDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.outsourcestock.OutsourceStockDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.outsourcestock.OutsourceStockDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.outsourcestockboom.OutsourceStockBoomDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.outsourcestockboom.OutsourceStockBoomDO;
@ -26,8 +27,10 @@ import com.chanko.yunxi.mes.module.heli.dal.dataobject.storageinventory.StorageI
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelog.StorageLogDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelog.StorageLogDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagelogNow.StorageLogNowDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagemat.StorageMatDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.storagemat.StorageMatDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.supplier.SupplierDO;
import com.chanko.yunxi.mes.module.heli.dal.dataobject.warehouse.WarehouseDO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.warehouse.WarehouseDO;
import com.chanko.yunxi.mes.module.heli.dal.mysql.composition.CompositionMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.composition.CompositionMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.deliverorder.DeliverOrderMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.master.MasterMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.master.MasterMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.material.MaterialMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.material.MaterialMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.outsourcestock.OutsourceStockMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.outsourcestock.OutsourceStockMapper;
@ -40,6 +43,7 @@ import com.chanko.yunxi.mes.module.heli.dal.mysql.storageinventory.StorageInvent
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogNowMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.storagelog.StorageLogNowMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storagemat.StorageMatMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.storagemat.StorageMatMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.supplier.SupplierMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.warehouse.WarehouseMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.warehouse.WarehouseMapper;
import com.chanko.yunxi.mes.module.heli.enums.BusinesTypeEnum; import com.chanko.yunxi.mes.module.heli.enums.BusinesTypeEnum;
import com.chanko.yunxi.mes.module.heli.enums.CodeEnum; import com.chanko.yunxi.mes.module.heli.enums.CodeEnum;
@ -135,8 +139,11 @@ public class StorageServiceImpl implements StorageService {
@Resource @Resource
private PnMapper pnMapper; private PnMapper pnMapper;
@Resource @Resource
private StorageLogService storageLogService; private SupplierMapper supplierMapper;
@Resource
private StorageLogService storageLogService;
/* /*
* *
* 委外验收取消提交作废入库单 * 委外验收取消提交作废入库单
@ -442,6 +449,16 @@ private StorageLogService storageLogService;
} }
// 更新 // 更新
StorageDO updateObj = BeanUtils.toBean(updateReqVO, StorageDO.class); StorageDO updateObj = BeanUtils.toBean(updateReqVO, StorageDO.class);
//根据供应商ID查询供应商信息
if (updateReqVO.getSupplierId() != null) {
SupplierDO supplierDO = supplierMapper.selectById(updateReqVO.getSupplierId());
if (supplierDO != null) {
updateObj.setName(supplierDO.getName());
updateObj.setSupplierId(supplierDO.getId());
updateObj.setBrief(supplierDO.getBrief());
}
}
storageMapper.updateById(updateObj); storageMapper.updateById(updateObj);
} }
@Override @Override

View File

@ -33,6 +33,7 @@ export interface CustomerVO {
bankNo: string bankNo: string
bankAddress: string bankAddress: string
taxNo: string taxNo: string
custCode: string
} }
// 查询客户新表分页 // 查询客户新表分页

View File

@ -19,6 +19,8 @@ export interface StorageVO {
pickmode: string pickmode: string
pickmcar: string pickmcar: string
projectSubName: string projectSubName: string
supplierId: number
name: string
} }
// 查询入/出库分页 // 查询入/出库分页

View File

@ -40,6 +40,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-col :span="24">
<el-form-item prop="custCode" label="客户代码">
<el-input v-model="formData.custCode" />
</el-form-item>
</el-col>
</el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="description"> <el-form-item label="备注" prop="description">
@ -385,6 +392,7 @@ const formData = ref({
bankNo: undefined, bankNo: undefined,
bankAddress: undefined, bankAddress: undefined,
taxNo: undefined, taxNo: undefined,
custCode: undefined,
attachments: [], attachments: [],
operateLogs: [], operateLogs: [],
alterFieldNames: [], alterFieldNames: [],
@ -667,7 +675,8 @@ const resetForm = () => {
attachments: [], attachments: [],
operateLogs: [], operateLogs: [],
alterFieldNames: [], alterFieldNames: [],
taxNo: undefined taxNo: undefined,
custCode: undefined
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }

View File

@ -85,6 +85,7 @@
<dict-tag :type="DICT_TYPE.HELI_CUSTOMER_LEVEL" :value="scope.row.level" /> <dict-tag :type="DICT_TYPE.HELI_CUSTOMER_LEVEL" :value="scope.row.level" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="客户代码" align="center" min-width="120" prop="custCode" />
<el-table-column label="业务员" align="center" min-width="120" prop="userId" > <el-table-column label="业务员" align="center" min-width="120" prop="userId" >
<template #default="scope"> <template #default="scope">
{{ userList.find((user) => user.id === scope.row.userId)?.nickname }} {{ userList.find((user) => user.id === scope.row.userId)?.nickname }}

View File

@ -241,15 +241,23 @@ class="!w-250px" v-model="formData.fiveFuKuanTime"
<el-row> <el-row>
<el-col :span="24"> <el-col :span="12">
<el-form-item label="可引用的原有技术" prop="referenceTechnology"> <el-form-item label="可引用的原有技术" prop="referenceTechnology">
<el-input <el-input
class="!w-703px" :disabled="detailDisabled || priceDisabled || formData.deliveryStatus == 3" class="!w-250px" :disabled="detailDisabled || priceDisabled || formData.deliveryStatus == 3"
v-model="formData.referenceTechnology" placeholder="请输入可引用的原有技术" v-model="formData.referenceTechnology" placeholder="请输入可引用的原有技术"
:class="{ 'alter-class': fieldHasAlter('referenceTechnology') }" /> :class="{ 'alter-class': fieldHasAlter('referenceTechnology') }" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="辅助项" prop="auItem">
<el-input
class="!w-250px" :disabled="detailDisabled || priceDisabled || formData.deliveryStatus == 3"
v-model="formData.auItem" placeholder="请输入辅助项"/>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
@ -965,7 +973,8 @@ type="textarea" v-model="formData.activeOpinion" placeholder="请输入打回原
sixFuKuanTime: undefined, sixFuKuanTime: undefined,
sumMoney:undefined, sumMoney:undefined,
sumBl:undefined sumBl:undefined,
auItem: undefined
}) })
const formRules = reactive({ const formRules = reactive({
businessDeptId: [{ businessDeptId: [{
@ -998,6 +1007,16 @@ type="textarea" v-model="formData.activeOpinion" placeholder="请输入打回原
message: '是否有价格不能为空', message: '是否有价格不能为空',
trigger: 'blur' trigger: 'blur'
}], }],
auItem: [{
validator: (rule, value, callback) => {
if (value === null || value === undefined) {
callback(new Error('辅助项必须跟新中大一致,请确认!'))
} else {
callback()
}
},
trigger: 'blur'
}],
projectStartTime: [{ projectStartTime: [{
required: true, required: true,
message: '项目开始日期不能为空', message: '项目开始日期不能为空',

View File

@ -92,12 +92,31 @@ v-model="formData.whId" placeholder="下拉选择" clearable class="!w-400px" @c
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="4">
<el-form-item label="即入即出" prop="inOutFlag"> <el-form-item label="即入即出" prop="inOutFlag">
<el-switch v-model="formData.inOutFlag" :disabled="ctrView || ctrSave" /> <el-switch v-model="formData.inOutFlag" :disabled="ctrView || ctrSave" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="16"> <el-col :span="4">
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
placeholder="请选择供应商"
clearable
filterable
style="width: 100%"
:disabled="ctrView || ctrSave"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="15">
<el-form-item label="备注" prop="description"> <el-form-item label="备注" prop="description">
<el-input <el-input
type="textarea" v-model="formData.description" show-word-limit maxlength="200" type="textarea" v-model="formData.description" show-word-limit maxlength="200"
@ -475,11 +494,13 @@ import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as StorageApi from '@/api/heli/storage' import * as StorageApi from '@/api/heli/storage'
import * as StorageCheckApi from '@/api/heli/storagecheck' import * as StorageCheckApi from '@/api/heli/storagecheck'
import * as StorageMatApi from '@/api/heli/storagemat' import * as StorageMatApi from '@/api/heli/storagemat'
import * as SupplierApi from '@/api/heli/supplier'
import { getAccessToken, getTenantId } from '@/utils/auth' import { getAccessToken, getTenantId } from '@/utils/auth'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import * as MaterialApi from '@/api/heli/material' import * as MaterialApi from '@/api/heli/material'
import * as WarehouseApi from '@/api/heli/warehouse' import * as WarehouseApi from '@/api/heli/warehouse'
import * as PurchaseordernodetailApi from '@/api/heli/purchaseordernodetail' import * as PurchaseordernodetailApi from '@/api/heli/purchaseordernodetail'
import * as PurchaseordernoApi from '@/api/heli/purchaseorderno'
import * as RgApi from '@/api/heli/rg' import * as RgApi from '@/api/heli/rg'
import * as PnApi from '@/api/heli/pn' import * as PnApi from '@/api/heli/pn'
import { deleteFile, downloadFile, getFilePage } from '@/api/infra/file' import { deleteFile, downloadFile, getFilePage } from '@/api/infra/file'
@ -524,6 +545,7 @@ const formData = ref({
attachments: [], attachments: [],
headerId:undefined, headerId:undefined,
inOutFlag: false, inOutFlag: false,
supplierId: undefined,
}) })
const formRules = reactive({ const formRules = reactive({
// name: [{ required: true, message: '', trigger: 'blur' }], // name: [{ required: true, message: '', trigger: 'blur' }],
@ -723,17 +745,27 @@ function limitTo20Chars(input) {
} }
const handleSelectedProjectPurchaseorder = async (arr) => {
const handleSelectedProjectPurchaseorder = (arr) => {
if (arr) { if (arr) {
formData.value.headerNo = arr.purchaseNo formData.value.headerNo = arr.purchaseNo
formData.value.headerId=arr.id formData.value.headerId = arr.id
//
if (arr.id) {
try {
const purchaseOrder = await PurchaseordernoApi.getPurchaseOrderNo(arr.id)
if (purchaseOrder && purchaseOrder.supplierId) {
formData.value.supplierId = purchaseOrder.supplierId
//
const supplier = supplierList.value.find(s => s.id === purchaseOrder.supplierId)
if (supplier) {
formData.value.name = supplier.name
}
}
} catch (error) {
console.error('获取采购订单详情失败:', error)
}
}
} }
} }
const openProjectForm = (scope) => { const openProjectForm = (scope) => {
@ -1194,6 +1226,8 @@ const rgList = ref([])
const pnList = ref([]) const pnList = ref([])
// //
const noList = ref([]) const noList = ref([])
//
const supplierList = ref([])
const handleWh = async (wid) => { const handleWh = async (wid) => {
//------------------- //-------------------
// //
@ -1309,9 +1343,12 @@ onMounted(async () => {
// //
dialogTitle.value = query.type === 'review' ? '查看' : t('action.' + query.type) dialogTitle.value = query.type === 'review' ? '查看' : t('action.' + query.type)
//- //
whList.value = await WarehouseApi.getWarehouseSimpList() whList.value = await WarehouseApi.getWarehouseSimpList()
//
supplierList.value = await SupplierApi.getSimpList()
if (whList.value.length==1){ if (whList.value.length==1){
formData.value.whId = whList.value[0].id; formData.value.whId = whList.value[0].id;
const dataRgList = await RgApi.getSimpList() const dataRgList = await RgApi.getSimpList()

View File

@ -85,7 +85,15 @@
</el-select> --> </el-select> -->
<UserSelect v-model="formData.userId" @update:newValue="handleSelectedUser" class="!w-400px"/> <UserSelect v-model="formData.userId" @update:newValue="handleSelectedUser" class="!w-400px"/>
</el-form-item> </el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="税率" prop="taxRate">
<el-input v-model="formData.taxRate" placeholder="请输入税率" class="!w-400px" type="number" >
<template #append>%</template>
</el-input>
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
@ -319,6 +327,7 @@ const formData = ref({
industry: undefined, industry: undefined,
level: undefined, level: undefined,
category: undefined, category: undefined,
taxRate: undefined,
userId: undefined, userId: undefined,
description: undefined, description: undefined,
contact1Name: undefined, contact1Name: undefined,