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

This commit is contained in:
zt
2025-09-08 20:03:11 +08:00
16 changed files with 303 additions and 23 deletions

View File

@ -88,6 +88,8 @@ public class BusMaterialbatchdemandplanServiceImpl extends ServiceImpl<BusMateri
@Override @Override
public TableDataInfo<BusMaterialbatchdemandplanVo> queryPageList(BusMaterialbatchdemandplanBo bo, PageQuery pageQuery) { public TableDataInfo<BusMaterialbatchdemandplanVo> queryPageList(BusMaterialbatchdemandplanBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<BusMaterialbatchdemandplan> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<BusMaterialbatchdemandplan> lqw = buildQueryWrapper(bo);
Page<BusMaterialbatchdemandplanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
if (bo.getSupplierId()!=null){
BusBiddingPlanBo bo1 = new BusBiddingPlanBo(); BusBiddingPlanBo bo1 = new BusBiddingPlanBo();
bo1.setProjectId(bo.getProjectId()); bo1.setProjectId(bo.getProjectId());
bo1.setType("2"); bo1.setType("2");
@ -100,12 +102,12 @@ public class BusMaterialbatchdemandplanServiceImpl extends ServiceImpl<BusMateri
busBiddingPlanVos.stream().forEach(vo -> { busBiddingPlanVos.stream().forEach(vo -> {
hashSet.add(vo.getName()+"+"+vo.getSpecification()); hashSet.add(vo.getName()+"+"+vo.getSpecification());
}); });
Page<BusMaterialbatchdemandplanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
List<BusMaterialbatchdemandplanVo> list = result.getRecords().stream().filter(vo -> { List<BusMaterialbatchdemandplanVo> list = result.getRecords().stream().filter(vo -> {
String key = vo.getName() + "+" + vo.getSpecification(); // 拼接字符串(需与 Set 中格式一致) String key = vo.getName() + "+" + vo.getSpecification(); // 拼接字符串(需与 Set 中格式一致)
return hashSet.contains(key); // 仅保留 Set 中存在的数据 return hashSet.contains(key); // 仅保留 Set 中存在的数据
}).toList(); }).toList();
result.setRecords(list); result.setRecords(list);
}
return TableDataInfo.build(result); return TableDataInfo.build(result);
} }

View File

@ -16,6 +16,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.gps.domain.GpsManmachine; import org.dromara.gps.domain.GpsManmachine;
import org.dromara.gps.domain.bo.GpsEquipmentSonBo; import org.dromara.gps.domain.bo.GpsEquipmentSonBo;
import org.dromara.gps.domain.vo.GpsProjectVo; import org.dromara.gps.domain.vo.GpsProjectVo;
@ -39,6 +41,7 @@ import org.dromara.gps.service.IGpsEquipmentService;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -212,8 +215,8 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
GpsEquipmentSonBo gpsEquipmentSon = JSONUtil.toBean(device, GpsEquipmentSonBo.class); GpsEquipmentSonBo gpsEquipmentSon = JSONUtil.toBean(device, GpsEquipmentSonBo.class);
JSONObject location = device.getJSONObject("location"); JSONObject location = device.getJSONObject("location");
gpsEquipmentSon.setLocLatitude(location.getBigDecimal("latitude")); gpsEquipmentSon.setLocLatitude(location.getBigDecimal("latitude").divide(new BigDecimal("1000000"),6, RoundingMode.HALF_UP));
gpsEquipmentSon.setLocLongitude(location.getBigDecimal("longitude")); gpsEquipmentSon.setLocLongitude(location.getBigDecimal("longitude").divide(new BigDecimal("1000000"),6, RoundingMode.HALF_UP));
if (equipment != null) { if (equipment != null) {
gpsEquipmentSon.setProjectId(equipment.getProjectId()); gpsEquipmentSon.setProjectId(equipment.getProjectId());
} }
@ -234,11 +237,52 @@ public class GpsEquipmentServiceImpl extends ServiceImpl<GpsEquipmentMapper, Gps
gpsEquipmentSonService.insertByBo(gpsEquipmentSon); gpsEquipmentSonService.insertByBo(gpsEquipmentSon);
//保存到redis如果存在则更新存活时间 //保存到redis如果存在则更新存活时间
// --------------------------
// 发布String类型订阅消息
// --------------------------
// 1. 构造需要推送的消息内容String类型
String pushContent = buildPushMessage(gpsEquipmentSon);
// WebSocketUtils.publishAll(pushContent);
// 2. 发布消息根据是否有用户ID决定发送给指定用户或广播
if (equipment != null && equipment.getUserId() != null) {
// 发送给指定用户equipment.getUserId()
WebSocketMessageDto messageDto = new WebSocketMessageDto();
messageDto.setMessage(pushContent);
messageDto.setSessionKeys(Collections.singletonList(equipment.getUserId()));
WebSocketUtils.publishMessage(messageDto);
} else {
// 无用户ID则广播给所有在线客户端
WebSocketUtils.publishAll(pushContent);
}
} }
// 保存到Redis并设置过期监听 // 保存到Redis并设置过期监听
updateDeviceAliveStatus(gpsEquipment.getClientId()); updateDeviceAliveStatus(gpsEquipment.getClientId());
} }
/**
* 构建推送消息内容String类型
*/
private String buildPushMessage(GpsEquipmentSonBo sonBo) {
// 构造消息对象(包含关键信息)
JSONObject messageObj = new JSONObject();
messageObj.put("type", "GPS_DATA_UPDATE"); // 消息类型
messageObj.put("clientId", sonBo.getClientId()); // 设备唯一标识
messageObj.put("projectId", sonBo.getProjectId()); // 项目ID
messageObj.put("userId", sonBo.getUserId()); // 关联用户ID
// 位置信息
JSONObject locationObj = new JSONObject();
locationObj.put("latitude", sonBo.getLocLatitude()); // 纬度
locationObj.put("longitude", sonBo.getLocLongitude()); // 经度
locationObj.put("altitude", sonBo.getLocAltitude()); // 海拔
messageObj.put("location", locationObj);
// 转换为String类型返回
return messageObj.toString();
}
private static final int DEVICE_ALIVE_TIMEOUT = 120; // 5分钟 private static final int DEVICE_ALIVE_TIMEOUT = 120; // 5分钟
/** /**

View File

@ -37,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -141,6 +142,7 @@ public class BusEnterRoadController extends BaseController {
return busEnterRoad; return busEnterRoad;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
Collections.reverse(busEnterRoads);
busEnterRoadService.saveBatch(busEnterRoads); busEnterRoadService.saveBatch(busEnterRoads);
}, },
projectId, projectId,

View File

@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -132,6 +133,7 @@ public class BusLandBlockController extends BaseController {
return busLandBlock; return busLandBlock;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
Collections.reverse(busLandBlocks);
busLandBlockService.saveBatch(busLandBlocks); busLandBlockService.saveBatch(busLandBlocks);
}, },
projectId, projectId,

View File

@ -17,6 +17,8 @@ import org.dromara.tender.domain.bo.BusBillofquantitiesLimitListBo;
import org.dromara.tender.domain.bo.TenderAllVersionNumbersReq; import org.dromara.tender.domain.bo.TenderAllVersionNumbersReq;
import org.dromara.tender.domain.vo.BusBLimitListVersionsVo; import org.dromara.tender.domain.vo.BusBLimitListVersionsVo;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListVo; import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListVo;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListWuZiVo;
import org.dromara.tender.enums.LimitListTypeEnum;
import org.dromara.tender.service.IBusBillofquantitiesLimitListService; import org.dromara.tender.service.IBusBillofquantitiesLimitListService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -89,8 +91,13 @@ public class BusTenderPlanLimitListController extends BaseController {
@Log(title = "限价一览", businessType = BusinessType.EXPORT) @Log(title = "限价一览", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(BusBillofquantitiesLimitListBo bo, HttpServletResponse response) { public void export(BusBillofquantitiesLimitListBo bo, HttpServletResponse response) {
if (LimitListTypeEnum.SUB_COMPANY.getCode().equals(bo.getType())){
List<BusBillofquantitiesLimitListVo> list = busBillofquantitiesLimitListService.queryList(bo); List<BusBillofquantitiesLimitListVo> list = busBillofquantitiesLimitListService.queryList(bo);
ExcelUtil.exportExcel(list, "限价一览", BusBillofquantitiesLimitListVo.class, response); ExcelUtil.exportExcel(list, "限价一览", BusBillofquantitiesLimitListVo.class, response);
}else {
List<BusBillofquantitiesLimitListWuZiVo> list = busBillofquantitiesLimitListService.queryVoList(bo);
ExcelUtil.exportExcel(list, "限价一览", BusBillofquantitiesLimitListWuZiVo.class, response);
}
} }
/** /**

View File

@ -99,6 +99,15 @@ public class BusBillofquantitiesLimitList extends BaseEntity {
* 总价 * 总价
*/ */
// private BigDecimal price; // private BigDecimal price;
/**
* 供应单位
*/
private String supplier;
/**
* 合同编号
*/
private String contractNumber;
/** /**
* 备注 * 备注

View File

@ -95,6 +95,16 @@ public class BusBillofquantitiesLimitListBo extends BaseEntity {
*/ */
private BigDecimal taxRate; private BigDecimal taxRate;
/**
* 供应单位
*/
private String supplier;
/**
* 合同编号
*/
private String contractNumber;
/** /**
* 总价 * 总价
*/ */

View File

@ -135,5 +135,10 @@ public class BusBiddingPlanVo implements Serializable {
*/ */
private Long winningBidderId; private Long winningBidderId;
/**
* 招标文件数量
*/
private Long annexCount;
} }

View File

@ -135,6 +135,16 @@ public class BusBillofquantitiesLimitListVo implements Serializable {
@ExcelProperty(value = "备注") @ExcelProperty(value = "备注")
private String remark; private String remark;
/**
* 供应单位
*/
private String supplier;
/**
* 合同编号
*/
private String contractNumber;
/** /**
* 子节点 * 子节点
*/ */

View File

@ -0,0 +1,153 @@
package org.dromara.tender.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.tender.domain.BusBillofquantitiesLimitList;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 限价一览视图对象 bus_billofquantities_limit_list
*
* @author Lion Li
* @date 2025-08-19
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = BusBillofquantitiesLimitList.class)
public class BusBillofquantitiesLimitListWuZiVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 项目Id
*/
@ExcelProperty(value = "项目Id")
private Long projectId;
/**
* 版本号
*/
@ExcelProperty(value = "版本号")
private String versions;
/**
* 表名
*/
@ExcelProperty(value = "表名")
private String sheet;
/**
* 子ID
*/
@ExcelProperty(value = "子ID")
private String sid;
/**
* 父ID
*/
@ExcelProperty(value = "父ID")
private String pid;
/**
* 编号
*/
@ExcelProperty(value = "编号")
private String num;
/**
* 类型
*/
@ExcelProperty(value = "类型")
private String type;
/**
* 名称
*/
@ColumnWidth(50)
@ExcelProperty(value = "名称")
private String name;
/**
* 规格
*/
@ExcelProperty(value = "规格")
private String specification;
/**
* 单位
*/
@ExcelProperty(value = "单位")
private String unit;
/**
* 数量
*/
@ExcelProperty(value = "数量")
private BigDecimal quantity;
/**
* 使用数量
*/
private BigDecimal useQuantity;
/**
* 单价
*/
@ExcelProperty(value = "单价")
private BigDecimal unitPrice;
/**
* 税率
*/
@ExcelProperty(value = "税率(%)")
private BigDecimal taxRate;
/**
* 总价
*/
// @ExcelProperty(value = "总价")
private BigDecimal price;
/**
* 供应单位
*/
@ExcelProperty(value = "供应单位")
private String supplier;
/**
* 合同编号
*/
@ExcelProperty(value = "合同编号")
private String contractNumber;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 子节点
*/
private List<BusBillofquantitiesLimitListWuZiVo> children = new ArrayList<>();
}

View File

@ -67,4 +67,6 @@ public interface IBusBiddingPlanAnnexService extends IService<BusBiddingPlanAnne
* @return 是否删除成功 * @return 是否删除成功
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
Long getCount(Long id);
} }

View File

@ -9,6 +9,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListWuZiVo;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.Collection; import java.util.Collection;
@ -109,4 +110,6 @@ public interface IBusBillofquantitiesLimitListService extends IService<BusBillof
BusBillofquantitiesLimitListVo queryBySId(String pid); BusBillofquantitiesLimitListVo queryBySId(String pid);
List<BusBillofquantitiesLimitListVo> queryVoByIds(List<Long> ids); List<BusBillofquantitiesLimitListVo> queryVoByIds(List<Long> ids);
List<BusBillofquantitiesLimitListWuZiVo> queryVoList(BusBillofquantitiesLimitListBo bo);
} }

View File

@ -130,4 +130,9 @@ public class BusBiddingPlanAnnexServiceImpl extends ServiceImpl<BusBiddingPlanAn
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
@Override
public Long getCount(Long id) {
return baseMapper.selectCount(new LambdaQueryWrapper<BusBiddingPlanAnnex>().eq(BusBiddingPlanAnnex::getBiddingPlanId,id));
}
} }

View File

@ -90,6 +90,7 @@ public class BusBiddingPlanServiceImpl extends ServiceImpl<BusBiddingPlanMapper,
public TableDataInfo<BusBiddingPlanVo> queryPageList(BusBiddingPlanBo bo, PageQuery pageQuery) { public TableDataInfo<BusBiddingPlanVo> queryPageList(BusBiddingPlanBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<BusBiddingPlan> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<BusBiddingPlan> lqw = buildQueryWrapper(bo);
Page<BusBiddingPlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); Page<BusBiddingPlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
result.getRecords().forEach(item -> item.setAnnexCount(busBiddingPlanAnnexService.getCount(item.getId())));
return TableDataInfo.build(result); return TableDataInfo.build(result);
} }
@ -195,6 +196,9 @@ public class BusBiddingPlanServiceImpl extends ServiceImpl<BusBiddingPlanMapper,
if ((bo.getBidFile() == null || bo.getBidFile().isEmpty()) && (bo.getContractPrice() != null ||bo.getWinningBidderId() != null)){ if ((bo.getBidFile() == null || bo.getBidFile().isEmpty()) && (bo.getContractPrice() != null ||bo.getWinningBidderId() != null)){
throw new ServiceException("中标文件未上传"); throw new ServiceException("中标文件未上传");
} }
if (bo.getPrice()!=null && bo.getContractPrice()!=null && bo.getContractPrice().compareTo(bo.getPrice()) >0){
throw new ServiceException("合同金额不能超过总价");
}
} }
} }
// validEntityBeforeSave(update); // validEntityBeforeSave(update);

View File

@ -22,10 +22,12 @@ import org.dromara.tender.domain.bo.BusBillofquantitiesLimitListBo;
import org.dromara.tender.domain.bo.TenderAllVersionNumbersReq; import org.dromara.tender.domain.bo.TenderAllVersionNumbersReq;
import org.dromara.tender.domain.vo.BusBLimitListVersionsVo; import org.dromara.tender.domain.vo.BusBLimitListVersionsVo;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListVo; import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListVo;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListWuZiVo;
import org.dromara.tender.enums.LimitListTypeEnum; import org.dromara.tender.enums.LimitListTypeEnum;
import org.dromara.tender.mapper.BusBillofquantitiesLimitListMapper; import org.dromara.tender.mapper.BusBillofquantitiesLimitListMapper;
import org.dromara.tender.service.IBusBLimitListVersionsService; import org.dromara.tender.service.IBusBLimitListVersionsService;
import org.dromara.tender.service.IBusBillofquantitiesLimitListService; import org.dromara.tender.service.IBusBillofquantitiesLimitListService;
import org.springframework.beans.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 org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -193,7 +195,6 @@ public class BusBillofquantitiesLimitListServiceImpl extends ServiceImpl<BusBill
if (bo.getType().equals(LimitListTypeEnum.COMPANY.getCode())){ if (bo.getType().equals(LimitListTypeEnum.COMPANY.getCode())){
listVoList = baseMapper.selectByBoByType(bo); listVoList = baseMapper.selectByBoByType(bo);
}else { }else {
listVoList = baseMapper.selectByBo(bo); listVoList = baseMapper.selectByBo(bo);
} }
//过滤数量和单价为空的数据并计算总价 //过滤数量和单价为空的数据并计算总价
@ -255,7 +256,7 @@ public class BusBillofquantitiesLimitListServiceImpl extends ServiceImpl<BusBill
file, // 上传的文件 file, // 上传的文件
1, // 跳过1行表头 1, // 跳过1行表头
0, // 从第0列开始 0, // 从第0列开始
14, // 到第5列结束 16, // 到第5列结束
BusBillofquantitiesLimitListBo.class // 目标实体类 BusBillofquantitiesLimitListBo.class // 目标实体类
); );
List<BusBillofquantitiesLimitList> busBillofquantities = new ArrayList<BusBillofquantitiesLimitList>(); List<BusBillofquantitiesLimitList> busBillofquantities = new ArrayList<BusBillofquantitiesLimitList>();
@ -270,6 +271,10 @@ public class BusBillofquantitiesLimitListServiceImpl extends ServiceImpl<BusBill
limitList.setType(bo.getType()); limitList.setType(bo.getType());
limitList.setUnitPrice(item.getUnitPrice()); limitList.setUnitPrice(item.getUnitPrice());
limitList.setTaxRate(item.getTaxRate()); limitList.setTaxRate(item.getTaxRate());
if (LimitListTypeEnum.SPECIAL.getCode().equals(bo.getType())){
limitList.setSupplier(item.getSupplier());
limitList.setContractNumber(item.getContractNumber());
}
busBillofquantities.add(limitList); busBillofquantities.add(limitList);
}); });
if (CollUtil.isEmpty(busBillofquantities)) { if (CollUtil.isEmpty(busBillofquantities)) {
@ -303,6 +308,19 @@ public class BusBillofquantitiesLimitListServiceImpl extends ServiceImpl<BusBill
return baseMapper.selectVoByIds(ids); return baseMapper.selectVoByIds(ids);
} }
@Override
public List<BusBillofquantitiesLimitListWuZiVo> queryVoList(BusBillofquantitiesLimitListBo bo) {
LambdaQueryWrapper<BusBillofquantitiesLimitList> lqw = buildQueryWrapper(bo);
List<BusBillofquantitiesLimitListVo> listVoList = baseMapper.selectVoList(lqw);
List<BusBillofquantitiesLimitListWuZiVo> wuZiVoArrayList = new ArrayList<>();
listVoList.forEach(item -> {
BusBillofquantitiesLimitListWuZiVo vo = new BusBillofquantitiesLimitListWuZiVo();
BeanUtils.copyProperties(item, vo);
wuZiVoArrayList.add(vo);
});
return wuZiVoArrayList;
}
/** /**
* 递归构建树形结构 * 递归构建树形结构
* *

View File

@ -97,6 +97,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bbll.quantity as quantity, bbll.quantity as quantity,
bbll.unit_price as unitPrice, bbll.unit_price as unitPrice,
bbll.tax_rate as taxRate, bbll.tax_rate as taxRate,
bbll.supplier as supplier,
bbll.contract_number as contractNumber,
bbll.remark as remark, bbll.remark as remark,
SUM(btpll.num) AS useQuantity SUM(btpll.num) AS useQuantity
FROM FROM
@ -138,6 +140,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bbll.quantity as quantity, bbll.quantity as quantity,
bbll.tax_rate as taxRate, bbll.tax_rate as taxRate,
bbll.unit_price as unitPrice, bbll.unit_price as unitPrice,
bbll.supplier as supplier,
bbll.contract_number as contractNumber,
bbll.remark as remark, bbll.remark as remark,
SUM(btpll.num) AS useQuantity SUM(btpll.num) AS useQuantity
FROM FROM