Compare commits

..

4 Commits

Author SHA1 Message Date
XinanXf
8286416fd4 采購訂單export 選中 2025-06-17 14:53:11 +08:00
XinanXf
657e4b5c53 采購訂單export 選中 2025-06-13 11:24:54 +08:00
XinanXf
1683a83944 銷售訂單export 選中 2025-06-12 16:32:56 +08:00
XinanXf
3d167f3688 銷售訂單新增利潤率 2025-06-12 16:09:57 +08:00
18 changed files with 384 additions and 44 deletions

View File

@ -201,8 +201,12 @@ public class GetSaleOrderBo extends BaseBo<SaleOrderFullDto> {
@ApiModelProperty("订单明细")
private List<OrderDetailBo> details;
/**
* 毛利率 仅做校验不做存储
* 毛利率 = 本单利润/含税总金额* 100%
*/
@ApiModelProperty("毛利率")
private String grossMargin;
public GetSaleOrderBo() {

View File

@ -186,6 +186,12 @@ public class QuerySaleOrderBo extends BaseBo<SaleOrder> implements BaseDto {
@ApiModelProperty(value = "序列号")
private String productName;
/**
* 毛利率 仅做计算不做存储
* 毛利率 = 本单利润/含税总金额* 100%
*/
@ApiModelProperty("毛利率")
private String grossMargin;
public QuerySaleOrderBo(SaleOrder dto) {

View File

@ -19,6 +19,7 @@ import com.lframework.xingyun.sc.bo.purchase.PurchaseOrderWithReceiveBo;
import com.lframework.xingyun.sc.bo.purchase.PurchaseProductBo;
import com.lframework.xingyun.sc.bo.purchase.QueryPurchaseOrderBo;
import com.lframework.xingyun.sc.bo.purchase.QueryPurchaseOrderWithReceiveBo;
import com.lframework.xingyun.sc.convert.QueryPurchaseOrderVoConverter;
import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderFullDto;
import com.lframework.xingyun.sc.dto.purchase.PurchaseOrderWithReceiveDto;
import com.lframework.xingyun.sc.dto.purchase.PurchaseProductDto;
@ -31,15 +32,7 @@ import com.lframework.xingyun.sc.excel.purchase.PurchaseOrderPayTypeImportListen
import com.lframework.xingyun.sc.excel.purchase.PurchaseOrderPayTypeImportModel;
import com.lframework.xingyun.sc.service.purchase.PurchaseOrderService;
import com.lframework.xingyun.sc.service.sale.SaleOrderService;
import com.lframework.xingyun.sc.vo.purchase.ApprovePassPurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.ApproveRefusePurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.BatchApprovePassPurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.BatchApproveRefusePurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.CreatePurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderWithReceiveVo;
import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseProductVo;
import com.lframework.xingyun.sc.vo.purchase.UpdatePurchaseOrderVo;
import com.lframework.xingyun.sc.vo.purchase.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -131,19 +124,19 @@ public class PurchaseOrderController extends DefaultBaseController {
@ApiOperation("导出")
@HasPermission({"purchase:order:export"})
@PostMapping("/export")
public void export(@Valid QueryPurchaseOrderVo vo) {
public void export(@Valid QueryPurchaseExportOrderVo vo) {
ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("采购单信息",
PurchaseOrderExportModel.class);
PurchaseOrderExportModel.class);
try {
int pageIndex = 1;
while (true) {
PageResult<PurchaseOrder> pageResult = purchaseOrderService.query(pageIndex,
getExportSize(), vo);
QueryPurchaseOrderVo convert = QueryPurchaseOrderVoConverter.convert(vo);
PageResult<PurchaseOrder> pageResult = purchaseOrderService.queryExport(pageIndex, getExportSize(), convert, vo.getOrderIds());
List<PurchaseOrder> datas = pageResult.getDatas();
List<PurchaseOrderExportModel> models = datas.stream().map(PurchaseOrderExportModel::new)
.collect(Collectors.toList());
.collect(Collectors.toList());
builder.doWrite(models);
if (!pageResult.isHasNext()) {

View File

@ -21,6 +21,7 @@ import com.lframework.xingyun.sc.bo.sale.QuerySaleOrderBo;
import com.lframework.xingyun.sc.bo.sale.QuerySaleOrderWithOutBo;
import com.lframework.xingyun.sc.bo.sale.SaleOrderWithOutBo;
import com.lframework.xingyun.sc.bo.sale.SaleProductBo;
import com.lframework.xingyun.sc.convert.QuerySaleOrderVoConverter;
import com.lframework.xingyun.sc.dto.sale.SaleOrderFullDto;
import com.lframework.xingyun.sc.dto.sale.SaleOrderWithOutDto;
import com.lframework.xingyun.sc.dto.sale.SaleProductDto;
@ -30,15 +31,8 @@ import com.lframework.xingyun.sc.excel.sale.SaleOrderExportModel;
import com.lframework.xingyun.sc.mappers.SaleOrderDetailMapper;
import com.lframework.xingyun.sc.service.sale.SaleOrderDetailService;
import com.lframework.xingyun.sc.service.sale.SaleOrderService;
import com.lframework.xingyun.sc.vo.sale.ApprovePassSaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.ApproveRefuseSaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.BatchApprovePassSaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.BatchApproveRefuseSaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.CreateSaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo;
import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderWithOutVo;
import com.lframework.xingyun.sc.vo.sale.QuerySaleProductVo;
import com.lframework.xingyun.sc.vo.sale.UpdateSaleOrderVo;
import com.lframework.xingyun.sc.util.CalUtils;
import com.lframework.xingyun.sc.vo.sale.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -123,7 +117,7 @@ public class SaleOrderController extends DefaultBaseController {
public InvokeResult<PageResult<QuerySaleOrderBo>> query(@Valid QuerySaleOrderVo vo) {
PageResult<SaleOrder> pageResult = saleOrderService.query(getPageIndex(vo), getPageSize(vo),
vo);
vo);
List<SaleOrder> datas = pageResult.getDatas();
List<QuerySaleOrderBo> results = null;
@ -134,21 +128,24 @@ public class SaleOrderController extends DefaultBaseController {
if(results!=null){
for (QuerySaleOrderBo result : results) {
List<SaleOrderDetail> orderDetails=saleOrderDetailMapper.getBySaleOrderId(result.getId());
// 计算毛利率 = 本单利润/含税总金额* 100%
String grossMargin = CalUtils.CalGrossMargin(result.getThisOrderProfit(),result.getTotalAmount());
result.setGrossMargin(grossMargin + "%");
List<String> productNames = new ArrayList<>();
BigDecimal totalPurchasePrice = BigDecimal.ZERO;
for (SaleOrderDetail orderDetail : orderDetails) {
Product product= productService.findById(orderDetail.getProductId());
if (product != null && product.getName() != null) {
productNames.add(product.getName());
}
//计算成本
totalPurchasePrice = totalPurchasePrice.add(orderDetail.getTotalPurchasePrice());
}
result.setProductName(String.join(", ", productNames));
result.setTotalPurchasePrice(totalPurchasePrice);
}
}
return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results));
}
@ -158,7 +155,7 @@ public class SaleOrderController extends DefaultBaseController {
@ApiOperation("导出")
@HasPermission({"sale:order:export"})
@PostMapping("/export")
public void export(@Valid QuerySaleOrderVo vo) {
public void export(@Valid QuerySaleOrderExportVo vo) {
ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXls("销售单信息",
SaleOrderExportModel.class);
@ -166,9 +163,8 @@ public class SaleOrderController extends DefaultBaseController {
try {
int pageIndex = 1;
while (true) {
// PageResult<SaleOrder> pageResult = saleOrderService.query(pageIndex, getExportSize(), vo);
// List<SaleOrder> datas = pageResult.getDatas();
PageResult<SaleOrder> pageResult = saleOrderService.query(pageIndex, getExportSize(), vo);
QuerySaleOrderVo orderVo = QuerySaleOrderVoConverter.convert(vo);
PageResult<SaleOrder> pageResult = saleOrderService.queryExport(pageIndex, getExportSize(), orderVo, vo.getOrderIds());
List<SaleOrder> datas = pageResult.getDatas();
List<QuerySaleOrderBo> results = null;
@ -180,22 +176,28 @@ public class SaleOrderController extends DefaultBaseController {
List<String> orderIds = results.stream().map(QuerySaleOrderBo::getId).collect(Collectors.toList());
List<SaleOrderDetail> orderDetailList = saleOrderDetailService.selectList(orderIds);
// 根据orderId分组
// 根据orderId分组基础版
Map<String, List<SaleOrderDetail>> OrderIdDetailMap = orderDetailList.stream()
.collect(Collectors.groupingBy(SaleOrderDetail::getOrderId));
//拼接产品名称
for (QuerySaleOrderBo result : results) {
List<SaleOrderDetail> orderDetails = OrderIdDetailMap.get(result.getId());
// 计算毛利率 = 本单利润/含税总金额* 100%
result.setGrossMargin(CalUtils.CalGrossMargin(result.getThisOrderProfit(),result.getTotalAmount()) + "%");
List<String> productNames = new ArrayList<>();
BigDecimal totalPurchasePrice = BigDecimal.ZERO;
for (SaleOrderDetail orderDetail : orderDetails) {
Product product= productService.findById(orderDetail.getProductId());
if (product != null && product.getName() != null) {
productNames.add(product.getName());
}
//计算成本 = 商品采购单价总和
totalPurchasePrice = totalPurchasePrice.add(orderDetail.getTotalPurchasePrice());
}
result.setProductName(String.join(", ", productNames));
result.setTotalPurchasePrice(totalPurchasePrice);
}
}
@ -243,6 +245,8 @@ public class SaleOrderController extends DefaultBaseController {
detail.setPurchaseDecimal(purchaseDecimal);
detail.setTotalPurchasePrice(totalPurchasePrice);
}
// 计算毛利率 = 本单利润/含税总金额* 100%
result.setGrossMargin(CalUtils.CalGrossMargin(result.getThisOrderProfit(),result.getTotalAmount()));
}
return InvokeResultBuilder.success(result);

View File

@ -0,0 +1,26 @@
package com.lframework.xingyun.sc.convert;
import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseExportOrderVo;
import com.lframework.xingyun.sc.vo.purchase.QueryPurchaseOrderVo;
public class QueryPurchaseOrderVoConverter {
public static QueryPurchaseOrderVo convert(QueryPurchaseExportOrderVo exportVo) {
if (exportVo == null) {
return null;
}
QueryPurchaseOrderVo vo = new QueryPurchaseOrderVo();
vo.setCode(exportVo.getCode());
vo.setSupplierId(exportVo.getSupplierId());
vo.setScId(exportVo.getScId());
vo.setCreateBy(exportVo.getCreateBy());
vo.setCreateStartTime(exportVo.getCreateStartTime());
vo.setCreateEndTime(exportVo.getCreateEndTime());
vo.setApproveBy(exportVo.getApproveBy());
vo.setApproveStartTime(exportVo.getApproveStartTime());
vo.setApproveEndTime(exportVo.getApproveEndTime());
vo.setStatus(exportVo.getStatus());
vo.setPurchaserId(exportVo.getPurchaserId());
return vo;
}
}

View File

@ -0,0 +1,32 @@
package com.lframework.xingyun.sc.convert;
import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderExportVo;
import com.lframework.xingyun.sc.vo.sale.QuerySaleOrderVo;
public class QuerySaleOrderVoConverter {
public static QuerySaleOrderVo convert(QuerySaleOrderExportVo exportVo) {
if (exportVo == null) {
return null;
}
QuerySaleOrderVo vo = new QuerySaleOrderVo();
vo.setCode(exportVo.getCode());
vo.setCustomerId(exportVo.getCustomerId());
vo.setScId(exportVo.getScId());
vo.setCreateBy(exportVo.getCreateBy());
vo.setCreateStartTime(exportVo.getCreateStartTime());
vo.setCreateEndTime(exportVo.getCreateEndTime());
vo.setApproveBy(exportVo.getApproveBy());
vo.setApproveStartTime(exportVo.getApproveStartTime());
vo.setApproveEndTime(exportVo.getApproveEndTime());
vo.setStatus(exportVo.getStatus());
vo.setSalerId(exportVo.getSalerId());
vo.setIsLease(exportVo.getIsLease());
vo.setPurchaseStatus(exportVo.getPurchaseStatus());
vo.setLeaseStartTime(exportVo.getLeaseStartTime());
vo.setLeaseEndTime(exportVo.getLeaseEndTime());
return vo;
}
}

View File

@ -86,6 +86,14 @@ public class SaleOrderExportModel extends BaseBo<QuerySaleOrderBo> implements Ex
@ExcelProperty("利润")
private BigDecimal thisOrderProfit;
/**
* 毛利率 仅做计算不做存储
* 毛利率 = 本单利润/含税总金额* 100%
*/
@ExcelProperty("毛利率")
private String grossMargin;
/**
* 销售数量
*/
@ -181,6 +189,7 @@ public class SaleOrderExportModel extends BaseBo<QuerySaleOrderBo> implements Ex
this.setTotalAmount(dto.getTotalAmount());
this.setCustomMoney(dto.getCustomMoney());
this.setThisOrderProfit(dto.getThisOrderProfit());
this.setGrossMargin(dto.getGrossMargin());
this.setTotalNum(dto.getTotalNum());
this.setTotalGiftNum(dto.getTotalGiftNum());
this.setIsLease(dto.getIsLease() == 1 ? "" : "");

View File

@ -109,10 +109,26 @@ public class PurchaseOrderServiceImpl extends BaseMpServiceImpl<PurchaseOrderMap
return PageResultUtil.convert(new PageInfo<>(datas));
}
@Override
public PageResult<PurchaseOrder> queryExport(int pageIndex, int pageSize, QueryPurchaseOrderVo vo, List<String> orderIds) {
Assert.greaterThanZero(pageIndex);
Assert.greaterThanZero(pageSize);
PageHelperUtil.startPage(pageIndex, pageSize);
List<PurchaseOrder> datas = this.query(vo, orderIds);
return PageResultUtil.convert(new PageInfo<>(datas));
}
public List<PurchaseOrder> query(QueryPurchaseOrderVo vo, List<String> orderIds) {
return getBaseMapper().query(vo, orderIds);
}
@Override
public List<PurchaseOrder> query(QueryPurchaseOrderVo vo) {
return getBaseMapper().query(vo);
return getBaseMapper().query(vo, null);
}
@Override

View File

@ -123,12 +123,14 @@ public class SaleOrderServiceImpl extends BaseMpServiceImpl<SaleOrderMapper, Sal
return PageResultUtil.convert(new PageInfo<>(datas));
}
public List<SaleOrder> query(QuerySaleOrderVo vo, List<String> orderIds) {
List<SaleOrder> list=getBaseMapper().query(vo, orderIds);
return list;
}
@Override
public List<SaleOrder> query(QuerySaleOrderVo vo) {
List<SaleOrder> list=getBaseMapper().query(vo);
List<SaleOrder> list=getBaseMapper().query(vo, null);
return list;
}
@ -584,7 +586,18 @@ public class SaleOrderServiceImpl extends BaseMpServiceImpl<SaleOrderMapper, Sal
return data;
}
private void create(SaleOrder order, CreateSaleOrderVo vo) {
@Override
public PageResult<SaleOrder> queryExport(int pageIndex, int pageSize, QuerySaleOrderVo vo, List<String> orderIds) {
Assert.greaterThanZero(pageIndex);
Assert.greaterThanZero(pageSize);
PageHelperUtil.startPage(pageIndex, pageSize);
List<SaleOrder> datas = this.query(vo, orderIds);
return PageResultUtil.convert(new PageInfo<>(datas));
}
private void create(SaleOrder order, CreateSaleOrderVo vo) {
// StoreCenter sc = storeCenterService.findById(vo.getScId());

View File

@ -46,7 +46,7 @@ public interface PurchaseOrderMapper extends BaseMapper<PurchaseOrder> {
@DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = {
@DataPermission(template = "order", alias = "o")
})
List<PurchaseOrder> query(@Param("vo") QueryPurchaseOrderVo vo);
List<PurchaseOrder> query(@Param("vo") QueryPurchaseOrderVo vo, @Param("orderIds") List<String> orderIds);
/**
* 根据ID查询

View File

@ -45,7 +45,7 @@ public interface SaleOrderMapper extends BaseMapper<SaleOrder> {
@DataPermissions(type = SysDataPermissionDataPermissionType.ORDER, value = {
@DataPermission(template = "order", alias = "o")
})
List<SaleOrder> query(@Param("vo") QuerySaleOrderVo vo);
List<SaleOrder> query(@Param("vo") QuerySaleOrderVo vo, @Param("orderIds") List<String> orderIds);
/**
* 根据ID查询

View File

@ -30,6 +30,9 @@ public interface PurchaseOrderService extends BaseMpService<PurchaseOrder> {
*/
PageResult<PurchaseOrder> query(Integer pageIndex, Integer pageSize, QueryPurchaseOrderVo vo);
PageResult<PurchaseOrder> queryExport(int pageIndex, int exportSize, QueryPurchaseOrderVo convert, List<String> orderIds);
/**
* 查询列表
*

View File

@ -166,4 +166,6 @@ public interface SaleOrderService extends BaseMpService<SaleOrder> {
* @return
*/
SaleProductDto getSaleById(String id);
PageResult<SaleOrder> queryExport(int pageIndex, int exportSize, QuerySaleOrderVo orderVo, List<String> orderIds);
}

View File

@ -0,0 +1,22 @@
package com.lframework.xingyun.sc.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class CalUtils {
// 计算毛利率 = 本单利润/含税总金额* 100%
public static String CalGrossMargin(BigDecimal thisOrderProfit, BigDecimal totalAmount) {
if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) == 0) {
return "0.000%";
}
BigDecimal margin = thisOrderProfit
.divide(totalAmount, 6, RoundingMode.HALF_UP) // 增加到6位小数
.multiply(BigDecimal.valueOf(100))
.setScale(3, RoundingMode.HALF_UP);
return margin.stripTrailingZeros().toPlainString() + "%";
}
}

View File

@ -0,0 +1,86 @@
package com.lframework.xingyun.sc.vo.purchase;
import com.lframework.starter.web.components.validation.IsEnum;
import com.lframework.starter.web.vo.SortPageVo;
import com.lframework.xingyun.sc.enums.PurchaseOrderStatus;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
@Data
public class QueryPurchaseExportOrderVo extends SortPageVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("订单Id列表")
private List<String> orderIds;
/**
* 单号
*/
@ApiModelProperty("单号")
private String code;
/**
* 供应商ID
*/
@ApiModelProperty("供应商ID")
private String supplierId;
/**
* 仓库ID
*/
@ApiModelProperty("仓库ID")
private String scId;
/**
* 操作人ID
*/
@ApiModelProperty("操作人ID")
private String createBy;
/**
* 操作起始时间
*/
@ApiModelProperty("操作起始时间")
private LocalDateTime createStartTime;
/**
* 操作截止时间
*/
@ApiModelProperty("操作截止时间")
private LocalDateTime createEndTime;
/**
* 审核人ID
*/
@ApiModelProperty("审核人ID")
private String approveBy;
/**
* 审核起始时间
*/
@ApiModelProperty("审核起始时间")
private LocalDateTime approveStartTime;
/**
* 审核截止时间
*/
@ApiModelProperty("审核截止时间")
private LocalDateTime approveEndTime;
/**
* 状态
*/
@ApiModelProperty("状态")
@IsEnum(message = "状态格式不正确!", enumClass = PurchaseOrderStatus.class)
private Integer status;
/**
* 采购员ID
*/
@ApiModelProperty("采购员ID")
private String purchaserId;
}

View File

@ -0,0 +1,110 @@
package com.lframework.xingyun.sc.vo.sale;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lframework.starter.common.constants.StringPool;
import com.lframework.starter.web.components.validation.IsEnum;
import com.lframework.xingyun.sc.enums.SaleOrderStatus;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class QuerySaleOrderExportVo {
private static final long serialVersionUID = 1L;
@ApiModelProperty("订单Id列表")
private List<String> orderIds;
/**
* 单号
*/
@ApiModelProperty("单号")
private String code;
/**
* 客户ID
*/
@ApiModelProperty("客户ID")
private String customerId;
/**
* 仓库ID
*/
@ApiModelProperty("仓库ID")
private String scId;
/**
* 操作人ID
*/
@ApiModelProperty("操作人ID")
private String createBy;
/**
* 操作起始时间
*/
@ApiModelProperty("操作起始时间")
private LocalDateTime createStartTime;
/**
* 操作截止时间
*/
@ApiModelProperty("操作截止时间")
private LocalDateTime createEndTime;
/**
* 审核人ID
*/
@ApiModelProperty("审核人ID")
private String approveBy;
/**
* 审核起始时间
*/
@ApiModelProperty("审核起始时间")
private LocalDateTime approveStartTime;
/**
* 审核截止时间
*/
@ApiModelProperty("审核截止时间")
private LocalDateTime approveEndTime;
/**
* 状态
*/
@ApiModelProperty("状态")
@IsEnum(message = "状态格式不正确!", enumClass = SaleOrderStatus.class)
private Integer status;
/**
* 销售员ID
*/
@ApiModelProperty("销售员ID")
private String salerId;
@ApiModelProperty("是否租赁订单")
//@IsEnum(message = "格式不正确!", enumClass = SaleOrderIsLease.class)
private Integer isLease;
/**
* 采购状态0未采购2完成采购3部分采购
*/
//@IsEnum(message = "格式不正确!", enumClass = SaleOrderPurchaseStatus.class)
private Integer purchaseStatus;
@ApiModelProperty(value = "租赁开始日期")
@DateTimeFormat(StringPool.DATE_PATTERN)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime leaseStartTime;
@ApiModelProperty(value = "租赁结束日期")
@DateTimeFormat(StringPool.DATE_PATTERN)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime leaseEndTime;
}

View File

@ -213,6 +213,13 @@
]]>
</if>
</if>
<if test="orderIds != null and !orderIds.isEmpty()">
AND o.id IN
<foreach item="id" collection="orderIds" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</where>
ORDER BY o.create_time DESC
</select>

View File

@ -265,6 +265,13 @@
]]>
</if>
</if>
<if test="orderIds != null and !orderIds.isEmpty()">
AND o.id IN
<foreach item="id" collection="orderIds" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</where>
ORDER BY o.create_time DESC
</select>