feat(cost): 添加数据源注解和批量操作功能

- 为CostItemService、CostPriceService、CostProdDetailService、CostProdMetricService添加@DataSource注解
- 在CostProdDetailController中新增批量保存生产成本明细接口
- 实现CostProdDetailService的batchSaveWithDelete方法支持先删除再插入
- 添加CostProdDetailBo批量操作参数对象
- 在CostProdReportService中实现copyReport功能支持复制生产月报
- 配置数据源类型为KLP确保数据库连接正确
- 添加相应的映射器方法和SQL模板支持批量插入操作
This commit is contained in:
2026-06-09 10:39:19 +08:00
parent 75ff7790d8
commit c8350b5f0e
12 changed files with 284 additions and 49 deletions

View File

@@ -0,0 +1,40 @@
package com.ruoyi.cost.bo;
import com.ruoyi.cost.domain.CostProdDetail;
import java.util.List;
/**
* 生产成本明细批量操作参数
*
* @author ruoyi
* @date 2026-06-09
*/
public class CostProdDetailBo
{
/** 需删除的明细ID列表 */
private List<Long> detailIds;
/** 需保存的明细列表 */
private List<CostProdDetail> prodDetailList;
public List<Long> getDetailIds()
{
return detailIds;
}
public void setDetailIds(List<Long> detailIds)
{
this.detailIds = detailIds;
}
public List<CostProdDetail> getProdDetailList()
{
return prodDetailList;
}
public void setProdDetailList(List<CostProdDetail> prodDetailList)
{
this.prodDetailList = prodDetailList;
}
}

View File

@@ -18,6 +18,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.cost.domain.CostProdDetail; import com.ruoyi.cost.domain.CostProdDetail;
import com.ruoyi.cost.service.ICostProdDetailService; import com.ruoyi.cost.service.ICostProdDetailService;
import com.ruoyi.cost.bo.CostProdDetailBo;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
@@ -101,4 +102,15 @@ public class CostProdDetailController extends BaseController
{ {
return toAjax(costProdDetailService.deleteCostProdDetailByDetailIds(detailIds)); return toAjax(costProdDetailService.deleteCostProdDetailByDetailIds(detailIds));
} }
/**
* 批量保存生产成本明细(先删除再插入)
*/
@PreAuthorize("@ss.hasPermi('cost:detail:add')")
@Log(title = "生产成本明细", businessType = BusinessType.INSERT)
@PostMapping("/batchSave")
public AjaxResult batchSave(@RequestBody CostProdDetailBo bo)
{
return toAjax(costProdDetailService.batchSaveWithDelete(bo));
}
} }

View File

@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
@@ -80,6 +81,17 @@ public class CostProdReportController extends BaseController
return toAjax(costProdReportService.insertCostProdReport(costProdReport)); return toAjax(costProdReportService.insertCostProdReport(costProdReport));
} }
/**
* 复制生产月报
*/
@PreAuthorize("@ss.hasPermi('cost:report:add')")
@Log(title = "生产月报", businessType = BusinessType.INSERT)
@PostMapping("/copy")
public AjaxResult copy(@RequestParam Long sourceId, @RequestBody CostProdReport costProdReport)
{
return success(costProdReportService.copyReport(sourceId, costProdReport));
}
/** /**
* 修改生产月报 * 修改生产月报
*/ */

View File

@@ -58,4 +58,12 @@ public interface CostProdDetailMapper
* @return 结果 * @return 结果
*/ */
public int deleteCostProdDetailByDetailIds(Long[] detailIds); public int deleteCostProdDetailByDetailIds(Long[] detailIds);
/**
* 批量新增生产成本明细
*
* @param list 生产成本明细列表
* @return 结果
*/
public int insertBatch(List<CostProdDetail> list);
} }

View File

@@ -2,6 +2,8 @@ package com.ruoyi.cost.service;
import java.util.List; import java.util.List;
import com.ruoyi.cost.domain.CostProdDetail; import com.ruoyi.cost.domain.CostProdDetail;
import com.ruoyi.cost.bo.CostProdDetailBo;
import org.springframework.transaction.annotation.Transactional;
/** /**
* 生产成本明细Service接口 * 生产成本明细Service接口
@@ -58,4 +60,14 @@ public interface ICostProdDetailService
* @return 结果 * @return 结果
*/ */
public int deleteCostProdDetailByDetailId(Long detailId); public int deleteCostProdDetailByDetailId(Long detailId);
/**
* 批量保存生产成本明细(先删除再插入)
*
* @param bo 批量操作参数
* @return 结果
*/
@Transactional(rollbackFor = Exception.class)
public Boolean batchSaveWithDelete(CostProdDetailBo bo);
} }

View File

@@ -58,4 +58,14 @@ public interface ICostProdReportService
* @return 结果 * @return 结果
*/ */
public int deleteCostProdReportByReportId(Long reportId); public int deleteCostProdReportByReportId(Long reportId);
/**
* 复制生产月报
* 明细列原样保留itemId不变指标列重新插入并更新config中的id引用
*
* @param sourceId 源报表ID
* @param bo 新报表覆盖字段
* @return 新报表
*/
public CostProdReport copyReport(Long sourceId, CostProdReport bo);
} }

View File

@@ -1,6 +1,9 @@
package com.ruoyi.cost.service.impl; package com.ruoyi.cost.service.impl;
import java.util.List; import java.util.List;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -15,6 +18,7 @@ import com.ruoyi.cost.service.ICostItemService;
* @date 2026-06-09 * @date 2026-06-09
*/ */
@Service @Service
@DataSource(DataSourceType.KLP)
public class CostItemServiceImpl implements ICostItemService public class CostItemServiceImpl implements ICostItemService
{ {
@Autowired @Autowired

View File

@@ -1,6 +1,9 @@
package com.ruoyi.cost.service.impl; package com.ruoyi.cost.service.impl;
import java.util.List; import java.util.List;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -15,6 +18,7 @@ import com.ruoyi.cost.service.ICostPriceService;
* @date 2026-06-09 * @date 2026-06-09
*/ */
@Service @Service
@DataSource(DataSourceType.KLP)
public class CostPriceServiceImpl implements ICostPriceService public class CostPriceServiceImpl implements ICostPriceService
{ {
@Autowired @Autowired

View File

@@ -1,12 +1,19 @@
package com.ruoyi.cost.service.impl; package com.ruoyi.cost.service.impl;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.ruoyi.cost.mapper.CostProdDetailMapper; import com.ruoyi.cost.mapper.CostProdDetailMapper;
import com.ruoyi.cost.domain.CostProdDetail; import com.ruoyi.cost.domain.CostProdDetail;
import com.ruoyi.cost.service.ICostProdDetailService; import com.ruoyi.cost.service.ICostProdDetailService;
import com.ruoyi.cost.bo.CostProdDetailBo;
/** /**
* 生产成本明细Service业务层处理 * 生产成本明细Service业务层处理
@@ -15,6 +22,7 @@ import com.ruoyi.cost.service.ICostProdDetailService;
* @date 2026-06-09 * @date 2026-06-09
*/ */
@Service @Service
@DataSource(DataSourceType.KLP)
public class CostProdDetailServiceImpl implements ICostProdDetailService public class CostProdDetailServiceImpl implements ICostProdDetailService
{ {
@Autowired @Autowired
@@ -93,4 +101,29 @@ public class CostProdDetailServiceImpl implements ICostProdDetailService
{ {
return costProdDetailMapper.deleteCostProdDetailByDetailId(detailId); return costProdDetailMapper.deleteCostProdDetailByDetailId(detailId);
} }
/**
* 批量保存生产成本明细(先删除再插入)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean batchSaveWithDelete(CostProdDetailBo bo)
{
if (!CollectionUtils.isEmpty(bo.getProdDetailList()))
{
if (!CollectionUtils.isEmpty(bo.getDetailIds()))
{
// 转成Long[]后删除
Long[] ids = bo.getDetailIds().toArray(new Long[0]);
costProdDetailMapper.deleteCostProdDetailByDetailIds(ids);
}
// 设置createTime后批量插入
List<CostProdDetail> list = bo.getProdDetailList().stream()
.peek(item -> item.setCreateTime(DateUtils.getNowDate()))
.collect(Collectors.toList());
return costProdDetailMapper.insertBatch(list) > 0;
}
return false;
}
} }

View File

@@ -1,6 +1,9 @@
package com.ruoyi.cost.service.impl; package com.ruoyi.cost.service.impl;
import java.util.List; import java.util.List;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -15,6 +18,7 @@ import com.ruoyi.cost.service.ICostProdMetricService;
* @date 2026-06-09 * @date 2026-06-09
*/ */
@Service @Service
@DataSource(DataSourceType.KLP)
public class CostProdMetricServiceImpl implements ICostProdMetricService public class CostProdMetricServiceImpl implements ICostProdMetricService
{ {
@Autowired @Autowired

View File

@@ -1,10 +1,20 @@
package com.ruoyi.cost.service.impl; package com.ruoyi.cost.service.impl;
import java.util.List; import java.util.List;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.cost.mapper.CostProdMetricMapper;
import com.ruoyi.cost.mapper.CostProdReportMapper; import com.ruoyi.cost.mapper.CostProdReportMapper;
import com.ruoyi.cost.domain.CostProdMetric;
import com.ruoyi.cost.domain.CostProdReport; import com.ruoyi.cost.domain.CostProdReport;
import com.ruoyi.cost.service.ICostProdReportService; import com.ruoyi.cost.service.ICostProdReportService;
@@ -15,11 +25,15 @@ import com.ruoyi.cost.service.ICostProdReportService;
* @date 2026-06-09 * @date 2026-06-09
*/ */
@Service @Service
@DataSource(DataSourceType.KLP)
public class CostProdReportServiceImpl implements ICostProdReportService public class CostProdReportServiceImpl implements ICostProdReportService
{ {
@Autowired @Autowired
private CostProdReportMapper costProdReportMapper; private CostProdReportMapper costProdReportMapper;
@Autowired
private CostProdMetricMapper costProdMetricMapper;
/** /**
* 查询生产月报 * 查询生产月报
* *
@@ -93,4 +107,79 @@ public class CostProdReportServiceImpl implements ICostProdReportService
{ {
return costProdReportMapper.deleteCostProdReportByReportId(reportId); return costProdReportMapper.deleteCostProdReportByReportId(reportId);
} }
/**
* 复制生产月报
* 明细列原样保留itemId不变指标列重新插入并更新config中的id引用
*/
@Override
public CostProdReport copyReport(Long sourceId, CostProdReport bo)
{
CostProdReport source = costProdReportMapper.selectCostProdReportByReportId(sourceId);
if (source == null)
{
throw new RuntimeException("源报表不存在");
}
// 创建新报表先插入以获取ID
CostProdReport newRp = new CostProdReport();
BeanUtils.copyProperties(source, newRp, "reportId", "colConfig");
newRp.setReportTitle(bo.getReportTitle() != null ? bo.getReportTitle() : source.getReportTitle() + "-副本");
if (bo.getReportDate() != null) {
newRp.setReportDate(bo.getReportDate());
}
if (bo.getLineType() != null) {
newRp.setLineType(bo.getLineType());
}
if (bo.getInputWeight() != null) {
newRp.setInputWeight(bo.getInputWeight());
}
if (bo.getOutputWeight() != null) {
newRp.setOutputWeight(bo.getOutputWeight());
}
if (bo.getRemark() != null) {
newRp.setRemark(bo.getRemark());
}
newRp.setCreateTime(DateUtils.getNowDate());
costProdReportMapper.insertCostProdReport(newRp);
Long newRid = newRp.getReportId();
// 处理colConfig为每个指标列重新插入metric记录更新id引用
String colConfig = source.getColConfig();
if (StringUtils.isNotBlank(colConfig))
{
JSONObject cfg = JSON.parseObject(colConfig);
JSONArray columns = cfg.getJSONArray("columns");
if (columns != null && columns.size() > 0)
{
for (int i = 0; i < columns.size(); i++)
{
JSONObject col = columns.getJSONObject(i);
if ("m".equals(col.getString("t")))
{
String idStr = col.getString("id");
Long oldMetricId = idStr != null ? Long.parseLong(idStr) : null;
if (oldMetricId != null)
{
CostProdMetric srcMetric = costProdMetricMapper.selectCostProdMetricByMetricId(oldMetricId);
if (srcMetric != null)
{
CostProdMetric newMetric = new CostProdMetric();
BeanUtils.copyProperties(srcMetric, newMetric, "metricId", "reportId");
newMetric.setReportId(newRid);
newMetric.setCreateTime(DateUtils.getNowDate());
costProdMetricMapper.insertCostProdMetric(newMetric);
col.put("id", String.valueOf(newMetric.getMetricId()));
}
}
}
}
newRp.setColConfig(cfg.toString());
newRp.setUpdateTime(DateUtils.getNowDate());
costProdReportMapper.updateCostProdReport(newRp);
}
}
return costProdReportMapper.selectCostProdReportByReportId(newRid);
}
} }

View File

@@ -107,4 +107,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{detailId} #{detailId}
</foreach> </foreach>
</delete> </delete>
<insert id="insertBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="detailId">
insert into cost_prod_detail (report_id, shift, detail_date, item_id, quantity, unit_price, amount, remark, del_flag, create_by, create_time, update_by, update_time) values
<foreach collection="list" item="item" separator=",">
(#{item.reportId}, #{item.shift}, #{item.detailDate}, #{item.itemId}, #{item.quantity}, #{item.unitPrice}, #{item.amount}, #{item.remark}, #{item.delFlag}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime})
</foreach>
</insert>
</mapper> </mapper>