package com.ruoyi.productionPlan.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.base.BaseException;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.bean.BeanUtils;
|
import com.ruoyi.common.utils.http.HttpUtils;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.framework.config.AliDingConfig;
|
import com.ruoyi.production.pojo.ProductMaterial;
|
import com.ruoyi.production.pojo.ProductMaterialSku;
|
import com.ruoyi.production.pojo.ProductOrder;
|
import com.ruoyi.production.service.ProductMaterialService;
|
import com.ruoyi.production.service.ProductMaterialSkuService;
|
import com.ruoyi.production.service.ProductOrderService;
|
import com.ruoyi.productionPlan.dto.ProductionPlanDto;
|
import com.ruoyi.productionPlan.dto.ProductionPlanImportDto;
|
import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
|
import com.ruoyi.productionPlan.enums.DataSourceTypeEnum;
|
import com.ruoyi.productionPlan.mapper.ProductOrderPlanMapper;
|
import com.ruoyi.productionPlan.mapper.ProductionPlanMapper;
|
import com.ruoyi.productionPlan.pojo.ProductOrderPlan;
|
import com.ruoyi.productionPlan.pojo.ProductionPlan;
|
import com.ruoyi.productionPlan.service.ProductionPlanService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import javax.servlet.http.HttpServletResponse;
|
import java.math.BigDecimal;
|
import java.nio.charset.StandardCharsets;
|
import java.time.*;
|
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeParseException;
|
import java.util.*;
|
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.stream.Collectors;
|
|
|
/**
|
* <br>
|
* 销售生产需求接口实现类
|
* </br>
|
*
|
* @author deslrey
|
* @version 1.0
|
* @since 2026/03/10 10:00
|
*/
|
|
@Slf4j
|
@Service
|
public class ProductionPlanServiceImpl extends ServiceImpl<ProductionPlanMapper, ProductionPlan> implements ProductionPlanService {
|
|
@Autowired
|
private AliDingConfig aliDingConfig;
|
|
@Autowired
|
private ProductionPlanMapper productionPlanMapper;
|
|
@Autowired
|
private ProductOrderService productOrderService;
|
|
@Autowired
|
private ProductOrderPlanMapper productOrderPlanMapper;
|
|
@Autowired
|
private ProductMaterialSkuService productMaterialSkuService;
|
|
@Autowired
|
private ProductMaterialService productMaterialService;
|
|
/**
|
* 同步锁,确保手动和定时任务不同时执行
|
*/
|
private final ReentrantLock syncLock = new ReentrantLock();
|
|
@Override
|
public IPage<ProductionPlanDto> listPage(Page page, ProductionPlanDto productionPlanDto) {
|
return productionPlanMapper.listPage(page, productionPlanDto);
|
}
|
|
/**
|
* 页面手动同步
|
*/
|
@Override
|
public void loadProdData() {
|
syncProdData(1);
|
}
|
|
/**
|
* 定时任务同步
|
*/
|
@Override
|
public void syncProdDataJob() {
|
syncProdData(2);
|
}
|
|
/**
|
* 合并生产计划
|
*/
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean combine(ProductionPlanDto productionPlanDto) {
|
if (productionPlanDto.getIds() == null || productionPlanDto.getIds().isEmpty()) {
|
return false;
|
}
|
|
// 查询主生产计划
|
List<ProductionPlanDto> plans = productionPlanMapper.selectWithMaterialByIds(productionPlanDto.getIds());
|
|
// 校验是否存在不同的产品名称
|
String firstProductName = plans.get(0).getProductName();
|
if (plans.stream().anyMatch(p -> !p.getProductName().equals(firstProductName))) {
|
throw new BaseException("合并失败,存在不同的产品名称");
|
}
|
|
// 校验是否存在不同的产品规格
|
String firstProductSpec = plans.get(0).getSpecification();
|
if (plans.stream().anyMatch(p -> !p.getSpecification().equals(firstProductSpec))) {
|
throw new BaseException("合并失败,存在不同的产品规格");
|
}
|
|
// 叠加剩余方数
|
BigDecimal totalRemainingVolume = plans.stream()
|
.map(ProductionPlan::getRemainingVolume)
|
.filter(v -> v != null)
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
// 判断下发数量是否大于等于剩余方数
|
if (productionPlanDto.getTotalAssignedQuantity().compareTo(totalRemainingVolume) > 0) {
|
throw new BaseException("操作失败,下发数量不能大于剩余方数");
|
}
|
|
// 创建生产订单
|
ProductOrder productOrder = new ProductOrder();
|
productOrder.setQuantity(productionPlanDto.getTotalAssignedQuantity());
|
productOrder.setPlanCompleteTime(productionPlanDto.getPlanCompleteTime());
|
productOrderService.addProductOrder(productOrder);
|
|
// 根据下发数量,从第一个生产计划开始分配方数
|
BigDecimal assignedVolume = BigDecimal.ZERO;
|
for (ProductionPlan plan : plans) {
|
BigDecimal volume = plan.getVolume();
|
if (volume == null) {
|
continue;
|
}
|
// 计算剩余方数
|
BigDecimal remainingVolume = plan.getRemainingVolume();
|
if (remainingVolume.compareTo(BigDecimal.ZERO) <= 0) {
|
continue;
|
}
|
|
ProductOrderPlan productOrderPlan = new ProductOrderPlan();
|
productOrderPlan.setProductOrderId(productOrder.getId());
|
productOrderPlan.setProductionPlanId(plan.getId());
|
|
if (assignedVolume.add(remainingVolume).compareTo(productionPlanDto.getTotalAssignedQuantity()) >= 0) {
|
// 最后一个计划,分配剩余方数
|
BigDecimal lastRemainingVolume = productionPlanDto.getTotalAssignedQuantity().subtract(assignedVolume);
|
plan.setStatus(1);
|
plan.setAssignedQuantity(plan.getAssignedQuantity().add(lastRemainingVolume));
|
productOrderPlan.setAssignedQuantity(lastRemainingVolume);
|
productionPlanMapper.updateById(plan);
|
productOrderPlanMapper.insert(productOrderPlan);
|
break;
|
}
|
|
// 分配当前计划方数
|
plan.setStatus(1);
|
plan.setAssignedQuantity(plan.getAssignedQuantity().add(remainingVolume));
|
productOrderPlan.setAssignedQuantity(remainingVolume);
|
// 更新生产计划
|
productionPlanMapper.updateById(plan);
|
// 创建关联关系
|
productOrderPlanMapper.insert(productOrderPlan);
|
assignedVolume = assignedVolume.add(remainingVolume);
|
}
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean add(ProductionPlanDto productionPlanDto) {
|
productionPlanDto.setDataSourceType(DataSourceTypeEnum.MANUAL.getCode());
|
productionPlanMapper.insert(productionPlanDto);
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean update(ProductionPlanDto productionPlanDto) {
|
// 已下发状态,不能编辑
|
if (productionPlanDto.getStatus() == 1) {
|
throw new BaseException("已下发状态,不能编辑");
|
}
|
// 查询是否有关联订单
|
boolean hasProductOrderPlan = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductionPlanId, productionPlanDto.getId())).stream().anyMatch(p -> p.getProductOrderId() != null);
|
if (hasProductOrderPlan) {
|
// 如果关联,方数只能递增
|
ProductionPlan currentPlan = productionPlanMapper.selectById(productionPlanDto.getId());
|
if (productionPlanDto.getVolume().compareTo(currentPlan.getVolume()) < 0) {
|
throw new BaseException("方数不能递减");
|
}
|
}
|
|
return productionPlanMapper.updateById(productionPlanDto) > 0;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean delete(List<Long> ids) {
|
// 如果存在已下发的计划,则不能删除
|
if (productionPlanMapper.selectList(Wrappers.<ProductionPlan>lambdaQuery().in(ProductionPlan::getId, ids).eq(ProductionPlan::getStatus, 1)).stream().anyMatch(p -> p.getStatus() == 1)) {
|
throw new BaseException("删除失败,存在已下发的计划");
|
}
|
// 如果有关联订单,则不能删除
|
if (productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductionPlanId, ids)).stream().anyMatch(p -> p.getProductOrderId() != null)) {
|
throw new BaseException("删除失败,存在关联订单");
|
}
|
|
return productionPlanMapper.deleteBatchIds(ids) > 0;
|
}
|
|
/**
|
* 同步数据
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public void syncProdData(Integer dataSyncType) {
|
if (!syncLock.tryLock()) {
|
log.warn("同步正在进行中,本次 {} 同步请求被跳过", dataSyncType == 1 ? "手动同步" : "定时任务同步");
|
return;
|
}
|
|
try {
|
// 获取 AccessToken
|
String accessToken = getAccessToken();
|
if (StringUtils.isEmpty(accessToken)) {
|
return;
|
}
|
|
// 获取本地最后同步时间
|
LocalDateTime lastSyncTime = getLastSyncTime();
|
log.info("开始增量同步,本地最后修改时间: {}", lastSyncTime);
|
|
int pageNumber = 1;
|
int pageSize = 50;
|
boolean hasMore = true;
|
int totalSynced = 0;
|
|
while (hasMore) {
|
// 查询参数
|
JSONObject searchParam = buildSearchParam(lastSyncTime, pageNumber, pageSize);
|
|
// 调用宜搭接口拉取数据
|
String dataRes = HttpUtils.sendPostJson(
|
aliDingConfig.getSearchFormDataUrl(),
|
searchParam.toJSONString(),
|
StandardCharsets.UTF_8.name(),
|
null,
|
accessToken
|
);
|
|
if (StringUtils.isEmpty(dataRes)) {
|
log.warn("第 {} 页拉取数据为空", pageNumber);
|
break;
|
}
|
|
JSONObject resultObj = JSON.parseObject(dataRes);
|
JSONArray dataArr = resultObj.getJSONArray("data");
|
Integer totalCount = resultObj.getInteger("totalCount");
|
|
if (dataArr == null || dataArr.isEmpty()) {
|
log.info("没有更多新数据需要同步");
|
break;
|
}
|
|
// 解析并保存数据
|
List<ProductionPlan> list = parseProductionPlans(dataArr, dataSyncType, totalCount);
|
if (!list.isEmpty()) {
|
// 处理更新或新增
|
int affected = processSaveOrUpdate(list);
|
totalSynced += affected;
|
}
|
|
// 判断是否还有下一页
|
hasMore = (pageNumber * pageSize) < totalCount;
|
pageNumber++;
|
|
log.info("正在同步第 {} 页,当前已同步 {}/{}", pageNumber - 1, totalSynced, totalCount);
|
}
|
|
log.info("数据同步完成,共同步 {} 条数据", totalSynced);
|
} catch (Exception e) {
|
log.error("同步生产计划异常", e);
|
} finally {
|
// 释放锁
|
syncLock.unlock();
|
}
|
}
|
|
private String getAccessToken() {
|
String params = "appkey=" + aliDingConfig.getAppKey()
|
+ "&appsecret=" + aliDingConfig.getAppSecret();
|
String tokenRes = HttpUtils.sendGet(aliDingConfig.getAccessTokenUrl(), params);
|
JSONObject tokenObj = JSON.parseObject(tokenRes);
|
String accessToken = tokenObj.getString("access_token");
|
if (StringUtils.isEmpty(accessToken)) {
|
log.error("获取钉钉AccessToken失败: {}", tokenRes);
|
}
|
return accessToken;
|
}
|
|
private LocalDateTime getLastSyncTime() {
|
// 查询本地数据库中 formModifiedTime 最大的记录
|
LambdaQueryWrapper<ProductionPlan> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.orderByDesc(ProductionPlan::getFormModifiedTime).last("LIMIT 1");
|
ProductionPlan lastRecord = this.getOne(queryWrapper);
|
return lastRecord != null ? lastRecord.getFormModifiedTime() : null;
|
}
|
|
private JSONObject buildSearchParam(LocalDateTime lastSyncTime, int pageNumber, int pageSize) {
|
JSONObject searchParam = new JSONObject();
|
searchParam.put("appType", aliDingConfig.getAppType());
|
searchParam.put("systemToken", aliDingConfig.getSystemToken());
|
searchParam.put("userId", aliDingConfig.getUserId());
|
searchParam.put("formUuid", aliDingConfig.getProducePlanFormUuid());
|
searchParam.put("currentPage", pageNumber);
|
searchParam.put("pageSize", pageSize);
|
|
JSONArray searchConditions = new JSONArray();
|
JSONObject condition = new JSONObject();
|
condition.put("key", "processApprovedResult");
|
JSONArray valueArray = new JSONArray();
|
valueArray.add("agree");
|
|
condition.put("value", valueArray);
|
condition.put("type", "ARRAY");
|
condition.put("operator", "in");
|
condition.put("componentName", "SelectField");
|
searchConditions.add(condition);
|
|
searchParam.put("searchFieldJson", searchConditions.toJSONString());
|
|
// 默认按修改时间升序排序,确保分页拉取数据的连续性
|
// "+" 表示升序,"gmt_modified" 是官方内置字段
|
searchParam.put("orderConfigJson", "{\"gmt_modified\":\"+\"}");
|
|
// 设置修改时间筛选区间 (格式必须为yyyy-MM-dd HH:mm:ss)
|
if (lastSyncTime != null) {
|
// 起始时间:上次同步到的最后一条数据的修改时间
|
String startTime = lastSyncTime.plusSeconds(1).atZone(ZoneId.systemDefault())
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
searchParam.put("modifiedFromTimeGMT", startTime);
|
}
|
|
// 截止时间:当前时间,确保获取最新的已修改/已新增数据
|
String endTime = LocalDateTime.now().atZone(ZoneId.systemDefault())
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
searchParam.put("modifiedToTimeGMT", endTime);
|
|
return searchParam;
|
}
|
|
private List<ProductionPlan> parseProductionPlans(JSONArray dataArr, Integer dataSyncType, Integer totalCount) {
|
List<ProductionPlan> list = new ArrayList<>();
|
LocalDateTime now = LocalDateTime.now();
|
|
for (int i = 0; i < dataArr.size(); i++) {
|
JSONObject item = dataArr.getJSONObject(i);
|
String formInstanceId = item.getString("formInstanceId");
|
String serialNo = item.getString("serialNo");
|
|
JSONObject originator = item.getJSONObject("originator");
|
String originatorName = originator != null && originator.containsKey("userName")
|
? originator.getJSONObject("userName").getString("nameInChinese") : "未知";
|
|
JSONObject formData = item.getJSONObject("formData");
|
JSONArray tableArr = formData.getJSONArray("tableField_l7fytfcn");
|
if (tableArr == null || tableArr.isEmpty()) {
|
continue;
|
}
|
|
for (int j = 0; j < tableArr.size(); j++) {
|
JSONObject row = tableArr.getJSONObject(j);
|
ProductionPlan plan = new ProductionPlan();
|
|
plan.setFormInstanceId(formInstanceId);
|
plan.setSerialNo(serialNo);
|
plan.setApplyNo(formData.getString("textField_l7fytfco"));
|
plan.setCustomerName(formData.getString("textField_lbkozohg"));
|
|
String materialCode = row.getString("textField_l9xo62q5");
|
// 根据物料编码查询物料信息表,关联物料ID
|
if (StringUtils.isNotEmpty(materialCode)) {
|
LambdaQueryWrapper<ProductMaterialSku> skuQueryWrapper = new LambdaQueryWrapper<>();
|
skuQueryWrapper.eq(ProductMaterialSku::getMaterialCode, materialCode);
|
ProductMaterialSku sku = productMaterialSkuService.getOne(skuQueryWrapper);
|
if (sku != null) {
|
plan.setProductMaterialSkuId(sku.getId());
|
}
|
}
|
|
plan.setLength(row.getInteger("numberField_lb7lgatg_value"));
|
plan.setWidth(row.getInteger("numberField_lb7lgath_value"));
|
plan.setHeight(row.getInteger("numberField_lb7lgati_value"));
|
plan.setQuantity(row.getInteger("numberField_lb7lgatj_value"));
|
plan.setVolume(row.getBigDecimal("numberField_l7fytfd3_value"));
|
plan.setStrength(row.getString("radioField_m9urarr2_id"));
|
|
JSONArray dateArr = row.getJSONArray("cascadeDateField_lfxqqluw");
|
if (dateArr != null && dateArr.size() == 2) {
|
try {
|
long start = Long.parseLong(dateArr.getString(0));
|
long end = Long.parseLong(dateArr.getString(1));
|
|
Date startDate = Date.from(Instant.ofEpochMilli(start)
|
.atZone(ZoneId.systemDefault())
|
.toLocalDate()
|
.atStartOfDay(ZoneId.systemDefault())
|
.toInstant());
|
Date endDate = Date.from(Instant.ofEpochMilli(end)
|
.atZone(ZoneId.systemDefault())
|
.toLocalDate()
|
.atStartOfDay(ZoneId.systemDefault())
|
.toInstant());
|
|
plan.setStartDate(startDate);
|
plan.setEndDate(endDate);
|
} catch (Exception e) {
|
log.warn("解析日期失败: {}", dateArr);
|
}
|
}
|
|
plan.setSubmitter(originatorName);
|
plan.setSubmitOrg("宁夏中创绿能实业集团有限公司");
|
plan.setRemarkOne(formData.getString("textareaField_l7fytfcy"));
|
plan.setRemarkTwo(formData.getString("textField_l7fytfcx"));
|
plan.setCreatorName(originatorName);
|
|
JSONObject modifyUser = item.getJSONObject("modifyUser");
|
if (modifyUser != null && modifyUser.containsKey("userName")) {
|
plan.setModifierName(modifyUser.getJSONObject("userName").getString("nameInChinese"));
|
}
|
|
plan.setFormCreatedTime(parseUtcTime(item.getString("createdTimeGMT")));
|
plan.setFormModifiedTime(parseUtcTime(item.getString("modifiedTimeGMT")));
|
plan.setDataSourceType(DataSourceTypeEnum.DING_TALK.getCode());
|
plan.setCreateTime(now);
|
plan.setUpdateTime(now);
|
plan.setTotalCount(totalCount);
|
|
list.add(plan);
|
}
|
}
|
return list;
|
}
|
|
private int processSaveOrUpdate(List<ProductionPlan> list) {
|
if (list == null || list.isEmpty()) {
|
return 0;
|
}
|
int affected = 0;
|
|
// 去重 formInstanceId
|
Set<String> formIds = list.stream()
|
.map(ProductionPlan::getFormInstanceId)
|
.collect(Collectors.toSet());
|
|
// 查询数据库已有数据
|
List<ProductionPlan> existList = this.list(new LambdaQueryWrapper<ProductionPlan>().in(ProductionPlan::getFormInstanceId, formIds));
|
|
// Map (formInstanceId + materialCode)
|
Map<String, ProductionPlan> existMap = new HashMap<>();
|
for (ProductionPlan p : existList) {
|
String key = p.getFormInstanceId() + "_" + p.getProductMaterialSkuId();
|
existMap.put(key, p);
|
}
|
|
// 遍历同步数据
|
for (ProductionPlan plan : list) {
|
String key = plan.getFormInstanceId() + "_" + plan.getProductMaterialSkuId();
|
ProductionPlan exist = existMap.get(key);
|
if (exist == null) {
|
// 新增
|
this.save(plan);
|
affected++;
|
log.info("新增数据 formInstanceId={}, materialCode={}", plan.getFormInstanceId(), plan.getProductMaterialSkuId());
|
} else {
|
// 判断是否需要更新
|
if (exist.getFormModifiedTime() == null || !exist.getFormModifiedTime().equals(plan.getFormModifiedTime())) {
|
plan.setId(exist.getId());
|
plan.setCreateTime(exist.getCreateTime());
|
this.updateById(plan);
|
affected++;
|
log.info("更新数据 formInstanceId={}, materialCode={}", plan.getFormInstanceId(), plan.getProductMaterialSkuId());
|
}
|
}
|
}
|
return affected;
|
}
|
|
private LocalDateTime parseUtcTime(String utcString) {
|
if (StringUtils.isEmpty(utcString)) {
|
return null;
|
}
|
try {
|
OffsetDateTime odt = OffsetDateTime.parse(utcString);
|
return odt.toLocalDateTime();
|
} catch (DateTimeParseException ex) {
|
log.warn("解析时间 {} 失败: {}", utcString, ex.getMessage());
|
return null;
|
}
|
}
|
|
@Override
|
public List<ProductionPlanSummaryDto> summaryByProductType(ProductionPlanSummaryDto query) {
|
return baseMapper.selectSummaryByProductType(query);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void importProdData(MultipartFile file) {
|
if (file == null || file.isEmpty()) {
|
throw new ServiceException("导入数据不能为空");
|
}
|
ExcelUtil<ProductionPlanImportDto> excelUtil = new ExcelUtil<>(ProductionPlanImportDto.class);
|
List<ProductionPlanImportDto> list;
|
try {
|
list = excelUtil.importExcel(file.getInputStream());
|
} catch (Exception e) {
|
log.error("生产需求Excel导入失败", e);
|
throw new ServiceException("Excel解析失败");
|
}
|
|
if (list == null || list.isEmpty()) {
|
throw new ServiceException("Excel没有数据");
|
}
|
List<ProductionPlan> entityList = new ArrayList<>(list.size());
|
ProductionPlan entity;
|
for (ProductionPlanImportDto dto : list) {
|
entity = new ProductionPlan();
|
BeanUtils.copyProperties(dto, entity);
|
entity.setAssignedQuantity(BigDecimal.ZERO);
|
entity.setCreateTime(LocalDateTime.now());
|
entity.setUpdateTime(LocalDateTime.now());
|
entity.setDataSourceType(DataSourceTypeEnum.DING_TALK.getCode());
|
|
// 根据物料编码填充关联ID
|
if (StringUtils.isNotEmpty(dto.getMaterialCode())) {
|
LambdaQueryWrapper<ProductMaterialSku> skuQueryWrapper = new LambdaQueryWrapper<>();
|
skuQueryWrapper.eq(ProductMaterialSku::getMaterialCode, dto.getMaterialCode());
|
ProductMaterialSku sku = productMaterialSkuService.getOne(skuQueryWrapper);
|
if (sku != null) {
|
entity.setProductMaterialSkuId(sku.getId());
|
}
|
}
|
|
entityList.add(entity);
|
}
|
this.saveBatch(entityList);
|
}
|
|
@Override
|
public void exportProdData(HttpServletResponse response, List<Long> ids) {
|
List<ProductionPlan> list;
|
if (ids != null && !ids.isEmpty()) {
|
list = baseMapper.selectBatchIds(ids);
|
} else {
|
list = baseMapper.selectList(null);
|
}
|
|
List<ProductionPlanImportDto> exportList = new ArrayList<>();
|
for (ProductionPlan entity : list) {
|
ProductionPlanImportDto dto = new ProductionPlanImportDto();
|
BeanUtils.copyProperties(entity, dto);
|
exportList.add(dto);
|
}
|
ExcelUtil<ProductionPlanImportDto> util = new ExcelUtil<>(ProductionPlanImportDto.class);
|
util.exportExcel(response, exportList, "销售生产需求数据");
|
}
|
}
|