恢复被覆盖的代码

This commit is contained in:
马三炮 2026-01-22 18:25:33 +08:00
parent 463dfdc5ce
commit d21636425e
3 changed files with 588 additions and 160 deletions

View File

@ -4,23 +4,25 @@
<select id="queryProjectLeaseDetails" parameterType="com.bonus.cost.beans.ProjectLeaseCostDetail" resultType="com.bonus.cost.beans.ProjectLeaseCostDetail">
SELECT
wir.`CODE` AS machineCode,
1 AS operateType,
mt2.`NAME` AS machineTypeName,
mt.`NAME` AS machineModel,mt.ID AS machineTypeId,
mt.UNIT AS machineModel,
mt.LEASE_PRICE AS price,
mm.REMARK as remark,
bu.`NAME` AS leaseUnit,
bp.`NAME` AS projectName,
wla.`CODE` AS taskCode,
wtr1.NUMBER AS taskCode,
ROUND(wir.num) AS leaseNum,
wtr.OPERATION_TIME AS operateTime,
wtr1.LEASE_PERSON AS operatePersonName,
pmo. NAME AS companyName,
pu.`NAME` as servicer,
bs.`NAME` as bsName
wir.`CODE` AS machineCode,
1 AS operateType,
mt2.`NAME` AS machineTypeName,
mt.`NAME` AS machineModel,mt.ID AS machineTypeId,
mt.UNIT AS machineUnit,
mt3.`NAME` AS machineCodeName,
mt.LEASE_PRICE AS price,
mm.REMARK as remark,
bu.`NAME` AS leaseUnit,
bp.`NAME` AS projectName,
wla.`CODE` AS taskCode,
wtr1.NUMBER AS taskCode,
ROUND(wir.num) AS leaseNum,
wtr.OPERATION_TIME AS operateTime,
wtr1.LEASE_PERSON AS operatePersonName,
pmo. NAME AS companyName,
pu.`NAME` as servicer,
bs.`NAME` as bsName,
mm.REMARK as oldMachineCode
FROM wf_info_record wir
LEFT JOIN wf_task_record wtr ON wir.SUP_ID = wtr.ID
LEFT JOIN wf_task_record wtr1 ON wtr1.ID = wtr.SUP_ID
@ -31,6 +33,7 @@
LEFT JOIN wf_lease_agreement wla ON wat.AGREEMENT_ID = wla.ID
LEFT JOIN mm_type mt ON wir.MODEL_ID = mt.ID
LEFT JOIN mm_type mt2 ON mt.PARENT_ID = mt2.ID
LEFT JOIN mm_type mt3 ON mt2.PARENT_ID = mt3.ID
LEFT JOIN bm_unit bu ON wla.LEASE_COMPANY = bu.id
LEFT JOIN bm_project bp ON wla.PROJECT = bp.ID
LEFT JOIN pm_organization pmo ON pmo.id = wtr.ORG_ID
@ -38,39 +41,41 @@
LEFT JOIN pm_user pu ON wmo.OUT_PERSON = pu.ID
LEFT JOIN mm_machines mm ON mm.ID = wir.MA_ID
WHERE wir.TYPE = 2
and wtr.IS_ACTIVE = 1
and wla.PROJECT = #{param.projectId}
<if test="param.machineTypeId != null">
and wir.MODEL_ID = #{param.machineTypeId}
</if>
<if test="param.endTime != null">
<!-- 查询所有在统计结束时间之前的领料记录(包括统计期间开始之前的领料) -->
and wtr.IS_ACTIVE = 1
and wla.PROJECT = #{param.projectId}
<if test="param.machineTypeId != null">
and wir.MODEL_ID = #{param.machineTypeId}
</if>
<if test="param.endTime != null">
<!-- 查询所有在统计结束时间之前的领料记录(包括统计期间开始之前的领料) -->
and left(wtr.OPERATION_TIME,10) &lt;= #{param.endTime}
</if>
<if test="param.keyWord != null and param.keyWord != ''">
<if test="param.keyWord != null and param.keyWord != ''">
AND(
mt2.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
mt.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
mt.UNIT LIKE CONCAT('%',#{param.keyWord},'%') OR
bu.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
bp.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr.OPERATION_TIME LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr.LEASE_PERSON LIKE CONCAT('%',#{param.keyWord},'%') OR
wla.`CODE` LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr1.NUMBER LIKE CONCAT('%',#{param.keyWord},'%') OR
pmo. NAME LIKE CONCAT('%',#{param.keyWord},'%')
mt2.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
mt.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
mt.UNIT LIKE CONCAT('%',#{param.keyWord},'%') OR
bu.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
bp.`NAME` LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr.OPERATION_TIME LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr.LEASE_PERSON LIKE CONCAT('%',#{param.keyWord},'%') OR
wla.`CODE` LIKE CONCAT('%',#{param.keyWord},'%') OR
wtr1.NUMBER LIKE CONCAT('%',#{param.keyWord},'%') OR
pmo. NAME LIKE CONCAT('%',#{param.keyWord},'%')
)
</if>
GROUP BY wir.SUP_ID,wir.MODEL_ID,wir.`CODE`
</select>
</select>
<select id="queryProjectReturnDetails" resultType="com.bonus.cost.beans.ProjectLeaseCostDetail">
SELECT DISTINCT
wir.ID as id,wir.MODEL_ID as machineTypeId,wla.`CODE` AS agreementCode,bu.`NAME` AS leaseUnit,
bp.`NAME` AS projectName,mmt.`NAME` as machineTypeName,mt.`NAME` as machineModel,mt.BUY_PRICE AS price,
wtr.NUMBER AS taskCode,wir.`CODE` as machineCode,wir.TIME as operateTime,ROUND(wir.NUM) as returnNum,
mt.IS_COUNT as isCount,wir.TYPE as type,pmo.`NAME` as companyName,wrd.OPERATOR as operatePersonName,
mm.REMARK AS remark,bs.`NAME` as bsName,wir.RM_STATUS as rmStatus,2 AS operateType,mt.LEASE_PRICE AS price
wir.ID as id,wir.MODEL_ID as machineTypeId,wla.`CODE` AS agreementCode,bu.`NAME` AS leaseUnit,
bp.`NAME` AS projectName,mmt.`NAME` as machineTypeName,mt.`NAME` as machineModel,mt.BUY_PRICE AS price,
mt.UNIT AS machineUnit,mt.ID AS machineTypeId,
wtr.NUMBER AS taskCode,wir.`CODE` as machineCode,wir.TIME as operateTime,ROUND(wir.NUM) as returnNum,
mt.IS_COUNT as isCount,wir.TYPE as type,pmo.`NAME` as companyName,wrd.OPERATOR as operatePersonName,
mm.REMARK AS remark,bs.`NAME` as bsName,wir.RM_STATUS as rmStatus,2 AS operateType,mt.LEASE_PRICE AS price,
mt3.`NAME` AS machineCodeName,mm.REMARK as oldMachineCode
FROM wf_info_record wir
LEFT JOIN wf_return_material_details wrd ON wir.SUP_ID = wrd.ID
LEFT JOIN wf_task_record wtr ON wrd.TASK_ID = wtr.ID
@ -83,16 +88,17 @@
LEFT JOIN pm_user pu ON wtr.CHECKER_ID = pu.ID
LEFT JOIN mm_type mt ON wir.MODEL_ID = mt.ID
LEFT JOIN mm_type mmt ON mt.PARENT_ID = mmt.ID
LEFT JOIN mm_type mt3 ON mmt.PARENT_ID = mt3.ID
LEFT JOIN mm_machines mm ON mm.ID = wir.MA_ID
where
wir.TYPE = 4 and wtr.IS_ACTIVE = 1 and wla.PROJECT = #{param.projectId}
<if test="param.machineTypeId != null">
and wir.MODEL_ID = #{param.machineTypeId}
</if>
<if test="param.endTime != null">
<!-- 查询所有在统计结束时间之前的退料记录(包括统计期间开始之前的退料) -->
and left(wir.TIME,10) &lt;= #{param.endTime}
</if>
wir.TYPE = 4 and wtr.IS_ACTIVE = 1 and wla.PROJECT = #{param.projectId}
<if test="param.machineTypeId != null">
and wir.MODEL_ID = #{param.machineTypeId}
</if>
<if test="param.endTime != null">
<!-- 查询所有在统计结束时间之前的退料记录(包括统计期间开始之前的退料) -->
and left(wir.TIME,10) &lt;= #{param.endTime}
</if>
<if test="param.keyWord != null and param.keyWord != ''">
and (
bu.`NAME` like concat('%',#{param.keyWord},'%') OR
@ -121,57 +127,57 @@
CREATE_USER,
DEL_FLAG
) VALUES (
#{id},
#{projectId},
#{projectName},
#{startTime},
#{endTime},
#{leaseCount},
#{returnCount},
#{createTime},
#{createUser},
0
)
#{id},
#{projectId},
#{projectName},
#{startTime},
#{endTime},
#{leaseCount},
#{returnCount},
#{createTime},
#{createUser},
0
)
</select>
<insert id="saveSettlementDetails" parameterType="java.util.List">
insert into wf_project_settlement_details(
ID,
SETTLEMENT_ID,
OPERATE_TYPE,
MACHINE_TYPE_ID,
MACHINE_TYPE_NAME,
MACHINE_CODE,
MACHINE_MODEL,
MACHINE_UNIT,
PRICE,
LEASE_NUM,
RETURN_NUM,
LEASE_UNIT,
OPERATE_PERSON_NAME,
OPERATE_DATE,
TASK_CODE
ID,
SETTLEMENT_ID,
OPERATE_TYPE,
MACHINE_TYPE_ID,
MACHINE_TYPE_NAME,
MACHINE_CODE,
MACHINE_MODEL,
MACHINE_UNIT,
PRICE,
LEASE_NUM,
RETURN_NUM,
LEASE_UNIT,
OPERATE_PERSON_NAME,
OPERATE_DATE,
TASK_CODE
) values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},
#{item.settlementId},
#{item.operateType},
#{item.machineTypeId},
#{item.machineTypeName},
#{item.machineCode},
#{item.machineModel},
#{item.machineUnit},
#{item.price},
#{item.leaseNum},
#{item.returnNum},
#{item.leaseUnit},
#{item.operatePersonName},
#{item.operateDate},
#{item.taskCode}
)
</foreach>
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.id},
#{item.settlementId},
#{item.operateType},
#{item.machineTypeId},
#{item.machineTypeName},
#{item.machineCode},
#{item.machineModel},
#{item.machineUnit},
#{item.price},
#{item.leaseNum},
#{item.returnNum},
#{item.leaseUnit},
#{item.operatePersonName},
#{item.operateDate},
#{item.taskCode}
)
</foreach>
</insert>
</mapper>
</mapper>

View File

@ -2,11 +2,12 @@ package com.bonus.cost.beans;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.math.BigDecimal;
import java.util.Map;
/**
* 工程领退物资明细实体类
*
*
* @author syruan
*/
public class ProjectLeaseCostDetail {
@ -21,6 +22,11 @@ public class ProjectLeaseCostDetail {
*/
private String machineName;
/**
* 机具类别
*/
private String machineCodeName;
/**
* 机具类型名称
*/
@ -51,6 +57,8 @@ public class ProjectLeaseCostDetail {
*/
private String machineCode;
private String oldMachineCode;
/**
* 备注
*/
@ -106,6 +114,21 @@ public class ProjectLeaseCostDetail {
*/
private String operatePersonName;
/**
* 累计领料数量
*/
private BigDecimal totalLeaseQuantity;
/**
* 累计退料数量
*/
private BigDecimal totalReturnQuantity;
/**
* 领退料差额
*/
private BigDecimal differenceQuantity;
/**
* 操作日期
*/
@ -128,6 +151,16 @@ public class ProjectLeaseCostDetail {
*/
private String endTime;
/**
* 租赁单位
*/
private String bsName;
/**
* 序号第几次领料
*/
private Integer sequence;
/**
* 查询关键字
*/
@ -324,4 +357,61 @@ public class ProjectLeaseCostDetail {
public void setMachineTypeName(String machineTypeName) {
this.machineTypeName = machineTypeName;
}
public String getOldMachineCode() {
return oldMachineCode;
}
public void setOldMachineCode(String oldMachineCode) {
this.oldMachineCode = oldMachineCode;
}
public String getBsName() {
return bsName;
}
public void setBsName(String bsName) {
this.bsName = bsName;
}
public String getMachineCodeName() {
return machineCodeName;
}
public void setMachineCodeName(String machineCodeName) {
this.machineCodeName = machineCodeName;
}
public Integer getSequence() {
return sequence;
}
public void setSequence(Integer sequence) {
this.sequence = sequence;
}
public BigDecimal getTotalLeaseQuantity() {
return totalLeaseQuantity;
}
public void setTotalLeaseQuantity(BigDecimal totalLeaseQuantity) {
this.totalLeaseQuantity = totalLeaseQuantity;
}
public BigDecimal getTotalReturnQuantity() {
return totalReturnQuantity;
}
public void setTotalReturnQuantity(BigDecimal totalReturnQuantity) {
this.totalReturnQuantity = totalReturnQuantity;
}
public BigDecimal getDifferenceQuantity() {
return differenceQuantity;
}
public void setDifferenceQuantity(BigDecimal differenceQuantity) {
this.differenceQuantity = differenceQuantity;
}
}

View File

@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -44,20 +45,20 @@ public class ProjectCostServiceImpl implements ProjectCostService {
@Autowired
private ProjectCostDao projectCostDao;
@Autowired
private NewSettlementService newSettlementService;
@Autowired
private PlanApplicationDao planApplicationDao;
// 定义两个格式化器输入格式带时分秒输出格式仅年月日
private static final DateTimeFormatter INPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* 安全转换为Double类型
*
*
* @param obj 要转换的对象
* @param defaultValue 默认值
* @return 转换后的Double值
@ -91,7 +92,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
/**
* 安全转换为Integer类型
*
*
* @param obj 要转换的对象
* @param defaultValue 默认值
* @return 转换后的Integer值
@ -351,18 +352,18 @@ public class ProjectCostServiceImpl implements ProjectCostService {
LocalDateTime endtime = LocalDateTime.parse("2025-05-26 14:21:00", formatter);
long daysBetween = java.time.Duration.between(operateTime, endtime).toDays();
System.err.println(daysBetween);
}
@Override
public Map<String, Object> calculateSettlement(ProjectLeaseCostDetail o) {
return newSettlementService.getNewSettlement(o);
}
public Map<String, Object> calculateSettlement2(ProjectLeaseCostDetail o) {
// 获取领料明细
List<ProjectLeaseCostDetail> leaseDetails = queryProjectLeaseDetails(o);
// 获取退料明细
@ -440,7 +441,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
startDate = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
endDate = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
}
// 对每种物资类型进行计算
for (Map.Entry<String, List<ProjectLeaseCostDetail>> entry : groupedByMachineType.entrySet()) {
boolean add=true;
@ -450,7 +451,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if("3627".equals(machineTypeId)) {
System.err.println(machineTypeId);
}
// 按操作时间排序
items.sort(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime,
Comparator.nullsFirst(Comparator.naturalOrder())));
@ -473,7 +474,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 第一步处理统计期间开始之前的所有操作计算期初在用数量
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter formatter_day = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (ProjectLeaseCostDetail item : items) {
if (item == null || item.getOperateTime() == null) {
@ -498,7 +499,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
}
System.out.println("物资ID=" + machineTypeId + " 期初在用数量: " + currentCount);
// 如果期初在用数量大于0需要计算从统计开始时间到第一个操作时间或统计结束时间的费用
if (currentCount > 0) {
// 找到统计期间内的第一个操作时间
@ -519,8 +520,8 @@ public class ProjectCostServiceImpl implements ProjectCostService {
onlyAdd=false;
}
}
if (!operateTime.isBefore(startDate) && !operateTime.isAfter(endDate)) {
if (firstOperateTimeInPeriod == null || operateTime.isBefore(firstOperateTimeInPeriod)) {
firstOperateTimeInPeriod = operateTime;
@ -531,8 +532,8 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 如果统计期间内有操作计算从开始时间到第一个操作时间的费用
// 如果统计期间内没有操作计算从开始时间到结束时间的费用
LocalDateTime endTimeForInitialSegment = firstOperateTimeInPeriod != null ? firstOperateTimeInPeriod : endDate;
long daysBetween = getDay(startDate, endTimeForInitialSegment);
LocalDateTime startTimes = LocalDateTime.parse(o.getStartTime()+" 00:00:01", formatter);
if(!onlyAdd) {
@ -541,7 +542,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
add=false;
}
}
LocalDateTime lastTimes = LocalDateTime.parse(o.getEndTime()+" 23:59:59", formatter);
String parsedDateOnly = formatLocalDateTimeToDate(lastTimes);
String end_times = formatLocalDateTimeToDate(endTimeForInitialSegment);
@ -551,14 +552,14 @@ public class ProjectCostServiceImpl implements ProjectCostService {
}else {
ProjectLeaseCostDetail item=items.get(items.size()-1);
LocalDateTime operateTime = LocalDateTime.parse(item.getOperateTime(), formatter);
//判断当前数据是最后一条数据 =====
if(2==item.getOperateType() && operateTime.equals(endTimeForInitialSegment)) {
daysBetween+=1;
}
}
}
if (daysBetween > 0) {
@ -607,7 +608,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 判断操作类型1-领料2-退料
boolean isLease = (item.getOperateType() == null || item.getOperateType() != 2);
int quantity = 0;
// 计算上一个时间点到当前操作时间的租赁费用
if (currentCount > 0 && !previousTime.equals(operateTime)) {
if("3627".equals(machineTypeId)) {
@ -633,25 +634,25 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (daysBetween < 1) {
daysBetween = 1;
}
if(add) {
if(parsedDateOnly.equals(end_times)) {
daysBetween+=1;
}else {
//计算--
if(i==items.size()-1 && 2==item.getOperateType()) {
long datadelNum = item.getReturnNum() != null ? item.getReturnNum() : 0;
if(currentCount==datadelNum) {
daysBetween+=1;
}
}
}
}
//
//
// 计算该时间段的租赁费用
double segmentAmount = currentCount * unitPrice * daysBetween;
totalItemAmount += segmentAmount;
@ -702,7 +703,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if (currentCount > 0 && !previousTime.equals(endDate)) {
// 计算两个时间点之间的天数
long daysBetween =getDay(previousTime, endDate);
LocalDateTime lastTimes = LocalDateTime.parse(o.getEndTime()+" 23:59:59", formatter);
String parsedDateOnly = formatLocalDateTimeToDate(lastTimes);
String end_times = formatLocalDateTimeToDate(previousTime);
@ -726,8 +727,8 @@ public class ProjectCostServiceImpl implements ProjectCostService {
if(add) {
daysBetween+=1;
}
}
// 计算该时间段的租赁费用
@ -814,21 +815,21 @@ public class ProjectCostServiceImpl implements ProjectCostService {
result.put("totalAmount", totalAmount); // 总金额
return result;
}
/**
* 新的结算逻辑
*
*
*
*
*/
public Map<String, Object> getNewSettlement() {
Map<String, Object> result = new HashMap<>();
return result;
}
/**
* 核心方法将LocalDateTime格式化为yyyy-MM-dd字符串
* @param dateTime 待格式化的LocalDateTime对象
@ -844,9 +845,9 @@ public class ProjectCostServiceImpl implements ProjectCostService {
LocalDate startDate = operateTime.toLocalDate();
LocalDate endDate = endtime.toLocalDate();
long naturalDays = ChronoUnit.DAYS.between(startDate, endDate);
System.out.println("自然日天数差(正确结果):" + naturalDays);
System.out.println("自然日天数差(正确结果):" + naturalDays);
return naturalDays;
}
@Override
@ -982,6 +983,13 @@ public class ProjectCostServiceImpl implements ProjectCostService {
List<ProjectLeaseCostDetail> leaseDetails = queryProjectLeaseDetails(queryParam);
List<ProjectLeaseCostDetail> returnDetails = queryProjectReturnDetails(queryParam);
//同一天的统一类型的机具进行合并
leaseDetails = mergeByDay(leaseDetails,1);
returnDetails = mergeByDay(returnDetails,2);
//计算差额
leaseDetails =calculateMaterialDifference(leaseDetails, returnDetails);
List<ProjectLeaseCostDetail> allDetails = new ArrayList<>();
if (leaseDetails != null) {
allDetails.addAll(leaseDetails);
@ -1064,6 +1072,142 @@ public class ProjectCostServiceImpl implements ProjectCostService {
return calculation;
}
/**
* 计算领退料差额
* @param leaseDetails 领料明细列表
* @param returnDetails 退料明细列表
* @return 计算后的领料明细列表包含差额
*/
public List<ProjectLeaseCostDetail> calculateMaterialDifference(
List<ProjectLeaseCostDetail> leaseDetails,
List<ProjectLeaseCostDetail> returnDetails) {
// 1. 按物料类型分组领料数据
Map<Integer, List<ProjectLeaseCostDetail>> leaseByMaterial =
leaseDetails.stream()
.sorted(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime))
.collect(Collectors.groupingBy(
ProjectLeaseCostDetail::getMachineTypeId,
LinkedHashMap::new, // 保持顺序
Collectors.toList()
));
// 2. 按物料类型分组退料数据
Map<Integer, List<ProjectLeaseCostDetail>> returnByMaterial =
returnDetails.stream()
.sorted(Comparator.comparing(ProjectLeaseCostDetail::getOperateTime))
.collect(Collectors.groupingBy(
ProjectLeaseCostDetail::getMachineTypeId,
LinkedHashMap::new,
Collectors.toList()
));
// 3. 处理每个物料类型
List<ProjectLeaseCostDetail> result = new ArrayList<>();
for (Map.Entry<Integer, List<ProjectLeaseCostDetail>> entry : leaseByMaterial.entrySet()) {
Integer materialType = entry.getKey();
List<ProjectLeaseCostDetail> materialLeases = entry.getValue();
List<ProjectLeaseCostDetail> materialReturns =
returnByMaterial.getOrDefault(materialType, new ArrayList<>());
// 计算该物料的累计差额
List<ProjectLeaseCostDetail> calculated =
calculateForSingleMaterial(materialLeases, materialReturns);
result.addAll(calculated);
}
return result;
}
/**
* 计算单个物料的领退料差额
*/
private List<ProjectLeaseCostDetail> calculateForSingleMaterial(
List<ProjectLeaseCostDetail> leases,
List<ProjectLeaseCostDetail> returns) {
List<ProjectLeaseCostDetail> result = new ArrayList<>();
// 初始化累计量
BigDecimal totalReturn = BigDecimal.ZERO;
// 累计退料
for (ProjectLeaseCostDetail detail : returns) {
BigDecimal returnQty = detail.getReturnNum() != null ?
BigDecimal.valueOf(detail.getReturnNum()) : BigDecimal.ZERO;
totalReturn = totalReturn.add(returnQty);
}
// 按时间顺序处理每次领料
for (ProjectLeaseCostDetail lease : leases) {
//比较当前退料数量和领料数量
if(BigDecimal.valueOf(lease.getLeaseNum()).compareTo(totalReturn)>=0){
lease.setDifferenceQuantity(BigDecimal.valueOf(lease.getLeaseNum()).subtract(totalReturn));
totalReturn = BigDecimal.ZERO;
}else {
lease.setDifferenceQuantity(BigDecimal.ZERO);
//获取剩余的退料数量
totalReturn = totalReturn.subtract(BigDecimal.valueOf(lease.getLeaseNum()));
}
result.add(lease);
}
return result;
}
/**
* 根据 operateDate 按天合并累加 leaseNum
*/
public List<ProjectLeaseCostDetail> mergeByDay(List<ProjectLeaseCostDetail> leases, int i) {
List<ProjectLeaseCostDetail> leasesNew = new ArrayList<>();
// 使用 Map 按日期分组,同一天的合并一起
Map<LocalDate, ProjectLeaseCostDetail> mergedMap = new LinkedHashMap<>();
for (ProjectLeaseCostDetail returnDetail : leases) {
if ("牵张设备".equals(returnDetail.getMachineCodeName()) ||"施工机械".equals(returnDetail.getMachineCodeName()) ||"仪器设备".equals(returnDetail.getMachineCodeName())){
leasesNew.add(returnDetail);
}else {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String dateOnly = returnDetail.getOperateTime().substring(0, 10);
LocalDate dateKey = LocalDate.parse(dateOnly,
formatter);
if (mergedMap.containsKey(dateKey)) {
// 已存在该日期的记录合并数量
ProjectLeaseCostDetail existing = mergedMap.get(dateKey);
if (i==1){
// 累加 leaseNum
existing.setLeaseNum(
(existing.getLeaseNum() != null ? existing.getLeaseNum() : 0) +
(returnDetail.getLeaseNum() != null ? returnDetail.getLeaseNum() : 0)
);
}else {
// 累加 leaseNum
existing.setReturnNum(
(existing.getReturnNum() != null ? existing.getReturnNum() : 0) +
(returnDetail.getReturnNum() != null ? returnDetail.getReturnNum() : 0)
);
}
} else {
// 新日期的记录创建副本避免修改原对象
mergedMap.put(dateKey, returnDetail);
}
}
}
//保存合并后的数据
for (Map.Entry<LocalDate, ProjectLeaseCostDetail> entry : mergedMap.entrySet()) {
ProjectLeaseCostDetail materialLeases = entry.getValue();
leasesNew.add(materialLeases);
}
return leasesNew;
}
@Override
public boolean deleteCalculation(Integer id) {
return projectCostDao.deleteCalculation(id) > 0;
@ -1071,7 +1215,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
/**
* 封装导出Excel的方法适用于只有HttpServletResponse的情况
*
*
* @param fileName 文件名
* @param sheetName sheet名称
* @param headers 表头
@ -1914,46 +2058,234 @@ public class ProjectCostServiceImpl implements ProjectCostService {
// 准备Excel数据
String fileName = "领退记录表_" + calculation.getProjectName() + "_" + calculation.getId() + ".xls";
String sheetName = "领退记录表";
String sheetName = "领用、差缺明细表";
String sheetName2 = "退料明细表";
// 表头 - 增加规格型号字段
String[] headers = { "序号", "物资类型", "规格型号", "操作类型", "操作时间", "数量", "单位", "操作人", "任务编号" };
/*String[] headers = { "序号", "物资类型", "规格型号", "操作类型", "操作时间", "数量", "单位", "操作人", "任务编号" };*/
String[] headers = { "领料日期", "工程名称", "库房", "类别", "机具设备名称", "规格型号", "编码",
"新编码", "单位", "数量", "差额", "租赁单位", "备注" };
String[] headers2 = { "退料工程名称", "退料单位", "退料日期", "库房", "类别", "机具设备名称", "规格",
"编号", "单位", "数量", "备注" };
// 列宽 - 添加规格型号列宽
int[] widths = { 256 * 5, 256 * 15, 256 * 15, 256 * 10, 256 * 18, 256 * 10, 256 * 10, 256 * 10, 256 * 15 };
int[] widths = { 256 * 15,256 * 30,256 * 15,256 * 15,256 * 20,256 * 20,256 * 20,256 * 10,256 * 10, 256 * 10, 256 * 10, 256 * 20, 256 * 10 };
int[] widths2 = { 256 * 30,256 * 15,256 * 15,256 * 15,256 * 18,256 * 20,256 * 20,256 * 10,256 * 10, 256 * 10, 256 * 10 };
// 数据格式1:String left; 2:String center; 3:String right; 4:int right; 5:float
// right
int[] formats = { 4, 2, 2, 2, 2, 4, 2, 2, 2 };
int[] formats = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2 };
int[] formats2 = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 2 };
// 准备数据
List<Map<String, Object>> dataList = new ArrayList<>();
List<Map<String, Object>> dataList2 = new ArrayList<>();
// 获取所有物资的领退记录
List<ProjectCostCalculationDetail> details = calculation.getDetails();
if (details != null && !details.isEmpty()) {
int index = 1;
for (ProjectCostCalculationDetail detail : details) {
List<ProjectLeaseCostDetail> operRecords = detail.getDetails();
if (operRecords != null && !operRecords.isEmpty()) {
for (ProjectLeaseCostDetail record : operRecords) {
Map<String, Object> row = new HashMap<>();
row.put("序号", index++);
row.put("物资类型", record.getMachineTypeName());
row.put("规格型号", record.getMachineModel()); // 添加规格型号字段
row.put("操作类型", record.getOperateType() == 1 ? "领料" : "退料");
row.put("操作时间", record.getOperateTime());
row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum());
row.put("单位", record.getMachineUnit());
row.put("操作人", record.getOperatePersonName());
row.put("任务编号", record.getTaskCode());
dataList.add(row);
if (record.getOperateType() == 1){
Map<String, Object> row = new HashMap<>();
row.put("领料日期", record.getOperateTime().substring(0,10));
row.put("工程名称", calculation.getProjectName());
if ("牵张设备".equals(record.getMachineCodeName()) ||"施工机械".equals(record.getMachineCodeName()) ||"仪器设备".equals(record.getMachineCodeName())){
row.put("库房", "设备库");
}else {
row.put("库房", "机具库");
}
row.put("类别", record.getMachineCodeName()); // 添加规格型号字段
row.put("机具设备名称", record.getMachineTypeName());
row.put("规格型号", record.getMachineModel());
row.put("编码", record.getOldMachineCode());
row.put("新编码", record.getMachineCode());
row.put("单位", record.getMachineUnit());
row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum());
row.put("差额", record.getDifferenceQuantity());
row.put("租赁单位", record.getBsName());
row.put("备注",null);
dataList.add(row);
}else {
Map<String, Object> row = new HashMap<>();
row.put("退料工程名称", calculation.getProjectName());
row.put("退料单位", record.getBsName());
row.put("退料日期", record.getOperateTime().substring(0,10)); // 添加规格型号字段
if ("牵张设备".equals(record.getMachineCodeName()) ||"施工机械".equals(record.getMachineCodeName()) ||"仪器设备".equals(record.getMachineCodeName())){
row.put("库房", "设备库");
}else {
row.put("库房", "机具库");
}
row.put("类别", record.getMachineCodeName()); // 添加规格型号字段
row.put("机具设备名称", record.getMachineTypeName());
row.put("规格", record.getMachineModel());
row.put("编号", record.getOldMachineCode());
row.put("单位", record.getMachineUnit());
row.put("数量", record.getOperateType() == 1 ? record.getLeaseNum() : record.getReturnNum());
row.put("备注",null);
dataList2.add(row);
}
}
}
}
}
// 设置文件名
String filename = "";
try {
filename = URLEncoder.encode(fileName, "UTF-8");
} catch (Exception e) {
filename = fileName;
}
// 设置响应头
response.setHeader("Content-disposition", "attachment;filename=" + filename);
response.setContentType("application/vnd.ms-excel");
response.setHeader("Pragma", "No-cache");
// 创建一个工作簿
HSSFWorkbook wb = new HSSFWorkbook();
// 创建一个sheet
HSSFSheet sheet = wb.createSheet(sheetName);
// 创建一个sheet
HSSFSheet sheet2 = wb.createSheet(sheetName2);
// 调用导出方法
exportExcel(fileName, sheetName, headers, widths, formats, dataList, response);
exportExcelNew(wb, sheet, headers, widths, formats, dataList, response);
exportExcelNew(wb, sheet2, headers2, widths2, formats2, dataList2, response);
// 输出文件
OutputStream ouputStream = response.getOutputStream();
wb.write(ouputStream);
ouputStream.flush();
ouputStream.close();
}
/**
* 封装导出Excel的方法适用于只有HttpServletResponse的情况
*
* @param wb 文件名
* @param sheet sheet名称
* @param headers 表头
* @param widths 列宽
* @param formats 数据格式
* @param dataList 数据列表
* @param response HttpServletResponse对象
* @throws Exception 导出异常
*/
private void exportExcelNew(HSSFWorkbook wb, HSSFSheet sheet, String[] headers, int[] widths, int[] formats,
List<Map<String, Object>> dataList, javax.servlet.http.HttpServletResponse response) throws Exception {
try {
// 创建表头
int headerrow = 0;
if (headers != null) {
HSSFRow row = sheet.createRow(headerrow);
// 设置表头行高 - 调高表头高度
row.setHeight((short) 500); // 设置为原高度的约2倍
// 表头样式
HSSFCellStyle style = wb.createCellStyle();
HSSFFont font = wb.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
font.setFontName("微软雅黑");
font.setFontHeightInPoints((short) 11);
style.setFont(font);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 设置淡黄色背景
style.setFillForegroundColor((short) 0x2B); // 修改为更明确的淡黄色0x2B是淡黄色(light yellow)
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
for (int i = 0; i < headers.length; i++) {
sheet.setColumnWidth((short) i, (short) widths[i]);
HSSFCell cell = row.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(style);
}
headerrow++;
}
// 表格主体
if (dataList != null) {
List<HSSFCellStyle> styleList = new ArrayList<HSSFCellStyle>();
if (headers != null) {
for (int i = 0; i < headers.length; i++) { // 列数
HSSFCellStyle style = wb.createCellStyle();
HSSFFont font = wb.createFont();
font.setFontName("微软雅黑");
font.setFontHeightInPoints((short) 10);
style.setFont(font);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
// 添加垂直居中对齐
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
if (formats[i] == 1) {
style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
} else if (formats[i] == 2) {
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
} else if (formats[i] == 3) {
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
} else if (formats[i] == 4) {
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
// int类型
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
} else if (formats[i] == 5) {
// float类型
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));
} else if (formats[i] == 6) {
// 百分比类型
style.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%"));
}
styleList.add(style);
}
}
for (Map<String, Object> stringObjectMap : dataList) { // 行数
HSSFRow row = sheet.createRow(headerrow);
int j = 0;
for (String key : headers) { // 列数
HSSFCell cell = row.createCell(j);
Object o = stringObjectMap.get(key);
if (o == null || "".equals(o)) {
cell.setCellValue("");
} else if (formats[j] == 4) {
// int
try {
cell.setCellValue(Long.parseLong(String.valueOf(o)));
} catch (Exception e) {
cell.setCellValue(0);
}
} else if (formats[j] == 5 || formats[j] == 6) {
// float
try {
cell.setCellValue(Double.parseDouble(String.valueOf(o)));
} catch (Exception e) {
cell.setCellValue(0.0);
}
} else {
cell.setCellValue(String.valueOf(o));
}
cell.setCellStyle(styleList.get(j));
j++;
}
headerrow++;
}
}
} catch (Exception e) {
throw new Exception("导出Excel异常", e);
}
}
/**
@ -1968,4 +2300,4 @@ public class ProjectCostServiceImpl implements ProjectCostService {
}
return totalDays;
}
}
}