Merge remote-tracking branch 'origin/dev' into dev

dev
wanghao 3 months ago
commit c58e0d6747

@ -77,6 +77,15 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<${ClassName}> lqw = JoinWrappers.lambda(${ClassName}.class)
.selectAll(${ClassName}.class)
#set($hasDelFlag=false)
#foreach($col in $columns)
#if($col.javaField=='delFlag')
#set($hasDelFlag=true)
#end
#end
#if($hasDelFlag)
.eq(${ClassName}::getDelFlag, "0")
#end
#foreach($column in $columns)
#if($column.query)
#set($queryType=$column.queryType)

@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.oa.base.service.ITemplateVariableAssignService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -18,7 +19,9 @@ import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.base.domain.vo.BaseTemplateVariableVo;
import org.dromara.oa.base.domain.vo.TemplateVariableAssignVo;
import org.dromara.oa.base.domain.bo.BaseTemplateVariableBo;
import org.dromara.oa.base.domain.bo.TemplateVariableAssignRequest;
import org.dromara.oa.base.service.IBaseTemplateVariableService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -36,6 +39,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
public class BaseTemplateVariableController extends BaseController {
private final IBaseTemplateVariableService baseTemplateVariableService;
private final ITemplateVariableAssignService templateVariableAssignService;
/**
*
@ -113,4 +117,17 @@ public class BaseTemplateVariableController extends BaseController {
return R.ok(list);
}
/**
*
*
* @param request ID
* @return
*/
// @SaCheckPermission("oa/base:templateVariable:assign")
@PostMapping("/assign")
public R<List<TemplateVariableAssignVo>> assignTemplateVariables(@Validated @RequestBody TemplateVariableAssignRequest request) {
List<TemplateVariableAssignVo> result = templateVariableAssignService.assignTemplateVariables(request);
return R.ok(result);
}
}

@ -0,0 +1,35 @@
package org.dromara.oa.base.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author Yinq
* @date 2025-01-XX
*/
@Data
public class TemplateVariableAssignRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* (1 2
*/
@NotNull(message = "模板类型不能为空")
private String templateType;
/**
* ID
*/
@NotNull(message = "合同ID不能为空")
private Long contractId;
}

@ -0,0 +1,40 @@
package org.dromara.oa.base.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author Yinq
* @date 2025-01-XX
*/
@Data
public class TemplateVariableAssignVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private String varName;
/**
*
*/
private String varLabel;
/**
*
*/
private Object varValue;
/**
* (1 2 3 4)
*/
private String varType;
}

@ -1,6 +1,5 @@
package org.dromara.oa.base.service;
import org.dromara.oa.base.domain.BaseTemplateVariable;
import org.dromara.oa.base.domain.vo.BaseTemplateVariableVo;
import org.dromara.oa.base.domain.bo.BaseTemplateVariableBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;

@ -0,0 +1,25 @@
package org.dromara.oa.base.service;
import org.dromara.oa.base.domain.bo.TemplateVariableAssignRequest;
import org.dromara.oa.base.domain.vo.TemplateVariableAssignVo;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-01-XX
*/
public interface ITemplateVariableAssignService {
/**
*
* 1=2=
*
* @param request ID
* @return
*/
List<TemplateVariableAssignVo> assignTemplateVariables(TemplateVariableAssignRequest request);
}

@ -2,12 +2,11 @@ package org.dromara.oa.base.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.oa.base.domain.bo.BaseTemplateVariableBo;
@ -16,9 +15,8 @@ import org.dromara.oa.base.domain.BaseTemplateVariable;
import org.dromara.oa.base.mapper.BaseTemplateVariableMapper;
import org.dromara.oa.base.service.IBaseTemplateVariableService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.List;
/**
* Service
@ -39,23 +37,23 @@ public class BaseTemplateVariableServiceImpl implements IBaseTemplateVariableSer
* @return
*/
@Override
public BaseTemplateVariableVo queryById(Long variableId){
public BaseTemplateVariableVo queryById(Long variableId) {
return baseMapper.selectVoById(variableId);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<BaseTemplateVariableVo> queryPageList(BaseTemplateVariableBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<BaseTemplateVariable> lqw = buildQueryWrapper(bo);
Page<BaseTemplateVariableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<BaseTemplateVariableVo> queryPageList(BaseTemplateVariableBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<BaseTemplateVariable> lqw = buildQueryWrapper(bo);
Page<BaseTemplateVariableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
@ -70,20 +68,18 @@ public class BaseTemplateVariableServiceImpl implements IBaseTemplateVariableSer
}
private MPJLambdaWrapper<BaseTemplateVariable> buildQueryWrapper(BaseTemplateVariableBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<BaseTemplateVariable> lqw = JoinWrappers.lambda(BaseTemplateVariable.class)
.selectAll(BaseTemplateVariable.class)
.eq(StringUtils.isNotBlank(bo.getVarLabel()), BaseTemplateVariable::getVarLabel, bo.getVarLabel())
.like(StringUtils.isNotBlank(bo.getVarName()), BaseTemplateVariable::getVarName, bo.getVarName())
.eq(StringUtils.isNotBlank(bo.getTemplateType()), BaseTemplateVariable::getTemplateType, bo.getTemplateType())
.eq(StringUtils.isNotBlank(bo.getDataSource()), BaseTemplateVariable::getDataSource, bo.getDataSource())
.eq(StringUtils.isNotBlank(bo.getDataField()), BaseTemplateVariable::getDataField, bo.getDataField())
.eq(StringUtils.isNotBlank(bo.getVarType()), BaseTemplateVariable::getVarType, bo.getVarType())
.eq(StringUtils.isNotBlank(bo.getDefaultValue()), BaseTemplateVariable::getDefaultValue, bo.getDefaultValue())
.eq(bo.getSortOrder() != null, BaseTemplateVariable::getSortOrder, bo.getSortOrder())
.eq(bo.getTemplateId() != null, BaseTemplateVariable::getTemplateId, bo.getTemplateId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), BaseTemplateVariable::getActiveFlag, bo.getActiveFlag())
;
.selectAll(BaseTemplateVariable.class)
.eq(StringUtils.isNotBlank(bo.getVarLabel()), BaseTemplateVariable::getVarLabel, bo.getVarLabel())
.like(StringUtils.isNotBlank(bo.getVarName()), BaseTemplateVariable::getVarName, bo.getVarName())
.eq(StringUtils.isNotBlank(bo.getTemplateType()), BaseTemplateVariable::getTemplateType, bo.getTemplateType())
.eq(StringUtils.isNotBlank(bo.getDataSource()), BaseTemplateVariable::getDataSource, bo.getDataSource())
.eq(StringUtils.isNotBlank(bo.getDataField()), BaseTemplateVariable::getDataField, bo.getDataField())
.eq(StringUtils.isNotBlank(bo.getVarType()), BaseTemplateVariable::getVarType, bo.getVarType())
.eq(StringUtils.isNotBlank(bo.getDefaultValue()), BaseTemplateVariable::getDefaultValue, bo.getDefaultValue())
.eq(bo.getSortOrder() != null, BaseTemplateVariable::getSortOrder, bo.getSortOrder())
.eq(bo.getTemplateId() != null, BaseTemplateVariable::getTemplateId, bo.getTemplateId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), BaseTemplateVariable::getActiveFlag, bo.getActiveFlag());
return lqw;
}
@ -120,7 +116,7 @@ public class BaseTemplateVariableServiceImpl implements IBaseTemplateVariableSer
/**
*
*/
private void validEntityBeforeSave(BaseTemplateVariable entity){
private void validEntityBeforeSave(BaseTemplateVariable entity) {
//TODO 做一些数据校验,如唯一约束
}
@ -133,7 +129,7 @@ public class BaseTemplateVariableServiceImpl implements IBaseTemplateVariableSer
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;

@ -0,0 +1,403 @@
package org.dromara.oa.base.service.impl;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.oa.base.domain.bo.BaseTemplateVariableBo;
import org.dromara.oa.base.domain.bo.TemplateVariableAssignRequest;
import org.dromara.oa.base.domain.vo.BaseTemplateVariableVo;
import org.dromara.oa.base.domain.vo.TemplateVariableAssignVo;
import org.dromara.oa.base.service.IBaseTemplateVariableService;
import org.dromara.oa.base.service.ITemplateVariableAssignService;
import org.dromara.oa.erp.domain.bo.ErpContractInfoBo;
import org.dromara.oa.erp.domain.bo.ErpContractMaterialBo;
import org.dromara.oa.erp.domain.vo.ErpContractInfoVo;
import org.dromara.oa.erp.domain.vo.ErpContractMaterialVo;
import org.dromara.oa.erp.service.IErpContractInfoService;
import org.dromara.oa.erp.service.IErpContractMaterialService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Service
*
* @author Yinq
* @date 2025-01-XX
*/
@RequiredArgsConstructor
@Service
public class TemplateVariableAssignServiceImpl implements ITemplateVariableAssignService {
private final IBaseTemplateVariableService baseTemplateVariableService;
private final IErpContractInfoService erpContractInfoService;
private final IErpContractMaterialService erpContractMaterialService;
/**
*
* 1=2=
*
* @param request ID
* @return
*/
@Override
public List<TemplateVariableAssignVo> assignTemplateVariables(TemplateVariableAssignRequest request) {
// 根据模板类型选择不同的处理逻辑
String templateType = request.getTemplateType();
if ("1".equals(templateType)) {
// 合同类型
return assignContractTemplateVariables(request);
} else if ("2".equals(templateType)) {
// 发货单类型
return assignDeliveryTemplateVariables(request);
} else {
throw new ServiceException("不支持的模板类型:" + templateType);
}
}
/**
*
*
* @param request
* @return
*/
private List<TemplateVariableAssignVo> assignContractTemplateVariables(TemplateVariableAssignRequest request) {
// 1. 根据模板类型查询所有模板变量配置
BaseTemplateVariableBo queryBo = new BaseTemplateVariableBo();
queryBo.setTemplateType(request.getTemplateType());
List<BaseTemplateVariableVo> allTemplateVariables = baseTemplateVariableService.queryList(queryBo);
// 构建变量名到配置的映射
Map<String, BaseTemplateVariableVo> variableMap = buildVariableMap(allTemplateVariables);
// 2. 查询合同信息
ErpContractInfoBo bo = new ErpContractInfoBo();
bo.setContractId(request.getContractId());
List<ErpContractInfoVo> contractInfoVoList = erpContractInfoService.queryList(bo);
if (contractInfoVoList.isEmpty()) {
throw new ServiceException("合同信息不存在合同ID" + request.getContractId());
}
ErpContractInfoVo contractInfo = contractInfoVoList.get(0);
// 3. 查询合同物料列表(如果存在需要物料数据的变量)
List<ErpContractMaterialVo> contractMaterials = null;
boolean needMaterialData = allTemplateVariables.stream()
.anyMatch(var -> "erp_contract_material".equalsIgnoreCase(var.getDataSource()));
if (needMaterialData) {
ErpContractMaterialBo materialBo = new ErpContractMaterialBo();
materialBo.setContractId(request.getContractId());
contractMaterials = erpContractMaterialService.queryList(materialBo);
for (int i = 0; i < contractMaterials.size(); i++) {
contractMaterials.get(i).setSeq(i + 1L);
}
}
// 4. 为所有模板变量赋值
return buildAssignResultList(allTemplateVariables, variableMap, contractInfo, contractMaterials);
}
/**
*
*
* @param request
* @return
*/
private List<TemplateVariableAssignVo> assignDeliveryTemplateVariables(TemplateVariableAssignRequest request) {
// TODO: 实现发货单模板变量赋值逻辑
throw new ServiceException("发货单模板变量赋值功能暂未实现");
}
/**
*
*
* @param allTemplateVariables
* @param variableMap
* @param contractInfo
* @param contractMaterials
* @return
*/
private List<TemplateVariableAssignVo> buildAssignResultList(
List<BaseTemplateVariableVo> allTemplateVariables,
Map<String, BaseTemplateVariableVo> variableMap,
ErpContractInfoVo contractInfo,
List<ErpContractMaterialVo> contractMaterials) {
List<TemplateVariableAssignVo> resultList = new ArrayList<>();
for (BaseTemplateVariableVo variable : allTemplateVariables) {
if (variable == null || StringUtils.isBlank(variable.getVarName())) {
continue;
}
// 根据 dataSource 决定数据源
Object value = getValueFromDataSource(variable, contractInfo, contractMaterials);
// 如果获取不到值,使用默认值
if (value == null && StringUtils.isNotBlank(variable.getDefaultValue())) {
value = variable.getDefaultValue();
}
// 根据变量类型决定返回类型4表示数组类型
boolean shouldReturnArray = "4".equals(variable.getVarType());
Object finalValue = convertValueToTargetType(value, shouldReturnArray);
// 构建返回对象
TemplateVariableAssignVo assignVo = new TemplateVariableAssignVo();
assignVo.setVarName(variable.getVarName());
assignVo.setVarLabel(variable.getVarLabel());
assignVo.setVarValue(finalValue);
assignVo.setVarType(variable.getVarType());
resultList.add(assignVo);
}
return resultList;
}
/**
*
* #{}
* ^{}
*
* @param varNameWithFormat #{} ^{}
* @return
*/
private VariableNameInfo parseVariableName(String varNameWithFormat) {
if (StringUtils.isBlank(varNameWithFormat)) {
return new VariableNameInfo(varNameWithFormat, false);
}
// 检查是否是 #{变量名} 格式(字符串)
if (varNameWithFormat.startsWith("#{") && varNameWithFormat.endsWith("}")) {
String actualName = varNameWithFormat.substring(2, varNameWithFormat.length() - 1);
return new VariableNameInfo(actualName, false);
}
// 检查是否是 ^{变量名} 格式(数组)
if (varNameWithFormat.startsWith("^{") && varNameWithFormat.endsWith("}")) {
String actualName = varNameWithFormat.substring(2, varNameWithFormat.length() - 1);
return new VariableNameInfo(actualName, true);
}
// 默认格式,返回原值
return new VariableNameInfo(varNameWithFormat, false);
}
/**
*
*/
private static class VariableNameInfo {
private final String actualName;
private final boolean arrayType;
public VariableNameInfo(String actualName, boolean arrayType) {
this.actualName = actualName;
this.arrayType = arrayType;
}
public String getActualName() {
return actualName;
}
public boolean isArrayType() {
return arrayType;
}
}
/**
*
* #{}^{}
*
* @param templateVariables
* @return
*/
private Map<String, BaseTemplateVariableVo> buildVariableMap(
List<BaseTemplateVariableVo> templateVariables) {
Map<String, BaseTemplateVariableVo> variableMap = new HashMap<>();
for (BaseTemplateVariableVo variable : templateVariables) {
String varName = variable.getVarName();
if (StringUtils.isBlank(varName)) {
continue;
}
// 提取变量名(去除占位符)
String normalizedName = normalizeVariableName(varName);
// 添加到映射中使用规范化后的变量名作为key
variableMap.put(normalizedName, variable);
}
return variableMap;
}
/**
*
*
* @param varName #{^{}
* @return
*/
private String normalizeVariableName(String varName) {
if (StringUtils.isBlank(varName)) {
return varName;
}
// 去除 #{变量名} 或 ^{变量名} 格式
if ((varName.startsWith("#{") || varName.startsWith("^{")) && varName.endsWith("}")) {
return varName.substring(2, varName.length() - 1);
}
return varName;
}
/**
*
*
* @param variable
* @param contractInfo
* @param contractMaterials null
* @return
*/
private Object getValueFromDataSource(BaseTemplateVariableVo variable,
ErpContractInfoVo contractInfo,
List<ErpContractMaterialVo> contractMaterials) {
if (StringUtils.isBlank(variable.getDataField())) {
return null;
}
String dataSource = variable.getDataSource();
// 根据数据源类型获取值
if ("erp_contract_material".equalsIgnoreCase(dataSource)) {
// 从合同物料列表中提取字段值
return getFieldValueFromMaterialList(contractMaterials, variable.getDataField());
} else {
// 默认从合同信息中获取
return getFieldValueFromContract(contractInfo, variable.getDataField());
}
}
/**
*
*
* @param contractMaterials
* @param fieldName
* @return
*/
private List<Object> getFieldValueFromMaterialList(List<ErpContractMaterialVo> contractMaterials, String fieldName) {
if (contractMaterials == null || contractMaterials.isEmpty() || StringUtils.isBlank(fieldName)) {
return new ArrayList<>();
}
List<Object> values = new ArrayList<>();
for (ErpContractMaterialVo material : contractMaterials) {
Object value = getFieldValueFromObject(material, fieldName);
// 如果值为null用空字符串代替
values.add(value != null ? value : "");
}
return values;
}
/**
* 使
*
* @param obj
* @param fieldName
* @return
*/
private Object getFieldValueFromObject(Object obj, String fieldName) {
if (obj == null || StringUtils.isBlank(fieldName)) {
return null;
}
try {
// 先尝试使用反射获取字段值
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException e) {
// 如果字段不存在,尝试使用 getter 方法
try {
String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
return obj.getClass().getMethod(methodName).invoke(obj);
} catch (Exception ex) {
// 如果都获取不到,返回 null
return null;
}
} catch (Exception e) {
return null;
}
}
/**
* 使
*
* @param contractInfo
* @param fieldName
* @return
*/
private Object getFieldValueFromContract(ErpContractInfoVo contractInfo, String fieldName) {
return getFieldValueFromObject(contractInfo, fieldName);
}
/**
*
*
* @param value
* @param shouldReturnArray
* @return
*/
private Object convertValueToTargetType(Object value, boolean shouldReturnArray) {
if (shouldReturnArray) {
// 转换为数组类型
if (value instanceof List) {
return value;
} else if (value instanceof Collection) {
return new ArrayList<>((Collection<?>) value);
} else if (value != null) {
// 单个值,转换为列表
List<Object> arrayValue = new ArrayList<>();
arrayValue.add(value);
return arrayValue;
} else {
return new ArrayList<>();
}
} else {
// 转换为字符串类型
if (value instanceof List) {
List<?> list = (List<?>) value;
if (!list.isEmpty()) {
return list.get(0).toString();
} else {
return "";
}
} else if (value instanceof Collection) {
Collection<?> collection = (Collection<?>) value;
if (!collection.isEmpty()) {
return collection.iterator().next().toString();
} else {
return "";
}
} else if (value != null) {
return value.toString();
} else {
return "";
}
}
}
/**
*
*
* @param isArrayType
* @return
*/
private Object getDefaultValueByType(boolean isArrayType) {
return isArrayType ? new ArrayList<>() : "";
}
}

@ -0,0 +1,116 @@
package org.dromara.oa.crm.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.crm.domain.vo.CrmSupplierInfoVo;
import org.dromara.oa.crm.domain.bo.CrmSupplierInfoBo;
import org.dromara.oa.crm.service.ICrmSupplierInfoService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/oa/crm/crmSupplierInfo
*
* @author Yinq
* @date 2025-11-05
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/crm/crmSupplierInfo")
public class CrmSupplierInfoController extends BaseController {
private final ICrmSupplierInfoService crmSupplierInfoService;
/**
*
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:list")
@GetMapping("/list")
public TableDataInfo<CrmSupplierInfoVo> list(CrmSupplierInfoBo bo, PageQuery pageQuery) {
return crmSupplierInfoService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:export")
@Log(title = "供应商信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(CrmSupplierInfoBo bo, HttpServletResponse response) {
List<CrmSupplierInfoVo> list = crmSupplierInfoService.queryList(bo);
ExcelUtil.exportExcel(list, "供应商信息", CrmSupplierInfoVo.class, response);
}
/**
*
*
* @param supplierId
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:query")
@GetMapping("/{supplierId}")
public R<CrmSupplierInfoVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("supplierId") Long supplierId) {
return R.ok(crmSupplierInfoService.queryById(supplierId));
}
/**
*
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:add")
@Log(title = "供应商信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmSupplierInfoBo bo) {
return toAjax(crmSupplierInfoService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:edit")
@Log(title = "供应商信息", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmSupplierInfoBo bo) {
return toAjax(crmSupplierInfoService.updateByBo(bo));
}
/**
*
*
* @param supplierIds
*/
@SaCheckPermission("oa/crm:crmSupplierInfo:remove")
@Log(title = "供应商信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{supplierIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable("supplierIds") Long[] supplierIds) {
return toAjax(crmSupplierInfoService.deleteWithValidByIds(List.of(supplierIds), true));
}
/**
*
*/
@GetMapping("/getCrmSupplierInfoList")
public R<List<CrmSupplierInfoVo>> getCrmSupplierInfoList(CrmSupplierInfoBo bo) {
List<CrmSupplierInfoVo> list = crmSupplierInfoService.queryList(bo);
return R.ok(list);
}
}

@ -0,0 +1,178 @@
package org.dromara.oa.crm.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* crm_supplier_info
*
* @author Yinq
* @date 2025-11-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("crm_supplier_info")
public class CrmSupplierInfo extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "supplier_id", type = IdType.AUTO)
private Long supplierId;
/**
*
*/
private String supplierName;
/**
*
*/
private String mnemonicName;
/**
* 1 2 3
*/
private String supplierType;
/**
*
*/
private BigDecimal registeredCapital;
/**
*
*/
private Date establishmentDate;
/**
*
*/
private String businessScope;
/**
*
*/
private String mainIndustry;
/**
*
*/
private String legalRepresentative;
/**
*
*/
private String businessLicenseNumber;
/**
*
*/
private String taxNumber;
/**
*
*/
private String bankAccountOpening;
/**
*
*/
private String bankNumber;
/**
*
*/
private String registeredAddress;
/**
*
*/
private String businessAddress;
/**
*
*/
private String contactPerson;
/**
*
*/
private String contactPhone;
/**
*
*/
private String contactMobile;
/**
*
*/
private String contactEmail;
/**
*
*/
private String contactFax;
/**
*
*/
private String website;
/**
* ID
*/
private Long ownerId;
/**
*
*/
private String detailedAddress;
/**
* ID
*/
private String ossId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
* 0 1
*/
@TableLogic
private String delFlag;
/**
*
*/
@TableField(exist = false)
private String ownerName;
/**
*
*/
@TableField(exist = false)
private String ownerDeptName;
}

@ -0,0 +1,158 @@
package org.dromara.oa.crm.domain.bo;
import org.dromara.oa.crm.domain.CrmSupplierInfo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* crm_supplier_info
*
* @author Yinq
* @date 2025-11-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = CrmSupplierInfo.class, reverseConvertGenerate = false)
public class CrmSupplierInfoBo extends BaseEntity {
/**
* ID
*/
@NotNull(message = "供应商ID不能为空", groups = { EditGroup.class })
private Long supplierId;
/**
*
*/
private String supplierName;
/**
*
*/
private String mnemonicName;
/**
* 1 2 3
*/
private String supplierType;
/**
*
*/
private BigDecimal registeredCapital;
/**
*
*/
private Date establishmentDate;
/**
*
*/
private String businessScope;
/**
*
*/
private String mainIndustry;
/**
*
*/
private String legalRepresentative;
/**
*
*/
private String businessLicenseNumber;
/**
*
*/
private String taxNumber;
/**
*
*/
private String bankAccountOpening;
/**
*
*/
private String bankNumber;
/**
*
*/
private String registeredAddress;
/**
*
*/
private String businessAddress;
/**
*
*/
private String contactPerson;
/**
*
*/
private String contactPhone;
/**
*
*/
private String contactMobile;
/**
*
*/
private String contactEmail;
/**
*
*/
private String contactFax;
/**
*
*/
private String website;
/**
* ID
*/
private Long ownerId;
/**
*
*/
private String detailedAddress;
/**
* ID
*/
private String ossId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
}

@ -0,0 +1,209 @@
package org.dromara.oa.crm.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.oa.crm.domain.CrmSupplierInfo;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.resource.api.domain.RemoteFile;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* crm_supplier_info
*
* @author Yinq
* @date 2025-11-05
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = CrmSupplierInfo.class)
public class CrmSupplierInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "供应商ID")
private Long supplierId;
/**
*
*/
@ExcelProperty(value = "供应商名称")
private String supplierName;
/**
*
*/
@ExcelProperty(value = "助记名称")
private String mnemonicName;
/**
* 1 2 3
*/
@ExcelProperty(value = "供应商类型", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "supplier_type")
private String supplierType;
/**
*
*/
@ExcelProperty(value = "注册资本", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "万=元")
private BigDecimal registeredCapital;
/**
*
*/
@ExcelProperty(value = "成立日期")
private Date establishmentDate;
/**
*
*/
@ExcelProperty(value = "经营范围")
private String businessScope;
/**
*
*/
@ExcelProperty(value = "主营行业")
private String mainIndustry;
/**
*
*/
@ExcelProperty(value = "法定代表人")
private String legalRepresentative;
/**
*
*/
@ExcelProperty(value = "营业执照号码")
private String businessLicenseNumber;
/**
*
*/
@ExcelProperty(value = "税号")
private String taxNumber;
/**
*
*/
@ExcelProperty(value = "开户银行")
private String bankAccountOpening;
/**
*
*/
@ExcelProperty(value = "银行账号")
private String bankNumber;
/**
*
*/
@ExcelProperty(value = "注册地址")
private String registeredAddress;
/**
*
*/
@ExcelProperty(value = "经营地址")
private String businessAddress;
/**
*
*/
@ExcelProperty(value = "联系人")
private String contactPerson;
/**
*
*/
@ExcelProperty(value = "联系电话")
private String contactPhone;
/**
*
*/
@ExcelProperty(value = "联系手机")
private String contactMobile;
/**
*
*/
@ExcelProperty(value = "联系邮箱")
private String contactEmail;
/**
*
*/
@ExcelProperty(value = "传真")
private String contactFax;
/**
*
*/
@ExcelProperty(value = "网址")
private String website;
/**
* ID
*/
@ExcelProperty(value = "归属人员ID")
private Long ownerId;
/**
*
*/
@ExcelProperty(value = "详细地址")
private String detailedAddress;
/**
* ID
*/
@ExcelProperty(value = "附件ID")
private String ossId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "active_flag")
private String activeFlag;
/**
* sys_user
*/
@ExcelProperty(value = "归属人员名称")
private String ownerName;
/**
*
*/
@ExcelIgnore
private List<RemoteFile> attachmentList;
}

@ -0,0 +1,113 @@
package org.dromara.oa.crm.mapper;
import java.util.List;
import java.util.Collection;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.oa.crm.domain.CrmSupplierInfo;
import org.dromara.oa.crm.domain.vo.CrmSupplierInfoVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author Yinq
* @date 2025-11-05
*/
public interface CrmSupplierInfoMapper extends BaseMapperPlus<CrmSupplierInfo, CrmSupplierInfoVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
public Page<CrmSupplierInfoVo> selectCustomCrmSupplierInfoVoList(@Param("page") Page<CrmSupplierInfoVo> page, @Param(Constants.WRAPPER) MPJLambdaWrapper<CrmSupplierInfo> queryWrapper);
/**
*
*
* @param queryWrapper
* @return
*/
public List<CrmSupplierInfoVo> selectCustomCrmSupplierInfoVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<CrmSupplierInfo> queryWrapper);
/**
* ID
*
* @param supplierId ID
* @return
*/
CrmSupplierInfoVo selectCustomCrmSupplierInfoVoById(@Param("supplierId") Long supplierId);
/**
* ID
*
* @param ids ID
* @return
*/
List<CrmSupplierInfoVo> selectCustomCrmSupplierInfoVoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Long countCustomCrmSupplierInfo(@Param(Constants.WRAPPER) Wrapper<CrmSupplierInfo> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<CrmSupplierInfoVo> selectCustomCrmSupplierInfoVoPage(@Param("page") Page<CrmSupplierInfoVo> page, @Param(Constants.WRAPPER) Wrapper<CrmSupplierInfo> queryWrapper);
/**
*
*
* @param list
* @return
*/
int batchInsertCrmSupplierInfo(@Param("list") List<CrmSupplierInfo> list);
/**
*
*
* @param list
* @return
*/
int batchUpdateCrmSupplierInfo(@Param("list") List<CrmSupplierInfo> list);
/**
*
*
* @param queryWrapper
* @return
*/
int deleteCustomCrmSupplierInfo(@Param(Constants.WRAPPER) Wrapper<CrmSupplierInfo> queryWrapper);
/**
* ID
*
* @param ids ID
* @return
*/
int deleteCustomCrmSupplierInfoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Boolean existsCrmSupplierInfo(@Param(Constants.WRAPPER) Wrapper<CrmSupplierInfo> queryWrapper);
}

@ -0,0 +1,69 @@
package org.dromara.oa.crm.service;
import org.dromara.oa.crm.domain.CrmSupplierInfo;
import org.dromara.oa.crm.domain.vo.CrmSupplierInfoVo;
import org.dromara.oa.crm.domain.bo.CrmSupplierInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-11-05
*/
public interface ICrmSupplierInfoService {
/**
*
*
* @param supplierId
* @return
*/
CrmSupplierInfoVo queryById(Long supplierId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<CrmSupplierInfoVo> queryPageList(CrmSupplierInfoBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<CrmSupplierInfoVo> queryList(CrmSupplierInfoBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(CrmSupplierInfoBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(CrmSupplierInfoBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

@ -75,7 +75,7 @@ public class CrmCustomerContactServiceImpl implements ICrmCustomerContactService
MPJLambdaWrapper<CrmCustomerContact> lqw = JoinWrappers.lambda(CrmCustomerContact.class)
.selectAll(CrmCustomerContact.class)
.select(CrmCustomerInfo::getCustomerName)
.leftJoin(CrmCustomerInfo.class, CrmCustomerInfo::getCustomerId, CrmCustomerContact::getContactId)
.leftJoin(CrmCustomerInfo.class, CrmCustomerInfo::getCustomerId, CrmCustomerContact::getCustomerId)
.eq(bo.getCustomerId() != null, CrmCustomerContact::getCustomerId, bo.getCustomerId())
.like(StringUtils.isNotBlank(bo.getContactName()), CrmCustomerContact::getContactName, bo.getContactName())
.eq(StringUtils.isNotBlank(bo.getSexType()), CrmCustomerContact::getSexType, bo.getSexType())

@ -0,0 +1,217 @@
package org.dromara.oa.crm.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.dromara.oa.crm.domain.bo.CrmSupplierInfoBo;
import org.dromara.oa.crm.domain.vo.CrmSupplierInfoVo;
import org.dromara.oa.crm.domain.CrmSupplierInfo;
import org.dromara.oa.crm.mapper.CrmSupplierInfoMapper;
import org.dromara.oa.crm.service.ICrmSupplierInfoService;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.domain.RemoteFile;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.stream.Collectors;
/**
* Service
*
* @author Yinq
* @date 2025-11-05
*/
@RequiredArgsConstructor
@Service
public class CrmSupplierInfoServiceImpl implements ICrmSupplierInfoService {
private final CrmSupplierInfoMapper baseMapper;
@DubboReference(mock = "true")
private RemoteFileService remoteFileService;
/**
*
*
* @param supplierId
* @return
*/
@Override
public CrmSupplierInfoVo queryById(Long supplierId){
CrmSupplierInfoVo vo = baseMapper.selectVoById(supplierId);
fillAttachmentInfo(Collections.singletonList(vo));
return vo;
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<CrmSupplierInfoVo> queryPageList(CrmSupplierInfoBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<CrmSupplierInfo> lqw = buildQueryWrapper(bo);
Page<CrmSupplierInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillAttachmentInfo(result.getRecords());
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<CrmSupplierInfoVo> queryList(CrmSupplierInfoBo bo) {
MPJLambdaWrapper<CrmSupplierInfo> lqw = buildQueryWrapper(bo);
List<CrmSupplierInfoVo> list = baseMapper.selectVoList(lqw);
fillAttachmentInfo(list);
return list;
}
private MPJLambdaWrapper<CrmSupplierInfo> buildQueryWrapper(CrmSupplierInfoBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<CrmSupplierInfo> lqw = JoinWrappers.lambda(CrmSupplierInfo.class)
.selectAll(CrmSupplierInfo.class)
// // 左连接 sys_user 表获取归属人员名称
// .selectAs(SysUser::getNickName, CrmSupplierInfo::getOwnerName)
// .leftJoin(SysUser.class, SysUser::getUserId, CrmSupplierInfo::getOwnerId)
.eq(CrmSupplierInfo::getDelFlag, "0")
.like(StringUtils.isNotBlank(bo.getSupplierName()), CrmSupplierInfo::getSupplierName, bo.getSupplierName())
.like(StringUtils.isNotBlank(bo.getMnemonicName()), CrmSupplierInfo::getMnemonicName, bo.getMnemonicName())
.eq(StringUtils.isNotBlank(bo.getSupplierType()), CrmSupplierInfo::getSupplierType, bo.getSupplierType())
.eq(bo.getRegisteredCapital() != null, CrmSupplierInfo::getRegisteredCapital, bo.getRegisteredCapital())
.eq(bo.getEstablishmentDate() != null, CrmSupplierInfo::getEstablishmentDate, bo.getEstablishmentDate())
.eq(StringUtils.isNotBlank(bo.getBusinessScope()), CrmSupplierInfo::getBusinessScope, bo.getBusinessScope())
.eq(StringUtils.isNotBlank(bo.getMainIndustry()), CrmSupplierInfo::getMainIndustry, bo.getMainIndustry())
.eq(StringUtils.isNotBlank(bo.getLegalRepresentative()), CrmSupplierInfo::getLegalRepresentative, bo.getLegalRepresentative())
.eq(StringUtils.isNotBlank(bo.getBusinessLicenseNumber()), CrmSupplierInfo::getBusinessLicenseNumber, bo.getBusinessLicenseNumber())
.eq(StringUtils.isNotBlank(bo.getTaxNumber()), CrmSupplierInfo::getTaxNumber, bo.getTaxNumber())
.eq(StringUtils.isNotBlank(bo.getBankAccountOpening()), CrmSupplierInfo::getBankAccountOpening, bo.getBankAccountOpening())
.eq(StringUtils.isNotBlank(bo.getBankNumber()), CrmSupplierInfo::getBankNumber, bo.getBankNumber())
.eq(StringUtils.isNotBlank(bo.getRegisteredAddress()), CrmSupplierInfo::getRegisteredAddress, bo.getRegisteredAddress())
.eq(StringUtils.isNotBlank(bo.getBusinessAddress()), CrmSupplierInfo::getBusinessAddress, bo.getBusinessAddress())
.eq(StringUtils.isNotBlank(bo.getContactPerson()), CrmSupplierInfo::getContactPerson, bo.getContactPerson())
.eq(StringUtils.isNotBlank(bo.getContactPhone()), CrmSupplierInfo::getContactPhone, bo.getContactPhone())
.eq(StringUtils.isNotBlank(bo.getContactMobile()), CrmSupplierInfo::getContactMobile, bo.getContactMobile())
.eq(StringUtils.isNotBlank(bo.getContactEmail()), CrmSupplierInfo::getContactEmail, bo.getContactEmail())
.eq(StringUtils.isNotBlank(bo.getContactFax()), CrmSupplierInfo::getContactFax, bo.getContactFax())
.eq(StringUtils.isNotBlank(bo.getWebsite()), CrmSupplierInfo::getWebsite, bo.getWebsite())
.eq(bo.getOwnerId() != null, CrmSupplierInfo::getOwnerId, bo.getOwnerId())
.eq(StringUtils.isNotBlank(bo.getDetailedAddress()), CrmSupplierInfo::getDetailedAddress, bo.getDetailedAddress())
.eq(StringUtils.isNotBlank(bo.getOssId()), CrmSupplierInfo::getOssId, bo.getOssId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), CrmSupplierInfo::getActiveFlag, bo.getActiveFlag());
return lqw;
}
private void fillAttachmentInfo(List<CrmSupplierInfoVo> voList) {
if (voList == null || voList.isEmpty()) {
return;
}
Set<String> ossIdSet = new LinkedHashSet<>();
Map<CrmSupplierInfoVo, List<String>> voOssMapping = new HashMap<>();
for (CrmSupplierInfoVo vo : voList) {
if (vo == null || StringUtils.isBlank(vo.getOssId())) {
continue;
}
List<String> ids = List.of(StringUtils.split(vo.getOssId(), ","));
if (ids.isEmpty()) {
continue;
}
voOssMapping.put(vo, ids);
ossIdSet.addAll(ids);
}
if (ossIdSet.isEmpty()) {
return;
}
try {
List<RemoteFile> files = remoteFileService.selectByIds(String.join(",", ossIdSet));
Map<Long, RemoteFile> fileMap = files.stream()
.filter(item -> item.getOssId() != null)
.collect(Collectors.toMap(RemoteFile::getOssId, item -> item, (a, b) -> a));
for (Entry<CrmSupplierInfoVo, List<String>> entry : voOssMapping.entrySet()) {
List<RemoteFile> voFiles = entry.getValue().stream()
.map(id -> {
if (!StringUtils.isNumeric(id)) {
return null;
}
Long key = Long.parseLong(id);
return fileMap.get(key);
})
.filter(item -> item != null)
.collect(Collectors.toList());
entry.getKey().setAttachmentList(voFiles);
}
} catch (Exception ignored) {
// 远程文件服务异常时忽略附件
}
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean insertByBo(CrmSupplierInfoBo bo) {
CrmSupplierInfo add = MapstructUtils.convert(bo, CrmSupplierInfo.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setSupplierId(add.getSupplierId());
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean updateByBo(CrmSupplierInfoBo bo) {
CrmSupplierInfo update = MapstructUtils.convert(bo, CrmSupplierInfo.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(CrmSupplierInfo entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

@ -80,6 +80,19 @@ public class ErpProjectInfoController extends BaseController {
return toAjax(erpProjectInfoService.insertByBo(bo));
}
/**
*
* @param bo
* @return
*/
@SaCheckPermission("oa/erp:projectInfo:add")
@Log(title = "项目信息", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/submitAndFlowStart")
public R<ErpProjectInfoVo> submitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectInfoBo bo) {
return R.ok(erpProjectInfoService.projectSubmitAndFlowStart(bo));
}
/**
*
*/

@ -0,0 +1,130 @@
package org.dromara.oa.erp.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanBo;
import org.dromara.oa.erp.service.IErpProjectPlanService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/oa/erp/erpProjectPlan
*
* @author Yinq
* @date 2025-10-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/erp/erpProjectPlan")
public class ErpProjectPlanController extends BaseController {
private final IErpProjectPlanService erpProjectPlanService;
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:list")
@GetMapping("/list")
public TableDataInfo<ErpProjectPlanVo> list(ErpProjectPlanBo bo, PageQuery pageQuery) {
return erpProjectPlanService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:export")
@Log(title = "项目计划", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ErpProjectPlanBo bo, HttpServletResponse response) {
List<ErpProjectPlanVo> list = erpProjectPlanService.queryList(bo);
ExcelUtil.exportExcel(list, "项目计划", ErpProjectPlanVo.class, response);
}
/**
*
*
* @param projectPlanId
*/
@SaCheckPermission("oa/erp:erpProjectPlan:query")
@GetMapping("/{projectPlanId}")
public R<ErpProjectPlanVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("projectPlanId") Long projectPlanId) {
return R.ok(erpProjectPlanService.queryById(projectPlanId));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:add")
@Log(title = "项目计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<ErpProjectPlanVo> add(@Validated(AddGroup.class) @RequestBody ErpProjectPlanBo bo) {
erpProjectPlanService.insertByBo(bo);
return R.ok(erpProjectPlanService.queryById(bo.getProjectPlanId()));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlan:edit")
@Log(title = "项目计划", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ErpProjectPlanBo bo) {
return toAjax(erpProjectPlanService.updateByBo(bo));
}
/**
*
*
* @param projectPlanIds
*/
@SaCheckPermission("oa/erp:erpProjectPlan:remove")
@Log(title = "项目计划", businessType = BusinessType.DELETE)
@DeleteMapping("/{projectPlanIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable("projectPlanIds") Long[] projectPlanIds) {
return toAjax(erpProjectPlanService.deleteWithValidByIds(List.of(projectPlanIds), true));
}
/**
*
*/
@GetMapping("/getErpProjectPlanList")
public R<List<ErpProjectPlanVo>> getErpProjectPlanList(ErpProjectPlanBo bo) {
List<ErpProjectPlanVo> list = erpProjectPlanService.queryList(bo);
return R.ok(list);
}
/**
*
* @param bo
* @return
*/
@SaCheckPermission("oa/erp:erpProjectPlan:add")
@Log(title = "项目计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/projectPlanSubmitAndFlowStart")
public R<ErpProjectPlanVo> projectPlanSubmitAndFlowStart(@Validated(AddGroup.class) @RequestBody ErpProjectPlanBo bo) {
return R.ok(erpProjectPlanService.projectPlanSubmitAndFlowStart(bo));
}
}

@ -0,0 +1,116 @@
package org.dromara.oa.erp.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.oa.erp.service.IErpProjectPlanStageService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/oa/erp/erpProjectPlanStage
*
* @author Yinq
* @date 2025-10-30
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/erp/erpProjectPlanStage")
public class ErpProjectPlanStageController extends BaseController {
private final IErpProjectPlanStageService erpProjectPlanStageService;
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:list")
@GetMapping("/list")
public TableDataInfo<ErpProjectPlanStageVo> list(ErpProjectPlanStageBo bo, PageQuery pageQuery) {
return erpProjectPlanStageService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:export")
@Log(title = "项目计划阶段", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ErpProjectPlanStageBo bo, HttpServletResponse response) {
List<ErpProjectPlanStageVo> list = erpProjectPlanStageService.queryList(bo);
ExcelUtil.exportExcel(list, "项目计划阶段", ErpProjectPlanStageVo.class, response);
}
/**
*
*
* @param planStageId
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:query")
@GetMapping("/{planStageId}")
public R<ErpProjectPlanStageVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("planStageId") Long planStageId) {
return R.ok(erpProjectPlanStageService.queryById(planStageId));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:add")
@Log(title = "项目计划阶段", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ErpProjectPlanStageBo bo) {
return toAjax(erpProjectPlanStageService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:edit")
@Log(title = "项目计划阶段", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ErpProjectPlanStageBo bo) {
return toAjax(erpProjectPlanStageService.updateByBo(bo));
}
/**
*
*
* @param planStageIds
*/
@SaCheckPermission("oa/erp:erpProjectPlanStage:remove")
@Log(title = "项目计划阶段", businessType = BusinessType.DELETE)
@DeleteMapping("/{planStageIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable("planStageIds") Long[] planStageIds) {
return toAjax(erpProjectPlanStageService.deleteWithValidByIds(List.of(planStageIds), true));
}
/**
*
*/
@GetMapping("/getErpProjectPlanStageList")
public R<List<ErpProjectPlanStageVo>> getErpProjectPlanStageList(ErpProjectPlanStageBo bo) {
List<ErpProjectPlanStageVo> list = erpProjectPlanStageService.queryList(bo);
return R.ok(list);
}
}

@ -0,0 +1,87 @@
package org.dromara.oa.erp.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("erp_project_plan")
public class ErpProjectPlan extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "project_plan_id", type = IdType.ASSIGN_ID)
private Long projectPlanId;
/**
* ID
*/
private Long projectId;
/**
*
*/
private Long managerId;
/**
*
*/
private Long chargeId;
/**
*
*/
private String paymentMethod;
/**
* (1 2 3)
*/
private String projectPlanStatus;
/**
*
*/
private String flowStatus;
/**
*
*/
private Long sortOrder;
/**
* ID()
*/
private Long contractId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
* 0 1
*/
@TableLogic
private String delFlag;
}

@ -0,0 +1,129 @@
package org.dromara.oa.erp.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("erp_project_plan_stage")
public class ErpProjectPlanStage extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "plan_stage_id", type = IdType.AUTO)
private Long planStageId;
/**
* ID
*/
private Long projectId;
/**
* ID
*/
private Long projectPlanId;
/**
*
*/
private String projectPhases;
/**
*
*/
private Date planStartTime;
/**
*
*/
private Date planEndTime;
/**
*
*/
private String collectionStage;
/**
* (%)
*/
private Long repaymentRate;
/**
*
*/
private Long repaymentAmount;
/**
*
*/
private Date repaymentTime;
/**
*
*/
private Long delayDay;
/**
*
*/
private Date receivableDate;
/**
*
*/
private String reasonsExplanation;
/**
*
*/
private String scheduleRemark;
/**
*
*/
private Date realStartTime;
/**
*
*/
private Date realEndTime;
/**
*
*/
private Long sortOrder;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
* 0 1
*/
@TableLogic
private String delFlag;
}

@ -9,6 +9,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.util.*;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
/**
* erp_project_info
@ -131,5 +134,39 @@ public class ErpProjectInfoBo extends BaseEntity {
*/
private String activeFlag;
/**
*
*/
private String flowCode;
/**
* ( )
*/
private String handler;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
/**
*
*/
private RemoteFlowInstanceBizExt bizExt;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
public RemoteFlowInstanceBizExt getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new RemoteFlowInstanceBizExt();
}
return bizExt;
}
}

@ -0,0 +1,144 @@
package org.dromara.oa.erp.domain.bo;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
// import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt;
import java.util.*;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ErpProjectPlan.class, reverseConvertGenerate = false)
public class ErpProjectPlanBo extends BaseEntity {
/**
* ID
*/
@NotNull(message = "项目计划ID不能为空", groups = { EditGroup.class })
private Long projectPlanId;
/**
* ID
*/
private Long projectId;
/**
*
*/
private Long managerId;
/**
*
*/
private Long chargeId;
/**
*
*/
private String paymentMethod;
/**
* (1 2 3)
*/
private String projectPlanStatus;
/**
*
*/
private String flowStatus;
/**
*
*/
private Long sortOrder;
/**
* ID()
*/
private Long contractId;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
/**
*
*/
private List<ErpProjectPlanStage> planStageList;
/**
*
*/
private String projectName;
/**
*
*/
private String managerName;
/**
*
*/
private String chargeName;
/**
*
*/
private String contractName;
/**
*
*/
private String flowCode;
/**
* ( )
*/
private String handler;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
/**
*
*/
private RemoteFlowInstanceBizExt bizExt;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
public RemoteFlowInstanceBizExt getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new RemoteFlowInstanceBizExt();
}
return bizExt;
}
}

@ -0,0 +1,122 @@
package org.dromara.oa.erp.domain.bo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ErpProjectPlanStage.class, reverseConvertGenerate = false)
public class ErpProjectPlanStageBo extends BaseEntity {
/**
* ID
*/
@NotNull(message = "计划阶段ID不能为空", groups = { EditGroup.class })
private Long planStageId;
/**
* ID
*/
private Long projectId;
/**
* ID
*/
private Long projectPlanId;
/**
*
*/
private String projectPhases;
/**
*
*/
private Date planStartTime;
/**
*
*/
private Date planEndTime;
/**
*
*/
private String collectionStage;
/**
* (%)
*/
private Long repaymentRate;
/**
*
*/
private Long repaymentAmount;
/**
*
*/
private Date repaymentTime;
/**
*
*/
private Long delayDay;
/**
*
*/
private Date receivableDate;
/**
*
*/
private String reasonsExplanation;
/**
*
*/
private String scheduleRemark;
/**
*
*/
private Date realStartTime;
/**
*
*/
private Date realEndTime;
/**
*
*/
private Long sortOrder;
/**
*
*/
private String remark;
/**
* 1 0
*/
private String activeFlag;
}

@ -160,6 +160,13 @@ public class ErpContractMaterialVo implements Serializable {
/**
*
*/
@ExcelProperty(value = "计量单位名称")
@ExcelProperty(value = "单位")
private String unitName;
/**
*
*/
@ExcelProperty(value = "序号")
private Long seq;
}

@ -0,0 +1,151 @@
package org.dromara.oa.erp.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* erp_project_plan_stage
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ErpProjectPlanStage.class)
public class ErpProjectPlanStageVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "计划阶段ID")
private Long planStageId;
/**
* ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
* ID
*/
@ExcelProperty(value = "项目计划ID")
private Long projectPlanId;
/**
*
*/
@ExcelProperty(value = "项目阶段")
@ExcelDictFormat(dictType = " project_phases")
private String projectPhases;
/**
*
*/
@ExcelProperty(value = "计划开始时间")
private Date planStartTime;
/**
*
*/
@ExcelProperty(value = "计划结束时间")
private Date planEndTime;
/**
*
*/
@ExcelProperty(value = "回款阶段")
@ExcelDictFormat(dictType = " collection_stage")
private String collectionStage;
/**
* (%)
*/
@ExcelProperty(value = "预计回款比例(%)")
private Long repaymentRate;
/**
*
*/
@ExcelProperty(value = "预计回款金额")
private Long repaymentAmount;
/**
*
*/
@ExcelProperty(value = "预计回款时间")
private Date repaymentTime;
/**
*
*/
@ExcelProperty(value = "回款延期天数")
private Long delayDay;
/**
*
*/
@ExcelProperty(value = "应收款日期")
private Date receivableDate;
/**
*
*/
@ExcelProperty(value = "原因说明")
private String reasonsExplanation;
/**
*
*/
@ExcelProperty(value = "进度备注")
private String scheduleRemark;
/**
*
*/
@ExcelProperty(value = "实际开始时间")
private Date realStartTime;
/**
*
*/
@ExcelProperty(value = "实际结束时间")
private Date realEndTime;
/**
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "active_flag")
private String activeFlag;
}

@ -0,0 +1,129 @@
package org.dromara.oa.erp.domain.vo;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* erp_project_plan
*
* @author Yinq
* @date 2025-10-30
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ErpProjectPlan.class)
public class ErpProjectPlanVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@ExcelProperty(value = "项目计划ID")
private Long projectPlanId;
/**
* ID
*/
@ExcelProperty(value = "项目ID")
private Long projectId;
/**
*
*/
@ExcelProperty(value = "项目经理")
private Long managerId;
/**
*
*/
@ExcelProperty(value = "部门负责人")
private Long chargeId;
/**
*
*/
@ExcelProperty(value = "付款方式")
private String paymentMethod;
/**
* (1 2 3)
*/
@ExcelProperty(value = "项目计划状态(1暂存 2审批中 3可用)", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "project_plan_status")
private String projectPlanStatus;
/**
*
*/
@ExcelProperty(value = "流程状态")
private String flowStatus;
/**
*
*/
@ExcelProperty(value = "排序号")
private Long sortOrder;
/**
* ID()
*/
@ExcelProperty(value = "合同ID(预留)")
private Long contractId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 1 0
*/
@ExcelProperty(value = "激活标识", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "active_flag")
private String activeFlag;
/**
*
*/
private List<ErpProjectPlanStageVo> planStageList;
/**
*
*/
@ExcelProperty(value = "项目名称")
private String projectName;
/**
*
*/
@ExcelProperty(value = "项目经理名称")
private String managerName;
/**
*
*/
@ExcelProperty(value = "部门负责人名称")
private String chargeName;
/**
*
*/
@ExcelProperty(value = "合同名称")
private String contractName;
}

@ -0,0 +1,113 @@
package org.dromara.oa.erp.mapper;
import java.util.List;
import java.util.Collection;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author Yinq
* @date 2025-10-30
*/
public interface ErpProjectPlanMapper extends BaseMapperPlus<ErpProjectPlan, ErpProjectPlanVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
public Page<ErpProjectPlanVo> selectCustomErpProjectPlanVoList(@Param("page") Page<ErpProjectPlanVo> page, @Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param queryWrapper
* @return
*/
public List<ErpProjectPlanVo> selectCustomErpProjectPlanVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlan> queryWrapper);
/**
* ID
*
* @param projectPlanId ID
* @return
*/
ErpProjectPlanVo selectCustomErpProjectPlanVoById(@Param("projectPlanId") Long projectPlanId);
/**
* ID
*
* @param ids ID
* @return
*/
List<ErpProjectPlanVo> selectCustomErpProjectPlanVoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Long countCustomErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<ErpProjectPlanVo> selectCustomErpProjectPlanVoPage(@Param("page") Page<ErpProjectPlanVo> page, @Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
*
*
* @param list
* @return
*/
int batchInsertErpProjectPlan(@Param("list") List<ErpProjectPlan> list);
/**
*
*
* @param list
* @return
*/
int batchUpdateErpProjectPlan(@Param("list") List<ErpProjectPlan> list);
/**
*
*
* @param queryWrapper
* @return
*/
int deleteCustomErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
/**
* ID
*
* @param ids ID
* @return
*/
int deleteCustomErpProjectPlanByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Boolean existsErpProjectPlan(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlan> queryWrapper);
}

@ -0,0 +1,113 @@
package org.dromara.oa.erp.mapper;
import java.util.List;
import java.util.Collection;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author Yinq
* @date 2025-10-30
*/
public interface ErpProjectPlanStageMapper extends BaseMapperPlus<ErpProjectPlanStage, ErpProjectPlanStageVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
public Page<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoList(@Param("page") Page<ErpProjectPlanStageVo> page, @Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param queryWrapper
* @return
*/
public List<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoList(@Param(Constants.WRAPPER) MPJLambdaWrapper<ErpProjectPlanStage> queryWrapper);
/**
* ID
*
* @param planStageId ID
* @return
*/
ErpProjectPlanStageVo selectCustomErpProjectPlanStageVoById(@Param("planStageId") Long planStageId);
/**
* ID
*
* @param ids ID
* @return
*/
List<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Long countCustomErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<ErpProjectPlanStageVo> selectCustomErpProjectPlanStageVoPage(@Param("page") Page<ErpProjectPlanStageVo> page, @Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
*
*
* @param list
* @return
*/
int batchInsertErpProjectPlanStage(@Param("list") List<ErpProjectPlanStage> list);
/**
*
*
* @param list
* @return
*/
int batchUpdateErpProjectPlanStage(@Param("list") List<ErpProjectPlanStage> list);
/**
*
*
* @param queryWrapper
* @return
*/
int deleteCustomErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
/**
* ID
*
* @param ids ID
* @return
*/
int deleteCustomErpProjectPlanStageByIds(@Param("ids") Collection<Long> ids);
/**
*
*
* @param queryWrapper
* @return
*/
Boolean existsErpProjectPlanStage(@Param(Constants.WRAPPER) Wrapper<ErpProjectPlanStage> queryWrapper);
}

@ -66,4 +66,11 @@ public interface IErpProjectInfoService {
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
*
* @param bo
* @return
*/
ErpProjectInfoVo projectSubmitAndFlowStart(ErpProjectInfoBo bo);
}

@ -0,0 +1,76 @@
package org.dromara.oa.erp.service;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
public interface IErpProjectPlanService {
/**
*
*
* @param projectPlanId
* @return
*/
ErpProjectPlanVo queryById(Long projectPlanId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<ErpProjectPlanVo> queryPageList(ErpProjectPlanBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<ErpProjectPlanVo> queryList(ErpProjectPlanBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(ErpProjectPlanBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(ErpProjectPlanBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
*
* @param bo
* @return
*/
ErpProjectPlanVo projectPlanSubmitAndFlowStart(ErpProjectPlanBo bo);
}

@ -0,0 +1,69 @@
package org.dromara.oa.erp.service;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
public interface IErpProjectPlanStageService {
/**
*
*
* @param planStageId
* @return
*/
ErpProjectPlanStageVo queryById(Long planStageId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<ErpProjectPlanStageVo> queryPageList(ErpProjectPlanStageBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<ErpProjectPlanStageVo> queryList(ErpProjectPlanStageBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(ErpProjectPlanStageBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(ErpProjectPlanStageBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

@ -64,7 +64,8 @@ public class ErpContractInfoServiceImpl implements IErpContractInfoService {
ErpContractInfoVo contractInfoVo = baseMapper.selectVoById(contractId);
MPJLambdaWrapper<ErpContractMaterial> lqw = JoinWrappers.lambda(ErpContractMaterial.class)
.selectAll(ErpContractMaterial.class)
.eq(contractId != null, ErpContractMaterial::getContractId, contractId);
.eq(contractId != null, ErpContractMaterial::getContractId, contractId)
.eq("t.del_flag", "0");;
List<ErpContractMaterialVo> contractMaterialList = contractMaterialMapper.selectCustomErpContractMaterialVoList(lqw);
contractInfoVo.setContractMaterialList(contractMaterialList);
return contractInfoVo;
@ -117,6 +118,7 @@ public class ErpContractInfoServiceImpl implements IErpContractInfoService {
.eq(bo.getSignatureAppendix() != null, ErpContractInfo::getSignatureAppendix, bo.getSignatureAppendix())
.eq(bo.getTaxRate() != null, ErpContractInfo::getTaxRate, bo.getTaxRate())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpContractInfo::getActiveFlag, bo.getActiveFlag())
.eq("t.del_flag", "0")
.orderByDesc(ErpContractInfo::getCreateTime);
return lqw;
}

@ -66,7 +66,7 @@ public class ErpContractMaterialServiceImpl implements IErpContractMaterialServi
@Override
public List<ErpContractMaterialVo> queryList(ErpContractMaterialBo bo) {
MPJLambdaWrapper<ErpContractMaterial> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
return baseMapper.selectCustomErpContractMaterialVoList(lqw);
}
private MPJLambdaWrapper<ErpContractMaterial> buildQueryWrapper(ErpContractMaterialBo bo) {
@ -86,6 +86,7 @@ public class ErpContractMaterialServiceImpl implements IErpContractMaterialServi
.eq(bo.getIncludingPrice() != null, ErpContractMaterial::getIncludingPrice, bo.getIncludingPrice())
.eq(bo.getSubtotal() != null, ErpContractMaterial::getSubtotal, bo.getSubtotal())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpContractMaterial::getActiveFlag, bo.getActiveFlag())
.eq("t.del_flag", "0")
.orderByAsc(ErpContractMaterial::getContractMaterialId);
return lqw;
}

@ -76,7 +76,8 @@ public class ErpProjectContractsServiceImpl implements IErpProjectContractsServi
.eq(bo.getProjectId() != null, ErpProjectContracts::getProjectId, bo.getProjectId())
.eq(bo.getContractId() != null, ErpProjectContracts::getContractId, bo.getContractId())
.eq(bo.getSortOrder() != null, ErpProjectContracts::getSortOrder, bo.getSortOrder())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectContracts::getActiveFlag, bo.getActiveFlag());
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectContracts::getActiveFlag, bo.getActiveFlag())
.eq("t.del_flag", "0");
return lqw;
}

@ -7,7 +7,6 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpProjectInfoBo;
@ -15,6 +14,11 @@ import org.dromara.oa.erp.domain.vo.ErpProjectInfoVo;
import org.dromara.oa.erp.domain.ErpProjectInfo;
import org.dromara.oa.erp.mapper.ErpProjectInfoMapper;
import org.dromara.oa.erp.service.IErpProjectInfoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import java.util.List;
import java.util.Map;
@ -32,6 +36,9 @@ public class ErpProjectInfoServiceImpl implements IErpProjectInfoService {
private final ErpProjectInfoMapper baseMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
/**
*
*
@ -70,7 +77,6 @@ public class ErpProjectInfoServiceImpl implements IErpProjectInfoService {
}
private MPJLambdaWrapper<ErpProjectInfo> buildQueryWrapper(ErpProjectInfoBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectInfo> lqw = JoinWrappers.lambda(ErpProjectInfo.class)
.selectAll(ErpProjectInfo.class)
.eq(StringUtils.isNotBlank(bo.getContractFlag()), ErpProjectInfo::getContractFlag, bo.getContractFlag())
@ -91,7 +97,9 @@ public class ErpProjectInfoServiceImpl implements IErpProjectInfoService {
.eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectInfo::getFlowStatus, bo.getFlowStatus())
.eq(bo.getSortOrder() != null, ErpProjectInfo::getSortOrder, bo.getSortOrder())
.eq(bo.getContractId() != null, ErpProjectInfo::getContractId, bo.getContractId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectInfo::getActiveFlag, bo.getActiveFlag());
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectInfo::getActiveFlag, bo.getActiveFlag())
.eq("t.del_flag", "0")
.orderByDesc(ErpProjectInfo::getCreateTime);
return lqw;
}
@ -146,4 +154,35 @@ public class ErpProjectInfoServiceImpl implements IErpProjectInfoService {
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
*
*
* @param bo
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public ErpProjectInfoVo projectSubmitAndFlowStart(ErpProjectInfoBo bo) {
ErpProjectInfo add = MapstructUtils.convert(bo, ErpProjectInfo.class);
validEntityBeforeSave(add);
if (StringUtils.isNull(bo.getProjectId())) {
this.insertByBo(bo);
} else {
this.updateByBo(bo);
}
// 后端发起需要忽略权限
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getProjectId().toString());
startProcess.setFlowCode(bo.getFlowCode());
startProcess.setVariables(bo.getVariables());
startProcess.setBizExt(bo.getBizExt());
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("流程发起异常");
}
return MapstructUtils.convert(add, ErpProjectInfoVo.class);
}
}

@ -0,0 +1,322 @@
package org.dromara.oa.erp.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.enums.OAStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.oa.erp.domain.ErpProjectInfo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper;
import org.dromara.workflow.api.RemoteWorkflowService;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.event.ProcessEvent;
import org.springframework.context.event.EventListener;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanBo;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanVo;
import org.dromara.oa.erp.domain.ErpProjectPlan;
import org.dromara.oa.erp.mapper.ErpProjectPlanMapper;
import org.dromara.oa.erp.service.IErpProjectPlanService;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class ErpProjectPlanServiceImpl implements IErpProjectPlanService {
private final ErpProjectPlanMapper baseMapper;
private final ErpProjectPlanStageMapper planStageMapper;
@DubboReference(timeout = 30000)
private RemoteWorkflowService remoteWorkflowService;
/**
*
*
* @param projectPlanId
* @return
*/
@Override
public ErpProjectPlanVo queryById(Long projectPlanId){
// 使用自定义方法查询,包含关联数据
ErpProjectPlanVo projectPlanVo = baseMapper.selectCustomErpProjectPlanVoById(projectPlanId);
// 查询项目计划阶段列表
MPJLambdaWrapper<ErpProjectPlanStage> lqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
.selectAll(ErpProjectPlanStage.class)
.eq("t.del_flag", "0")
.eq(projectPlanId != null, ErpProjectPlanStage::getProjectPlanId, projectPlanId);
List<ErpProjectPlanStageVo> planStageList = planStageMapper.selectVoList(lqw);
projectPlanVo.setPlanStageList(planStageList);
return projectPlanVo;
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<ErpProjectPlanVo> queryPageList(ErpProjectPlanBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectPlan> lqw = buildQueryWrapper(bo);
// 使用自定义分页查询方法获取包含关联数据的结果
Page<ErpProjectPlanVo> result = baseMapper.selectCustomErpProjectPlanVoList(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<ErpProjectPlanVo> queryList(ErpProjectPlanBo bo) {
MPJLambdaWrapper<ErpProjectPlan> lqw = buildQueryWrapper(bo);
// 使用自定义查询方法获取包含关联数据的列表
return baseMapper.selectCustomErpProjectPlanVoList(lqw);
}
private MPJLambdaWrapper<ErpProjectPlan> buildQueryWrapper(ErpProjectPlanBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectPlan> lqw = JoinWrappers.lambda(ErpProjectPlan.class)
.selectAll(ErpProjectPlan.class)
.eq(ErpProjectPlan::getDelFlag, "0")
// 关联项目信息
.select(ErpProjectInfo::getProjectName)
.leftJoin(ErpProjectInfo.class,ErpProjectInfo::getProjectId, ErpProjectPlan::getProjectId)
.eq(bo.getProjectId() != null, ErpProjectPlan::getProjectId, bo.getProjectId())
.eq(bo.getManagerId() != null, ErpProjectPlan::getManagerId, bo.getManagerId())
.eq(bo.getChargeId() != null, ErpProjectPlan::getChargeId, bo.getChargeId())
.eq(StringUtils.isNotBlank(bo.getPaymentMethod()), ErpProjectPlan::getPaymentMethod, bo.getPaymentMethod())
.eq(StringUtils.isNotBlank(bo.getProjectPlanStatus()), ErpProjectPlan::getProjectPlanStatus, bo.getProjectPlanStatus())
.eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpProjectPlan::getFlowStatus, bo.getFlowStatus())
.eq(bo.getSortOrder() != null, ErpProjectPlan::getSortOrder, bo.getSortOrder())
.eq(bo.getContractId() != null, ErpProjectPlan::getContractId, bo.getContractId())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPlan::getActiveFlag, bo.getActiveFlag());
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ErpProjectPlanBo bo) {
ErpProjectPlan add = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(add);
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getManagerId());
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
boolean flag = baseMapper.insert(add) > 0;
if (flag && planStageList != null && !planStageList.isEmpty()) {
bo.setProjectPlanId(add.getProjectPlanId());
for (ErpProjectPlanStage planStage : planStageList) {
planStage.setProjectPlanId(add.getProjectPlanId());
planStage.setProjectId(add.getProjectId());
planStageMapper.insert(planStage);
}
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateByBo(ErpProjectPlanBo bo) {
// 获取原有数据
ErpProjectPlan existingPlan = baseMapper.selectById(bo.getProjectPlanId());
if (existingPlan == null) {
throw new ServiceException("项目计划不存在");
}
// 权限校验:只有项目经理才能修改
validateProjectManager(existingPlan.getManagerId());
// 如果不是草稿状态只允许更新阶段的delayDay和scheduleRemark
if (!"1".equals(existingPlan.getProjectPlanStatus())) {
// 非草稿状态,只更新阶段的特定字段
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
if (planStageList != null && !planStageList.isEmpty()) {
for (ErpProjectPlanStage newStage : planStageList) {
if (newStage.getPlanStageId() != null) {
// 只更新delayDay、scheduleRemark和receivableDate
ErpProjectPlanStage existingStage = planStageMapper.selectById(newStage.getPlanStageId());
if (existingStage != null) {
existingStage.setDelayDay(newStage.getDelayDay());
existingStage.setScheduleRemark(newStage.getScheduleRemark());
existingStage.setReceivableDate(newStage.getReceivableDate());
planStageMapper.updateById(existingStage);
}
}
}
}
// 不更新主表数据
return true;
}
// 草稿状态,允许全面更新
ErpProjectPlan update = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(update);
List<ErpProjectPlanStage> planStageList = bo.getPlanStageList();
MPJLambdaWrapper<ErpProjectPlanStage> lqwRecord = JoinWrappers.lambda(ErpProjectPlanStage.class);
lqwRecord.eq(ErpProjectPlanStage::getProjectPlanId, bo.getProjectPlanId());
List<ErpProjectPlanStage> planStageOldList = planStageMapper.selectList(lqwRecord);
// 如果计划阶段列表不为空且不为空列表,则进行处理
if (planStageList != null && !planStageList.isEmpty()) {
// 遍历计划阶段列表设置项目ID并插入或更新数据库记录
for (ErpProjectPlanStage planStage : planStageList) {
planStage.setProjectId(update.getProjectId());
planStageMapper.insertOrUpdate(planStage);
}
// 收集当前计划阶段列表中已存在的计划阶段ID集合
Set<Long> existingPlanStageIds = planStageList.stream()
.map(ErpProjectPlanStage::getPlanStageId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 从旧的计划阶段列表中筛选出需要删除的记录(即不在当前列表中的记录)
List<ErpProjectPlanStage> filterPlanStageIds = planStageOldList.stream()
.filter(stage -> !existingPlanStageIds.contains(stage.getPlanStageId()))
.toList();
// 删除需要移除的计划阶段记录
for (ErpProjectPlanStage filterPlanStageId : filterPlanStageIds) {
planStageMapper.deleteById(filterPlanStageId.getPlanStageId());
}
}
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(ErpProjectPlan entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param managerId ID
*/
private void validateProjectManager(Long managerId) {
// 超级管理员跳过校验
if (LoginHelper.isSuperAdmin()) {
return;
}
// 普通用户判断当前用户ID是否等于项目经理ID
Long currentUserId = LoginHelper.getUserId();
if (!currentUserId.equals(managerId)) {
throw new ServiceException("只有项目经理才能提交项目计划");
}
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
*
*
* @param bo
* @return
*/
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public ErpProjectPlanVo projectPlanSubmitAndFlowStart(ErpProjectPlanBo bo) {
ErpProjectPlan add = MapstructUtils.convert(bo, ErpProjectPlan.class);
validEntityBeforeSave(add);
// 权限校验:只有项目经理才能提交
validateProjectManager(bo.getManagerId());
if (StringUtils.isNull(bo.getProjectPlanId())) {
this.insertByBo(bo);
} else {
this.updateByBo(bo);
}
// 后端发起需要忽略权限
bo.getVariables().put("ignore", true);
RemoteStartProcess startProcess = new RemoteStartProcess();
startProcess.setBusinessId(bo.getProjectPlanId().toString());
startProcess.setFlowCode(bo.getFlowCode());
startProcess.setVariables(bo.getVariables());
startProcess.setBizExt(bo.getBizExt());
bo.getBizExt().setBusinessId(startProcess.getBusinessId());
boolean flagOne = remoteWorkflowService.startCompleteTask(startProcess);
if (!flagOne) {
throw new ServiceException("流程发起异常");
}
return MapstructUtils.convert(add, ErpProjectPlanVo.class);
}
/**
* (: 稿退)
*
* @param processEvent
*/
@EventListener(condition = "#processEvent.flowCode =='OAPS'")
public void processHandler(ProcessEvent processEvent) {
TenantHelper.dynamic(processEvent.getTenantId(), () -> {
log.info("当前任务执行了{}", processEvent.toString());
ErpProjectPlan projectPlan = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId()));
projectPlan.setFlowStatus(processEvent.getStatus());
Map<String, Object> params = processEvent.getParams();
if (MapUtil.isNotEmpty(params)) {
// 办理人
String handler = Convert.toStr(params.get("handler"));
}
if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) {
projectPlan.setProjectPlanStatus(OAStatusEnum.COMPLETED.getStatus());
}
baseMapper.updateById(projectPlan);
});
}
}

@ -0,0 +1,149 @@
package org.dromara.oa.erp.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.oa.erp.domain.bo.ErpProjectPlanStageBo;
import org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo;
import org.dromara.oa.erp.domain.ErpProjectPlanStage;
import org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper;
import org.dromara.oa.erp.service.IErpProjectPlanStageService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* Service
*
* @author Yinq
* @date 2025-10-30
*/
@RequiredArgsConstructor
@Service
public class ErpProjectPlanStageServiceImpl implements IErpProjectPlanStageService {
private final ErpProjectPlanStageMapper baseMapper;
/**
*
*
* @param planStageId
* @return
*/
@Override
public ErpProjectPlanStageVo queryById(Long planStageId){
return baseMapper.selectVoById(planStageId);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<ErpProjectPlanStageVo> queryPageList(ErpProjectPlanStageBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<ErpProjectPlanStage> lqw = buildQueryWrapper(bo);
Page<ErpProjectPlanStageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<ErpProjectPlanStageVo> queryList(ErpProjectPlanStageBo bo) {
MPJLambdaWrapper<ErpProjectPlanStage> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private MPJLambdaWrapper<ErpProjectPlanStage> buildQueryWrapper(ErpProjectPlanStageBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<ErpProjectPlanStage> lqw = JoinWrappers.lambda(ErpProjectPlanStage.class)
.selectAll(ErpProjectPlanStage.class)
.eq(ErpProjectPlanStage::getDelFlag, "0")
.eq(bo.getProjectId() != null, ErpProjectPlanStage::getProjectId, bo.getProjectId())
.eq(bo.getProjectPlanId() != null, ErpProjectPlanStage::getProjectPlanId, bo.getProjectPlanId())
.eq(StringUtils.isNotBlank(bo.getProjectPhases()), ErpProjectPlanStage::getProjectPhases, bo.getProjectPhases())
.eq(bo.getPlanStartTime() != null, ErpProjectPlanStage::getPlanStartTime, bo.getPlanStartTime())
.eq(bo.getPlanEndTime() != null, ErpProjectPlanStage::getPlanEndTime, bo.getPlanEndTime())
.eq(StringUtils.isNotBlank(bo.getCollectionStage()), ErpProjectPlanStage::getCollectionStage, bo.getCollectionStage())
.eq(bo.getRepaymentRate() != null, ErpProjectPlanStage::getRepaymentRate, bo.getRepaymentRate())
.eq(bo.getRepaymentAmount() != null, ErpProjectPlanStage::getRepaymentAmount, bo.getRepaymentAmount())
.eq(bo.getRepaymentTime() != null, ErpProjectPlanStage::getRepaymentTime, bo.getRepaymentTime())
.eq(bo.getDelayDay() != null, ErpProjectPlanStage::getDelayDay, bo.getDelayDay())
.eq(bo.getReceivableDate() != null, ErpProjectPlanStage::getReceivableDate, bo.getReceivableDate())
.eq(StringUtils.isNotBlank(bo.getReasonsExplanation()), ErpProjectPlanStage::getReasonsExplanation, bo.getReasonsExplanation())
.eq(StringUtils.isNotBlank(bo.getScheduleRemark()), ErpProjectPlanStage::getScheduleRemark, bo.getScheduleRemark())
.eq(bo.getRealStartTime() != null, ErpProjectPlanStage::getRealStartTime, bo.getRealStartTime())
.eq(bo.getRealEndTime() != null, ErpProjectPlanStage::getRealEndTime, bo.getRealEndTime())
.eq(bo.getSortOrder() != null, ErpProjectPlanStage::getSortOrder, bo.getSortOrder())
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpProjectPlanStage::getActiveFlag, bo.getActiveFlag())
;
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean insertByBo(ErpProjectPlanStageBo bo) {
ErpProjectPlanStage add = MapstructUtils.convert(bo, ErpProjectPlanStage.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanStageId(add.getPlanStageId());
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean updateByBo(ErpProjectPlanStageBo bo) {
ErpProjectPlanStage update = MapstructUtils.convert(bo, ErpProjectPlanStage.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(ErpProjectPlanStage entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

@ -0,0 +1,319 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.oa.crm.mapper.CrmSupplierInfoMapper">
<resultMap type="org.dromara.oa.crm.domain.vo.CrmSupplierInfoVo" id="CrmSupplierInfoResult">
</resultMap>
<select id="selectCustomCrmSupplierInfoVoList" resultMap="CrmSupplierInfoResult">
select t.supplier_id, t.tenant_id, t.supplier_name, t.mnemonic_name, t.supplier_type,
t.registered_capital, t.establishment_date, t.business_scope, t.main_industry,
t.legal_representative, t.business_license_number, t.tax_number, t.bank_account_opening,
t.bank_number, t.registered_address, t.business_address, t.contact_person, t.contact_phone, t.contact_mobile,
t.contact_email, t.contact_fax, t.website, t.owner_id, t.detailed_address, t.oss_id, t.remark, t.active_flag, t.del_flag, t.create_dept,
u1.nick_name as ownerName,
t.create_by, t.create_time, t.update_by, t.update_time
from crm_supplier_info t
left join sys_user u1 on u1.user_id = t.owner_id
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomCrmSupplierInfoVoById" resultMap="CrmSupplierInfoResult">
select t.supplier_id, t.tenant_id, t.supplier_name, t.mnemonic_name, t.supplier_type, t.registered_capital, t.establishment_date, t.business_scope, t.main_industry, t.legal_representative, t.business_license_number, t.tax_number, t.bank_account_opening, t.bank_number, t.registered_address, t.business_address, t.contact_person, t.contact_phone, t.contact_mobile, t.contact_email, t.contact_fax, t.website, t.owner_id, t.detailed_address, t.oss_id, t.remark, t.active_flag, t.del_flag, t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time
from crm_supplier_info t
where t.supplier_id = #{supplierId}
</select>
<!-- 批量查询 - 根据ID列表 -->
<select id="selectCustomCrmSupplierInfoVoByIds" resultMap="CrmSupplierInfoResult">
select t.supplier_id, t.tenant_id, t.supplier_name, t.mnemonic_name, t.supplier_type, t.registered_capital, t.establishment_date, t.business_scope, t.main_industry, t.legal_representative, t.business_license_number, t.tax_number, t.bank_account_opening, t.bank_number, t.registered_address, t.business_address, t.contact_person, t.contact_phone, t.contact_mobile, t.contact_email, t.contact_fax, t.website, t.owner_id, t.detailed_address, t.oss_id, t.remark, t.active_flag, t.del_flag, t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time
from crm_supplier_info t
where t.supplier_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 统计查询 -->
<select id="countCustomCrmSupplierInfo" resultType="java.lang.Long">
select count(1) from crm_supplier_info t
${ew.getCustomSqlSegment}
</select>
<!-- 分页查询(带自定义条件) -->
<select id="selectCustomCrmSupplierInfoVoPage" resultMap="CrmSupplierInfoResult">
select t.supplier_id, t.tenant_id, t.supplier_name, t.mnemonic_name, t.supplier_type, t.registered_capital, t.establishment_date, t.business_scope, t.main_industry, t.legal_representative, t.business_license_number, t.tax_number, t.bank_account_opening, t.bank_number, t.registered_address, t.business_address, t.contact_person, t.contact_phone, t.contact_mobile, t.contact_email, t.contact_fax, t.website, t.owner_id, t.detailed_address, t.oss_id, t.remark, t.active_flag, t.del_flag, t.create_dept, t.create_by, t.create_time, t.update_by, t.update_time
from crm_supplier_info t
${ew.getCustomSqlSegment}
</select>
<!-- 批量插入 -->
<insert id="batchInsertCrmSupplierInfo">
insert into crm_supplier_info(
tenant_id,
supplier_name,
mnemonic_name,
supplier_type,
registered_capital,
establishment_date,
business_scope,
main_industry,
legal_representative,
business_license_number,
tax_number,
bank_account_opening,
bank_number,
registered_address,
business_address,
contact_person,
contact_phone,
contact_mobile,
contact_email,
contact_fax,
website,
owner_id,
detailed_address,
oss_id,
remark,
active_flag,
del_flag,
create_dept,
create_by,
create_time,
update_by,
update_time
)
values
<foreach collection="list" item="item" separator=",">
(
#{item.tenantId},
#{item.supplierName},
#{item.mnemonicName},
#{item.supplierType},
#{item.registeredCapital},
#{item.establishmentDate},
#{item.businessScope},
#{item.mainIndustry},
#{item.legalRepresentative},
#{item.businessLicenseNumber},
#{item.taxNumber},
#{item.bankAccountOpening},
#{item.bankNumber},
#{item.registeredAddress},
#{item.businessAddress},
#{item.contactPerson},
#{item.contactPhone},
#{item.contactMobile},
#{item.contactEmail},
#{item.contactFax},
#{item.website},
#{item.ownerId},
#{item.detailedAddress},
#{item.ossId},
#{item.remark},
#{item.activeFlag},
#{item.delFlag},
#{item.createDept},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
#{item.updateTime}
)
</foreach>
</insert>
<!-- 批量更新 -->
<update id="batchUpdateCrmSupplierInfo">
<foreach collection="list" item="item" separator=";">
update crm_supplier_info
<set>
<if test="item.tenantId != null and item.tenantId != ''">
tenant_id = #{item.tenantId},
</if>
<if test="item.supplierName != null and item.supplierName != ''">
supplier_name = #{item.supplierName},
</if>
<if test="item.mnemonicName != null and item.mnemonicName != ''">
mnemonic_name = #{item.mnemonicName},
</if>
<if test="item.supplierType != null and item.supplierType != ''">
supplier_type = #{item.supplierType},
</if>
<if test="item.registeredCapital != null">
registered_capital = #{item.registeredCapital},
</if>
<if test="item.establishmentDate != null">
establishment_date = #{item.establishmentDate},
</if>
<if test="item.businessScope != null and item.businessScope != ''">
business_scope = #{item.businessScope},
</if>
<if test="item.mainIndustry != null and item.mainIndustry != ''">
main_industry = #{item.mainIndustry},
</if>
<if test="item.legalRepresentative != null and item.legalRepresentative != ''">
legal_representative = #{item.legalRepresentative},
</if>
<if test="item.businessLicenseNumber != null and item.businessLicenseNumber != ''">
business_license_number = #{item.businessLicenseNumber},
</if>
<if test="item.taxNumber != null and item.taxNumber != ''">
tax_number = #{item.taxNumber},
</if>
<if test="item.bankAccountOpening != null and item.bankAccountOpening != ''">
bank_account_opening = #{item.bankAccountOpening},
</if>
<if test="item.bankNumber != null and item.bankNumber != ''">
bank_number = #{item.bankNumber},
</if>
<if test="item.registeredAddress != null and item.registeredAddress != ''">
registered_address = #{item.registeredAddress},
</if>
<if test="item.businessAddress != null and item.businessAddress != ''">
business_address = #{item.businessAddress},
</if>
<if test="item.contactPerson != null and item.contactPerson != ''">
contact_person = #{item.contactPerson},
</if>
<if test="item.contactPhone != null and item.contactPhone != ''">
contact_phone = #{item.contactPhone},
</if>
<if test="item.contactMobile != null and item.contactMobile != ''">
contact_mobile = #{item.contactMobile},
</if>
<if test="item.contactEmail != null and item.contactEmail != ''">
contact_email = #{item.contactEmail},
</if>
<if test="item.contactFax != null and item.contactFax != ''">
contact_fax = #{item.contactFax},
</if>
<if test="item.website != null and item.website != ''">
website = #{item.website},
</if>
<if test="item.ownerId != null">
owner_id = #{item.ownerId},
</if>
<if test="item.detailedAddress != null and item.detailedAddress != ''">
detailed_address = #{item.detailedAddress},
</if>
<if test="item.ossId != null and item.ossId != ''">
oss_id = #{item.ossId},
</if>
<if test="item.remark != null and item.remark != ''">
remark = #{item.remark},
</if>
<if test="item.activeFlag != null and item.activeFlag != ''">
active_flag = #{item.activeFlag},
</if>
<if test="item.delFlag != null and item.delFlag != ''">
del_flag = #{item.delFlag},
</if>
<if test="item.createDept != null">
create_dept = #{item.createDept},
</if>
<if test="item.createBy != null">
create_by = #{item.createBy},
</if>
<if test="item.createTime != null">
create_time = #{item.createTime},
</if>
<if test="item.updateBy != null">
update_by = #{item.updateBy},
</if>
<if test="item.updateTime != null">
update_time = #{item.updateTime}
</if>
</set>
where supplier_id = #{item.supplierId}
</foreach>
</update>
<!-- 根据自定义条件删除 -->
<delete id="deleteCustomCrmSupplierInfo">
delete from crm_supplier_info
${ew.getCustomSqlSegment}
</delete>
<!-- 根据ID列表批量删除 -->
<delete id="deleteCustomCrmSupplierInfoByIds">
delete from crm_supplier_info
where supplier_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 检查是否存在 -->
<select id="existsCrmSupplierInfo" resultType="java.lang.Boolean">
select count(1) > 0 from crm_supplier_info t
${ew.getCustomSqlSegment}
</select>
</mapper>

@ -0,0 +1,307 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.oa.erp.mapper.ErpProjectPlanMapper">
<resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectPlanVo" id="ErpProjectPlanResult">
</resultMap>
<select id="selectCustomErpProjectPlanVoList" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomErpProjectPlanVoById" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
where t.project_plan_id = #{projectPlanId}
</select>
<!-- 批量查询 - 根据ID列表 -->
<select id="selectCustomErpProjectPlanVoByIds" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
where t.project_plan_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 统计查询 -->
<select id="countCustomErpProjectPlan" resultType="java.lang.Long">
select count(1) from erp_project_plan t
${ew.getCustomSqlSegment}
</select>
<!-- 分页查询(带自定义条件) -->
<select id="selectCustomErpProjectPlanVoPage" resultMap="ErpProjectPlanResult">
select t.project_plan_id,
t.tenant_id,
t.project_id,
t.manager_id,
t.charge_id,
t.payment_method,
t.project_plan_status,
t.flow_status,
t.sort_order,
t.contract_id,
t.remark,
t.active_flag,
t.del_flag,
t.create_dept,
t.create_by,
t.create_time,
t.update_by,
t.update_time,
p.project_name,
u1.nick_name as managerName,
u2.nick_name as chargeName,
c.contract_name as contractName
from erp_project_plan t
left join erp_project_info p on t.project_id = p.project_id
left join sys_user u1 on t.manager_id = u1.user_id
left join sys_user u2 on t.charge_id = u2.user_id
left join erp_contract_info c on t.contract_id = c.contract_id
${ew.getCustomSqlSegment}
</select>
<!-- 批量插入 -->
<insert id="batchInsertErpProjectPlan">
insert into erp_project_plan(
tenant_id,
project_id,
manager_id,
charge_id,
payment_method,
project_plan_status,
flow_status,
sort_order,
contract_id,
remark,
active_flag,
del_flag,
create_dept,
create_by,
create_time,
update_by,
update_time
)
values
<foreach collection="list" item="item" separator=",">
(
#{item.tenantId},
#{item.projectId},
#{item.managerId},
#{item.chargeId},
#{item.paymentMethod},
#{item.projectPlanStatus},
#{item.flowStatus},
#{item.sortOrder},
#{item.contractId},
#{item.remark},
#{item.activeFlag},
#{item.delFlag},
#{item.createDept},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
#{item.updateTime}
)
</foreach>
</insert>
<!-- 批量更新 -->
<update id="batchUpdateErpProjectPlan">
<foreach collection="list" item="item" separator=";">
update erp_project_plan
<set>
<if test="item.tenantId != null and item.tenantId != ''">
tenant_id = #{item.tenantId},
</if>
<if test="item.projectId != null">
project_id = #{item.projectId},
</if>
<if test="item.managerId != null">
manager_id = #{item.managerId},
</if>
<if test="item.chargeId != null">
charge_id = #{item.chargeId},
</if>
<if test="item.paymentMethod != null and item.paymentMethod != ''">
payment_method = #{item.paymentMethod},
</if>
<if test="item.projectPlanStatus != null and item.projectPlanStatus != ''">
project_plan_status = #{item.projectPlanStatus},
</if>
<if test="item.flowStatus != null and item.flowStatus != ''">
flow_status = #{item.flowStatus},
</if>
<if test="item.sortOrder != null">
sort_order = #{item.sortOrder},
</if>
<if test="item.contractId != null">
contract_id = #{item.contractId},
</if>
<if test="item.remark != null and item.remark != ''">
remark = #{item.remark},
</if>
<if test="item.activeFlag != null and item.activeFlag != ''">
active_flag = #{item.activeFlag},
</if>
<if test="item.delFlag != null and item.delFlag != ''">
del_flag = #{item.delFlag},
</if>
<if test="item.createDept != null">
create_dept = #{item.createDept},
</if>
<if test="item.createBy != null">
create_by = #{item.createBy},
</if>
<if test="item.createTime != null">
create_time = #{item.createTime},
</if>
<if test="item.updateBy != null">
update_by = #{item.updateBy},
</if>
<if test="item.updateTime != null">
update_time = #{item.updateTime}
</if>
</set>
where project_plan_id = #{item.projectPlanId}
</foreach>
</update>
<!-- 根据自定义条件删除 -->
<delete id="deleteCustomErpProjectPlan">
delete from erp_project_plan
${ew.getCustomSqlSegment}
</delete>
<!-- 根据ID列表批量删除 -->
<delete id="deleteCustomErpProjectPlanByIds">
delete from erp_project_plan
where project_plan_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 检查是否存在 -->
<select id="existsErpProjectPlan" resultType="java.lang.Boolean">
select count(1) > 0 from erp_project_plan t
${ew.getCustomSqlSegment}
</select>
</mapper>

@ -0,0 +1,262 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.oa.erp.mapper.ErpProjectPlanStageMapper">
<resultMap type="org.dromara.oa.erp.domain.vo.ErpProjectPlanStageVo" id="ErpProjectPlanStageResult">
</resultMap>
<select id="selectCustomErpProjectPlanStageVoList" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 根据ID查询详情 -->
<select id="selectCustomErpProjectPlanStageVoById" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
where t.plan_stage_id = #{planStageId}
</select>
<!-- 批量查询 - 根据ID列表 -->
<select id="selectCustomErpProjectPlanStageVoByIds" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
where t.plan_stage_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<!-- 统计查询 -->
<select id="countCustomErpProjectPlanStage" resultType="java.lang.Long">
select count(1) from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 分页查询(带自定义条件) -->
<select id="selectCustomErpProjectPlanStageVoPage" resultMap="ErpProjectPlanStageResult">
select plan_stage_id, tenant_id, project_id, project_plan_id, project_phases, plan_start_time, plan_end_time, collection_stage, repayment_rate, repayment_amount, repayment_time, delay_day, receivable_date, reasons_explanation, schedule_remark, real_start_time, real_end_time, sort_order, remark, active_flag, del_flag, create_dept, create_by, create_time, update_by, update_time
from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
<!-- 批量插入 -->
<insert id="batchInsertErpProjectPlanStage">
insert into erp_project_plan_stage(
tenant_id,
project_id,
project_plan_id,
project_phases,
plan_start_time,
plan_end_time,
collection_stage,
repayment_rate,
repayment_amount,
repayment_time,
delay_day,
receivable_date,
reasons_explanation,
schedule_remark,
real_start_time,
real_end_time,
sort_order,
remark,
active_flag,
del_flag,
create_dept,
create_by,
create_time,
update_by,
update_time
)
values
<foreach collection="list" item="item" separator=",">
(
#{item.tenantId},
#{item.projectId},
#{item.projectPlanId},
#{item.projectPhases},
#{item.planStartTime},
#{item.planEndTime},
#{item.collectionStage},
#{item.repaymentRate},
#{item.repaymentAmount},
#{item.repaymentTime},
#{item.delayDay},
#{item.receivableDate},
#{item.reasonsExplanation},
#{item.scheduleRemark},
#{item.realStartTime},
#{item.realEndTime},
#{item.sortOrder},
#{item.remark},
#{item.activeFlag},
#{item.delFlag},
#{item.createDept},
#{item.createBy},
#{item.createTime},
#{item.updateBy},
#{item.updateTime}
)
</foreach>
</insert>
<!-- 批量更新 -->
<update id="batchUpdateErpProjectPlanStage">
<foreach collection="list" item="item" separator=";">
update erp_project_plan_stage
<set>
<if test="item.tenantId != null and item.tenantId != ''">
tenant_id = #{item.tenantId},
</if>
<if test="item.projectId != null">
project_id = #{item.projectId},
</if>
<if test="item.projectPlanId != null">
project_plan_id = #{item.projectPlanId},
</if>
<if test="item.projectPhases != null and item.projectPhases != ''">
project_phases = #{item.projectPhases},
</if>
<if test="item.planStartTime != null">
plan_start_time = #{item.planStartTime},
</if>
<if test="item.planEndTime != null">
plan_end_time = #{item.planEndTime},
</if>
<if test="item.collectionStage != null and item.collectionStage != ''">
collection_stage = #{item.collectionStage},
</if>
<if test="item.repaymentRate != null">
repayment_rate = #{item.repaymentRate},
</if>
<if test="item.repaymentAmount != null">
repayment_amount = #{item.repaymentAmount},
</if>
<if test="item.repaymentTime != null">
repayment_time = #{item.repaymentTime},
</if>
<if test="item.delayDay != null">
delay_day = #{item.delayDay},
</if>
<if test="item.receivableDate != null">
receivable_date = #{item.receivableDate},
</if>
<if test="item.reasonsExplanation != null and item.reasonsExplanation != ''">
reasons_explanation = #{item.reasonsExplanation},
</if>
<if test="item.scheduleRemark != null and item.scheduleRemark != ''">
schedule_remark = #{item.scheduleRemark},
</if>
<if test="item.realStartTime != null">
real_start_time = #{item.realStartTime},
</if>
<if test="item.realEndTime != null">
real_end_time = #{item.realEndTime},
</if>
<if test="item.sortOrder != null">
sort_order = #{item.sortOrder},
</if>
<if test="item.remark != null and item.remark != ''">
remark = #{item.remark},
</if>
<if test="item.activeFlag != null and item.activeFlag != ''">
active_flag = #{item.activeFlag},
</if>
<if test="item.delFlag != null and item.delFlag != ''">
del_flag = #{item.delFlag},
</if>
<if test="item.createDept != null">
create_dept = #{item.createDept},
</if>
<if test="item.createBy != null">
create_by = #{item.createBy},
</if>
<if test="item.createTime != null">
create_time = #{item.createTime},
</if>
<if test="item.updateBy != null">
update_by = #{item.updateBy},
</if>
<if test="item.updateTime != null">
update_time = #{item.updateTime}
</if>
</set>
where plan_stage_id = #{item.planStageId}
</foreach>
</update>
<!-- 根据自定义条件删除 -->
<delete id="deleteCustomErpProjectPlanStage">
delete from erp_project_plan_stage
${ew.getCustomSqlSegment}
</delete>
<!-- 根据ID列表批量删除 -->
<delete id="deleteCustomErpProjectPlanStageByIds">
delete from erp_project_plan_stage
where plan_stage_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 检查是否存在 -->
<select id="existsErpProjectPlanStage" resultType="java.lang.Boolean">
select count(1) > 0 from erp_project_plan_stage t
${ew.getCustomSqlSegment}
</select>
</mapper>

@ -22,6 +22,7 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserPost;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.SysRole;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysPostVo;
import org.dromara.system.domain.vo.SysRoleVo;
@ -59,6 +60,32 @@ public class SysUserServiceImpl implements ISysUserService {
@Override
public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) {
Page<SysUserVo> page = baseMapper.selectVoPage(pageQuery.build(), this.buildQueryWrapper(user));
// 批量填充角色信息
if (CollUtil.isNotEmpty(page.getRecords())) {
List<Long> userIds = StreamUtils.toList(page.getRecords(), SysUserVo::getUserId);
// 批量查询用户角色关联关系
List<SysUserRole> userRoles = userRoleMapper.selectList(
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, userIds));
// 获取所有角色ID
List<Long> roleIds = StreamUtils.toList(userRoles, SysUserRole::getRoleId);
// 批量查询角色信息
List<SysRoleVo> allRoles = CollUtil.isEmpty(roleIds) ? new ArrayList<>() :
roleMapper.selectVoList(new LambdaQueryWrapper<SysRole>().in(SysRole::getRoleId, roleIds));
Map<Long, SysRoleVo> roleMap = StreamUtils.toIdentityMap(allRoles, SysRoleVo::getRoleId);
// 按用户ID分组用户角色关联关系
Map<Long, List<SysUserRole>> userRoleMap = StreamUtils.groupByKey(userRoles, SysUserRole::getUserId);
// 为每个用户填充角色信息
page.getRecords().forEach(userVo -> {
List<SysUserRole> userRoleList = userRoleMap.get(userVo.getUserId());
if (CollUtil.isNotEmpty(userRoleList)) {
List<SysRoleVo> userRoleVoList = StreamUtils.toList(userRoleList, ur -> roleMap.get(ur.getRoleId()))
.stream().filter(ObjectUtil::isNotNull).toList();
userVo.setRoles(userRoleVoList);
} else {
userVo.setRoles(new ArrayList<>());
}
});
}
return TableDataInfo.build(page);
}

Loading…
Cancel
Save