feat(aps): 新增排产单明细合并功能及优化界面展示

- 在排产单明细表格中添加多选合并功能
- 实现排产单明细合并对话框及合并逻辑
- 优化排产单明细表格列配置和表单布局
- 添加合并校验和接收产需单API接口
- 重构订单绑定解绑逻辑提升用户体验
- 添加ScheduleDetailCoilBind组件引入
This commit is contained in:
2026-06-29 16:07:29 +08:00
parent da01bfaa48
commit ee376f922f
19 changed files with 1547 additions and 154 deletions

View File

@@ -18,8 +18,11 @@ import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.flow.domain.vo.SchProdScheduleItemVo;
import com.klp.flow.domain.vo.SchProdScheduleItemMergeValidateVo;
import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.flow.service.ISchProdScheduleItemService;
import com.klp.common.core.page.TableDataInfo;
@@ -117,4 +120,22 @@ public class SchProdScheduleItemController extends BaseController {
public R<Void> merge(@Validated @RequestBody SchProdScheduleItemMergeBo mergeBo) {
return toAjax(iSchProdScheduleItemService.mergeByBo(mergeBo));
}
/**
* 接收产需单:从 sch_prod_schedule + sch_prod_schedule_detail 全字段复制到 sch_prod_schedule_item
*/
@Log(title = "排产单主加明细可合并", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/receive")
public R<Void> receive(@Validated @RequestBody SchProdScheduleItemReceiveBo receiveBo) {
return toAjax(iSchProdScheduleItemService.receiveByBo(receiveBo));
}
/**
* 合并校验:检查待合并记录来源产需单的 header 字段是否一致
*/
@PostMapping("/mergeValidate")
public R<SchProdScheduleItemMergeValidateVo> mergeValidate(@Validated @RequestBody SchProdScheduleItemMergeValidateBo validateBo) {
return R.ok(iSchProdScheduleItemService.validateMerge(validateBo));
}
}

View File

@@ -128,13 +128,9 @@ public class SchProdScheduleItem extends BaseEntity {
*/
private String returnReason;
/**
* 排产单主表ID
* 排产明细关联主表ID逗号分隔未合并存单值合并后存多个
*/
private String scheduleIds;
/**
* 来源销售订单明细ID溯源原始订单规格
*/
private String orderDetailIds;
private String scheduleDetailIds;
/**
* 规格 例1.0X1250
*/

View File

@@ -154,14 +154,9 @@ public class SchProdScheduleItemBo extends BaseEntity {
private String returnReason;
/**
* 排产单主表ID
* 排产明细关联主表ID逗号分隔未合并存单值合并后存多个
*/
private String scheduleIds;
/**
* 来源销售订单明细ID溯源原始订单规格
*/
private String orderDetailIds;
private String scheduleDetailIds;
/**
* 规格 例1.0X1250

View File

@@ -0,0 +1,22 @@
package com.klp.flow.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 排产单合并校验请求对象
*
* @author klp
* @date 2026-06-29
*/
@Data
public class SchProdScheduleItemMergeValidateBo {
/**
* 待合并记录ID列表
*/
@NotEmpty(message = "待合并记录ID不能为空")
private List<Long> ids;
}

View File

@@ -0,0 +1,21 @@
package com.klp.flow.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 产需单接收请求对象
*
* @author klp
* @date 2026-06-29
*/
@Data
public class SchProdScheduleItemReceiveBo {
/**
* 排产单主表ID产需单ID
*/
@NotNull(message = "排产单主表ID不能为空")
private Long scheduleId;
}

View File

@@ -0,0 +1,115 @@
package com.klp.flow.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* 排产单合并校验视图对象
*
* @author klp
* @date 2026-06-29
*/
@Data
public class SchProdScheduleItemMergeValidateVo {
/** 是否所有 header 字段一致 */
private Boolean consistent;
/** 有差异的字段列表 */
private List<FieldDiff> diffs;
/** 被合并记录快照 */
private List<ItemInfo> items;
/** 汇总信息 */
private MergedSummary summary;
/**
* 字段差异
*/
@Data
public static class FieldDiff {
/** 字段名Java属性名 */
private String fieldName;
/** 字段中文标签 */
private String fieldLabel;
/** scheduleId → 值 */
private Map<String, Object> values;
}
/**
* 被合并记录快照
*/
@Data
public static class ItemInfo {
/** sch_prod_schedule_item 主键 */
private Long itemId;
/** 第一个源 schedule_id从 scheduleIds 解析) */
private Long sourceScheduleId;
/** 排产单号 */
private String scheduleNo;
/** 订货单位 */
private String customerName;
/** 品名 */
private String productType;
/** 规格 */
private String spec;
/** 材质 */
private String material;
/** 排产吨数 */
private BigDecimal scheduleWeight;
/** 来源排产明细ID串 */
private String scheduleDetailIds;
/** 业务员 */
private String businessUser;
/** 联系电话 */
private String businessPhone;
/** 交货期(天) */
private Long deliveryCycle;
/** 产品用途 */
private String usePurpose;
/** 厚度公差 */
private String thicknessTolerance;
/** 宽度公差 */
private String widthTolerance;
/** 表面质量 */
private String surfaceQuality;
/** 表面处理 */
private String surfaceTreatment;
/** 内径尺寸 */
private String innerDiameter;
/** 外径要求 */
private String outerDiameter;
/** 包装要求 */
private String packReq;
/** 切边要求 */
private String cutEdgeReq;
/** 单件重量 */
private String singleCoilWeight;
/** 交货重量偏差 */
private String weightDeviation;
/** 其他技术要求 */
private String otherTechReq;
/** 付款情况说明 */
private String paymentDesc;
/** 关联销售合同号 */
private String relContractNo;
/** 排产总计划吨数 */
private BigDecimal totalPlanWeight;
/** 订单日期 */
private java.util.Date orderDate;
}
/**
* 合并汇总
*/
@Data
public static class MergedSummary {
/** 明细条数 */
private int itemCount;
/** 合计排产吨数 */
private BigDecimal totalScheduleWeight;
}
}

View File

@@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
/**
@@ -40,6 +41,8 @@ public class SchProdScheduleItemVo {
*/
@ExcelProperty(value = "生产日期", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "和=合同号组成业务关联键")
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date prodDate;
/**
@@ -181,17 +184,10 @@ public class SchProdScheduleItemVo {
private String returnReason;
/**
* 排产单主表ID
* 排产明细关联主表ID逗号分隔
*/
@ExcelProperty(value = "排产主表ID")
private String scheduleIds;
/**
* 来源销售订单明细ID溯源原始订单规格
*/
@ExcelProperty(value = "来源销售订单明细ID", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "溯=源原始订单规格")
private String orderDetailIds;
@ExcelProperty(value = "排产明细关联主表ID")
private String scheduleDetailIds;
/**
* 规格 例1.0X1250

View File

@@ -2,8 +2,11 @@ package com.klp.flow.service;
import com.klp.flow.domain.SchProdScheduleItem;
import com.klp.flow.domain.vo.SchProdScheduleItemVo;
import com.klp.flow.domain.vo.SchProdScheduleItemMergeValidateVo;
import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
@@ -57,4 +60,14 @@ public interface ISchProdScheduleItemService {
* 合并多条排产单主加明细可合并记录:先删除被合并的记录,再插入合并后的新记录
*/
Boolean mergeByBo(SchProdScheduleItemMergeBo mergeBo);
/**
* 接收产需单:从 sch_prod_schedule + sch_prod_schedule_detail 全字段复制到 sch_prod_schedule_item
*/
Boolean receiveByBo(SchProdScheduleItemReceiveBo receiveBo);
/**
* 合并校验:检查待合并记录来源产需单的 header 字段是否一致
*/
SchProdScheduleItemMergeValidateVo validateMerge(SchProdScheduleItemMergeValidateBo validateBo);
}

View File

@@ -11,16 +11,27 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.flow.domain.bo.SchProdScheduleItemBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeBo;
import com.klp.flow.domain.bo.SchProdScheduleItemReceiveBo;
import com.klp.flow.domain.bo.SchProdScheduleItemMergeValidateBo;
import com.klp.flow.domain.vo.SchProdScheduleItemVo;
import com.klp.flow.domain.vo.SchProdScheduleItemMergeValidateVo;
import com.klp.flow.domain.SchProdScheduleItem;
import com.klp.flow.domain.SchProdSchedule;
import com.klp.flow.domain.SchProdScheduleDetail;
import com.klp.flow.mapper.SchProdScheduleItemMapper;
import com.klp.flow.mapper.SchProdScheduleMapper;
import com.klp.flow.mapper.SchProdScheduleDetailMapper;
import com.klp.flow.service.ISchProdScheduleItemService;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 排产单主加明细可合并Service业务层处理
@@ -33,6 +44,8 @@ import java.util.Collection;
public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemService {
private final SchProdScheduleItemMapper baseMapper;
private final SchProdScheduleMapper schProdScheduleMapper;
private final SchProdScheduleDetailMapper schProdScheduleDetailMapper;
/**
* 查询排产单主加明细可合并
@@ -89,8 +102,7 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
lqw.eq(StringUtils.isNotBlank(bo.getOtherTechReq()), SchProdScheduleItem::getOtherTechReq, bo.getOtherTechReq());
lqw.eq(StringUtils.isNotBlank(bo.getPaymentDesc()), SchProdScheduleItem::getPaymentDesc, bo.getPaymentDesc());
lqw.eq(StringUtils.isNotBlank(bo.getReturnReason()), SchProdScheduleItem::getReturnReason, bo.getReturnReason());
lqw.eq(StringUtils.isNotBlank(bo.getScheduleIds()), SchProdScheduleItem::getScheduleIds, bo.getScheduleIds());
lqw.eq(StringUtils.isNotBlank(bo.getOrderDetailIds()), SchProdScheduleItem::getOrderDetailIds, bo.getOrderDetailIds());
lqw.eq(StringUtils.isNotBlank(bo.getScheduleDetailIds()), SchProdScheduleItem::getScheduleDetailIds, bo.getScheduleDetailIds());
lqw.eq(StringUtils.isNotBlank(bo.getSpec()), SchProdScheduleItem::getSpec, bo.getSpec());
lqw.eq(StringUtils.isNotBlank(bo.getMaterial()), SchProdScheduleItem::getMaterial, bo.getMaterial());
lqw.eq(bo.getScheduleWeight() != null, SchProdScheduleItem::getScheduleWeight, bo.getScheduleWeight());
@@ -179,4 +191,287 @@ public class SchProdScheduleItemServiceImpl implements ISchProdScheduleItemServi
}
return flag;
}
/**
* 接收产需单:从 sch_prod_schedule + sch_prod_schedule_detail 全字段复制到 sch_prod_schedule_item
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean receiveByBo(SchProdScheduleItemReceiveBo receiveBo) {
Long scheduleId = receiveBo.getScheduleId();
// 1. 查询产需单主表
SchProdSchedule header = schProdScheduleMapper.selectById(scheduleId);
if (header == null) {
throw new RuntimeException("产需单不存在scheduleId=" + scheduleId);
}
// 2. 查询产需单明细列表
List<SchProdScheduleDetail> details = schProdScheduleDetailMapper.selectList(
Wrappers.<SchProdScheduleDetail>lambdaQuery()
.eq(SchProdScheduleDetail::getScheduleId, scheduleId)
);
if (details == null || details.isEmpty()) {
throw new RuntimeException("产需单无明细数据scheduleId=" + scheduleId);
}
// 3. 遍历每条 detail构建 SchProdScheduleItem 列表
List<SchProdScheduleItem> addList = new ArrayList<>(details.size());
for (SchProdScheduleDetail detail : details) {
SchProdScheduleItem item = new SchProdScheduleItem();
// 从 header 复制所有字段
item.setScheduleNo(header.getScheduleNo());
item.setProdDate(header.getProdDate());
item.setScheduleStatus(2L); // 已下达
item.setTotalPlanWeight(header.getTotalPlanWeight());
item.setRelContractNo(header.getRelContractNo());
item.setBusinessUser(header.getBusinessUser());
item.setBusinessPhone(header.getBusinessPhone());
item.setOrderDate(header.getOrderDate());
item.setCustomerName(header.getCustomerName());
item.setDeliveryCycle(header.getDeliveryCycle());
item.setUsePurpose(header.getUsePurpose());
item.setProductType(header.getProductType());
item.setThicknessTolerance(header.getThicknessTolerance());
item.setWidthTolerance(header.getWidthTolerance());
item.setSurfaceQuality(header.getSurfaceQuality());
item.setSurfaceTreatment(header.getSurfaceTreatment());
item.setInnerDiameter(header.getInnerDiameter());
item.setOuterDiameter(header.getOuterDiameter());
item.setPackReq(header.getPackReq());
item.setCutEdgeReq(header.getCutEdgeReq());
item.setSingleCoilWeight(header.getSingleCoilWeight());
item.setWeightDeviation(header.getWeightDeviation());
item.setOtherTechReq(header.getOtherTechReq());
item.setPaymentDesc(header.getPaymentDesc());
item.setRemark(header.getRemark());
// 不复制 returnReason
// 从 detail 复制
item.setSpec(detail.getSpec());
item.setMaterial(detail.getMaterial());
item.setScheduleWeight(detail.getScheduleWeight());
item.setProductItem(detail.getProductType());
item.setRowRemark(detail.getRemark());
// 来源追溯未合并各存明细ID
item.setScheduleDetailIds(String.valueOf(detail.getScheduleDetailId()));
validEntityBeforeSave(item);
addList.add(item);
}
// 4. 批量插入
baseMapper.insertBatch(addList);
// 5. 更新产需单状态为 2已下达
header.setScheduleStatus(2L);
schProdScheduleMapper.updateById(header);
return true;
}
/**
* 合并校验:检查待合并记录来源产需单的 header 字段是否一致
*/
@Override
public SchProdScheduleItemMergeValidateVo validateMerge(SchProdScheduleItemMergeValidateBo validateBo) {
List<Long> ids = validateBo.getIds();
// 1. 查询所有待合并的 sch_prod_schedule_item 记录
List<SchProdScheduleItem> items = baseMapper.selectBatchIds(ids);
if (items == null || items.size() < 2) {
throw new RuntimeException("待合并记录不足至少需要2条");
}
// 2. 解析每条记录的 scheduleIds逗号分隔取第一个作为源 schedule_id
// 查询所有源 sch_prod_schedule 记录
List<Long> sourceScheduleIds = new ArrayList<>();
for (SchProdScheduleItem item : items) {
String sids = item.getScheduleDetailIds();
if (sids != null && !sids.isEmpty()) {
String[] parts = sids.split(",");
if (parts.length > 0) {
String firstId = parts[0].trim();
if (!firstId.isEmpty()) {
sourceScheduleIds.add(Long.valueOf(firstId));
}
}
}
}
List<Long> distinctSourceIds = sourceScheduleIds.stream().distinct().collect(Collectors.toList());
List<SchProdSchedule> sourceHeaders = schProdScheduleMapper.selectBatchIds(distinctSourceIds);
Map<Long, SchProdSchedule> headerMap = new LinkedHashMap<>();
for (SchProdSchedule h : sourceHeaders) {
headerMap.put(h.getScheduleId(), h);
}
// 3. 定义要比较的字段列表(字段名 → 中文标签)
Map<String, String> compareFields = new LinkedHashMap<>();
compareFields.put("scheduleNo", "排产单号");
compareFields.put("customerName", "订货单位");
compareFields.put("businessUser", "业务员");
compareFields.put("businessPhone", "联系电话");
compareFields.put("deliveryCycle", "交货期(天)");
compareFields.put("usePurpose", "产品用途");
compareFields.put("productType", "品名");
compareFields.put("thicknessTolerance", "厚度公差");
compareFields.put("widthTolerance", "宽度公差");
compareFields.put("surfaceQuality", "表面质量");
compareFields.put("surfaceTreatment", "表面处理");
compareFields.put("innerDiameter", "内径尺寸");
compareFields.put("outerDiameter", "外径要求");
compareFields.put("packReq", "包装要求");
compareFields.put("cutEdgeReq", "切边要求");
compareFields.put("singleCoilWeight", "单件重量");
compareFields.put("weightDeviation", "交货重量偏差");
compareFields.put("otherTechReq", "其他技术要求");
compareFields.put("paymentDesc", "付款情况说明");
compareFields.put("relContractNo", "关联销售合同号");
compareFields.put("totalPlanWeight", "排产总计划吨数");
compareFields.put("orderDate", "订单日期");
// 4. 逐一比较字段
List<SchProdScheduleItemMergeValidateVo.FieldDiff> diffs = new ArrayList<>();
boolean allConsistent = true;
for (Map.Entry<String, String> entry : compareFields.entrySet()) {
String fieldName = entry.getKey();
String fieldLabel = entry.getValue();
Map<String, Object> values = new LinkedHashMap<>();
for (SchProdSchedule header : sourceHeaders) {
Long headerId = header.getScheduleId();
Object val = getFieldValue(header, fieldName);
values.put(String.valueOf(headerId), val);
}
// 判断所有值是否一致
boolean same = values.values().stream().distinct().count() <= 1;
if (!same) {
allConsistent = false;
SchProdScheduleItemMergeValidateVo.FieldDiff diff = new SchProdScheduleItemMergeValidateVo.FieldDiff();
diff.setFieldName(fieldName);
diff.setFieldLabel(fieldLabel);
diff.setValues(values);
diffs.add(diff);
}
}
// 4.1 比对明细级字段spec, material, productItem—— 这些字段来自 item 自身,不来自 header
Map<String, String> itemCompareFields = new LinkedHashMap<>();
itemCompareFields.put("spec", "规格");
itemCompareFields.put("material", "材质");
itemCompareFields.put("productItem", "品名项");
for (Map.Entry<String, String> entry : itemCompareFields.entrySet()) {
String fieldName = entry.getKey();
String fieldLabel = entry.getValue();
Map<String, Object> values = new LinkedHashMap<>();
for (SchProdScheduleItem item : items) {
Object val = getItemFieldValue(item, fieldName);
values.put(String.valueOf(item.getScheduleId()), val);
}
boolean same = values.values().stream().distinct().count() <= 1;
if (!same) {
allConsistent = false;
SchProdScheduleItemMergeValidateVo.FieldDiff diff = new SchProdScheduleItemMergeValidateVo.FieldDiff();
diff.setFieldName(fieldName);
diff.setFieldLabel(fieldLabel);
diff.setValues(values);
diffs.add(diff);
}
}
// 5. 构建 ItemInfo 快照列表
List<SchProdScheduleItemMergeValidateVo.ItemInfo> itemInfos = new ArrayList<>();
BigDecimal totalWeight = BigDecimal.ZERO;
for (SchProdScheduleItem item : items) {
SchProdScheduleItemMergeValidateVo.ItemInfo info = new SchProdScheduleItemMergeValidateVo.ItemInfo();
info.setItemId(item.getScheduleId());
// 解析第一个源 schedule_id
String sids = item.getScheduleDetailIds();
Long firstSourceId = null;
if (sids != null && !sids.isEmpty()) {
String[] parts = sids.split(",");
if (parts.length > 0) {
try {
firstSourceId = Long.valueOf(parts[0].trim());
} catch (NumberFormatException ignored) {}
}
}
info.setSourceScheduleId(firstSourceId);
info.setScheduleNo(item.getScheduleNo());
info.setCustomerName(item.getCustomerName());
info.setProductType(item.getProductType());
info.setSpec(item.getSpec());
info.setMaterial(item.getMaterial());
info.setScheduleWeight(item.getScheduleWeight());
info.setScheduleDetailIds(item.getScheduleDetailIds());
// header 字段
info.setBusinessUser(item.getBusinessUser());
info.setBusinessPhone(item.getBusinessPhone());
info.setDeliveryCycle(item.getDeliveryCycle());
info.setUsePurpose(item.getUsePurpose());
info.setThicknessTolerance(item.getThicknessTolerance());
info.setWidthTolerance(item.getWidthTolerance());
info.setSurfaceQuality(item.getSurfaceQuality());
info.setSurfaceTreatment(item.getSurfaceTreatment());
info.setInnerDiameter(item.getInnerDiameter());
info.setOuterDiameter(item.getOuterDiameter());
info.setPackReq(item.getPackReq());
info.setCutEdgeReq(item.getCutEdgeReq());
info.setSingleCoilWeight(item.getSingleCoilWeight());
info.setWeightDeviation(item.getWeightDeviation());
info.setOtherTechReq(item.getOtherTechReq());
info.setPaymentDesc(item.getPaymentDesc());
info.setRelContractNo(item.getRelContractNo());
info.setTotalPlanWeight(item.getTotalPlanWeight());
info.setOrderDate(item.getOrderDate());
itemInfos.add(info);
totalWeight = totalWeight.add(item.getScheduleWeight() != null ? item.getScheduleWeight() : BigDecimal.ZERO);
}
// 6. 构建汇总
SchProdScheduleItemMergeValidateVo.MergedSummary summary = new SchProdScheduleItemMergeValidateVo.MergedSummary();
summary.setItemCount(items.size());
summary.setTotalScheduleWeight(totalWeight);
// 7. 组装返回
SchProdScheduleItemMergeValidateVo vo = new SchProdScheduleItemMergeValidateVo();
vo.setConsistent(allConsistent);
vo.setDiffs(diffs);
vo.setItems(itemInfos);
vo.setSummary(summary);
return vo;
}
/**
* 反射获取字段值(用于动态字段比较 — SchProdSchedule header
*/
private Object getFieldValue(SchProdSchedule header, String fieldName) {
try {
java.lang.reflect.Field field = SchProdSchedule.class.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(header);
} catch (Exception e) {
return null;
}
}
/**
* 反射获取字段值(用于动态字段比较 — SchProdScheduleItem 明细)
*/
private Object getItemFieldValue(SchProdScheduleItem item, String fieldName) {
try {
java.lang.reflect.Field field = SchProdScheduleItem.class.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(item);
} catch (Exception e) {
return null;
}
}
}

View File

@@ -196,6 +196,8 @@ public class SchProdScheduleServiceImpl implements ISchProdScheduleService {
lqw.eq(StringUtils.isNotBlank(bo.getOtherTechReq()), SchProdSchedule::getOtherTechReq, bo.getOtherTechReq());
lqw.eq(StringUtils.isNotBlank(bo.getPaymentDesc()), SchProdSchedule::getPaymentDesc, bo.getPaymentDesc());
lqw.eq(StringUtils.isNotBlank(bo.getReturnReason()), SchProdSchedule::getReturnReason, bo.getReturnReason());
// 根据创建时间倒叙排序
lqw.orderByDesc(SchProdSchedule::getCreateTime);
return lqw;
}