This commit is contained in:
zt
2025-08-22 10:24:00 +08:00
parent cf5d71d528
commit 05c1a37704
16 changed files with 501 additions and 13 deletions

View File

@ -5,12 +5,35 @@ import jakarta.annotation.Resource;
import org.dromara.bigscreen.service.MoneyBigScreenService;
import org.dromara.common.core.domain.R;
import org.dromara.project.domain.vo.project.BusProjectGisVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.bigscreen.domain.vo.MoneyContractCountVo;
import org.dromara.bigscreen.domain.vo.MoneyPayVo;
import org.dromara.bigscreen.domain.vo.MoneyTotalAmountVo;
import org.dromara.common.core.domain.R;
import org.dromara.ctr.domain.CtrExpensesContract;
import org.dromara.ctr.domain.CtrIncomeContract;
import org.dromara.ctr.service.ICtrExpensesContractService;
import org.dromara.ctr.service.ICtrIncomeContractService;
import org.dromara.out.domain.OutSettlementValueOwner;
import org.dromara.out.domain.OutSettlementValueSubcontract;
import org.dromara.out.service.IOutSettlementValueOwnerService;
import org.dromara.out.service.IOutSettlementValueSubcontractService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 资金大屏
*
@ -19,11 +42,21 @@ import java.util.List;
*/
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/money/big/screen")
public class MoneyBigScreenController {
@Resource
private MoneyBigScreenService moneyBigScreenService;
private final MoneyBigScreenService moneyBigScreenService;
private final IOutSettlementValueOwnerService settlementValueOwnerService;
private final IOutSettlementValueSubcontractService settlementValueSubcontractService;
private final ICtrIncomeContractService incomeContractService;
private final ICtrExpensesContractService expensesContractService;
private final BigDecimal HUNDRED = new BigDecimal(100);
private final BigDecimal FIRST_PHASE = new BigDecimal(1000000);
private final BigDecimal SECOND_PHASE = new BigDecimal(5000000);
private final BigDecimal THIRD_PHASE = new BigDecimal(10000000);
/**
* 查询项目位置列表
@ -33,4 +66,235 @@ public class MoneyBigScreenController {
public R<List<BusProjectGisVo>> getProjectGis() {
return R.ok(moneyBigScreenService.getProjectGis());
}
/**
* 应收实收
*/
@GetMapping("/income/pay")
public R<MoneyPayVo> incomePay() {
Map<String, LocalDate> monthStartAndEnd = getMonthStartAndEnd();
LocalDate startDate = monthStartAndEnd.get("start");
LocalDate endDate = monthStartAndEnd.get("end");
List<OutSettlementValueOwner> list = settlementValueOwnerService.list();
BigDecimal planAmount = list.stream()
.map(OutSettlementValueOwner::getSettlementValue)
.filter(java.util.Objects::nonNull) // 过滤掉 null 值
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 筛选当月记录用于实际金额计算(包含开始和结束日期)
List<OutSettlementValueOwner> monthlyList = list.stream()
.filter(item -> {
LocalDate settlementDate = item.getSettlementDate();
return settlementDate != null &&
!settlementDate.isBefore(startDate) &&
!settlementDate.isAfter(endDate);
}).toList();
// 根据项目ID分组并统计当月金额
Map<Long, BigDecimal> projectMonthlyAmountMap = monthlyList.stream()
.collect(Collectors.groupingBy(
OutSettlementValueOwner::getProjectId,
Collectors.reducing(
BigDecimal.ZERO,
OutSettlementValueOwner::getSettlementValue,
BigDecimal::add
)
));
BigDecimal actualAmount =BigDecimal.ZERO;
for (Long projectId : projectMonthlyAmountMap.keySet()) {
CtrIncomeContract contract = incomeContractService.getOne(Wrappers.lambdaQuery(CtrIncomeContract.class)
.eq(CtrIncomeContract::getProjectId, projectId)
.last("limit 1")
);
actualAmount = actualAmount.add(projectMonthlyAmountMap.get(projectId).multiply(contract.getPayRatio()).divide(HUNDRED));
}
return R.ok(new MoneyPayVo(planAmount, actualAmount));
}
/**
* 应付实付
*/
@GetMapping("/expenses/pay")
public R<MoneyPayVo> expensesPay() {
Map<String, LocalDate> monthStartAndEnd = getMonthStartAndEnd();
LocalDate startDate = monthStartAndEnd.get("start");
LocalDate endDate = monthStartAndEnd.get("end");
List<OutSettlementValueSubcontract> list = settlementValueSubcontractService.list(Wrappers
.lambdaQuery(OutSettlementValueSubcontract.class)
);
BigDecimal planAmount = list.stream()
.map(OutSettlementValueSubcontract::getSettlementValue)
.filter(java.util.Objects::nonNull) // 过滤掉 null 值
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 筛选当月记录用于实际金额计算(包含开始和结束日期)
List<OutSettlementValueSubcontract> monthlyList = list.stream()
.filter(item -> {
LocalDate settlementDate = item.getSettlementDate();
return settlementDate != null &&
!settlementDate.isBefore(startDate) &&
!settlementDate.isAfter(endDate);
}).toList();
// 根据分包商Id分组并统计金额
Map<String, BigDecimal> projectAmountMap = monthlyList.stream()
.collect(Collectors.groupingBy(
OutSettlementValueSubcontract::getContractCode, // 根据合同编号分组
Collectors.reducing(
BigDecimal.ZERO,
OutSettlementValueSubcontract::getSettlementValue, // 获取金额字段
BigDecimal::add // 对金额求和
)
));
BigDecimal actualAmount =BigDecimal.ZERO;
for (String contractCode: projectAmountMap.keySet()) {
CtrExpensesContract contract = expensesContractService.getOne(Wrappers.lambdaQuery(CtrExpensesContract.class)
.eq(CtrExpensesContract::getContractCode, contractCode)
.last("limit 1")
);
actualAmount = actualAmount.add(projectAmountMap.get(contractCode).multiply(contract.getPayRatio()).divide(HUNDRED));
}
return R.ok(new MoneyPayVo(planAmount, actualAmount));
}
/**
* 收入合同分析
*/
@GetMapping("/income/analyze")
public R<MoneyContractCountVo> incomeAnalyze() {
List<CtrIncomeContract> list = incomeContractService.list();
// 按金额区间统计数量
Integer lessThan1M = (int)list.stream()
.filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(FIRST_PHASE) < 0)
.count();
Integer between1MAnd5M = (int)list.stream()
.filter(contract -> contract.getAmount() != null
&& contract.getAmount().compareTo(FIRST_PHASE) >= 0
&& contract.getAmount().compareTo(SECOND_PHASE) < 0)
.count();
Integer between5MAnd10M = (int)list.stream()
.filter(contract -> contract.getAmount() != null
&& contract.getAmount().compareTo(SECOND_PHASE) >= 0
&& contract.getAmount().compareTo(THIRD_PHASE) < 0)
.count();
Integer greaterThanOrEqualTo10M = (int)list.stream()
.filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(THIRD_PHASE) >= 0)
.count();
return R.ok(new MoneyContractCountVo(lessThan1M, between1MAnd5M, between5MAnd10M, greaterThanOrEqualTo10M));
}
/**
* 支出合同分析
*/
@GetMapping("/expenses/analyze")
public R<MoneyContractCountVo> expensesAnalyze() {
List<CtrExpensesContract> list = expensesContractService.list();
// 按金额区间统计数量
Integer lessThan1M = (int)list.stream()
.filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(FIRST_PHASE) < 0)
.count();
Integer between1MAnd5M = (int)list.stream()
.filter(contract -> contract.getAmount() != null
&& contract.getAmount().compareTo(FIRST_PHASE) >= 0
&& contract.getAmount().compareTo(SECOND_PHASE) < 0)
.count();
Integer between5MAnd10M = (int)list.stream()
.filter(contract -> contract.getAmount() != null
&& contract.getAmount().compareTo(SECOND_PHASE) >= 0
&& contract.getAmount().compareTo(THIRD_PHASE) < 0)
.count();
Integer greaterThanOrEqualTo10M = (int)list.stream()
.filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(THIRD_PHASE) >= 0)
.count();
return R.ok(new MoneyContractCountVo(lessThan1M, between1MAnd5M, between5MAnd10M, greaterThanOrEqualTo10M));
}
/**
* 合同金额
*/
@GetMapping("/totalAmount")
public R<MoneyTotalAmountVo> totalAmount() {
List<CtrIncomeContract> incomeContracts = incomeContractService.list();
BigDecimal incomeTotalAmount = incomeContracts.stream()
.filter(contract -> contract.getAmount() != null)
.map(CtrIncomeContract::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
List<CtrExpensesContract> expensesContracts = expensesContractService.list();
BigDecimal expensesTotalAmount = expensesContracts.stream()
.filter(contract -> contract.getAmount() != null)
.map(CtrExpensesContract::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
//利润
BigDecimal profitAmount = incomeTotalAmount.subtract(expensesTotalAmount);
//todo: 工程变更计算 不清楚逻辑先设为0
BigDecimal changeAmount = BigDecimal.ZERO;
return R.ok(new MoneyTotalAmountVo(incomeTotalAmount, expensesTotalAmount,profitAmount,changeAmount));
}
/**
* 获取当前月份的开始时间和结束时间
* @return
*/
public Map<String, LocalDate> getMonthStartAndEnd() {
LocalDate now = LocalDate.now();
LocalDate start = now.with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = now.with(TemporalAdjusters.lastDayOfMonth());
return new HashMap<String, LocalDate>() {{
put("start", start);
put("end", end);
}};
}
}

View File

@ -8,6 +8,18 @@ import org.dromara.common.core.domain.R;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.bigscreen.domain.vo.ProjectLandVo;
import org.dromara.common.core.domain.R;
import org.dromara.land.domain.BusLandBlock;
import org.dromara.land.domain.BusLandTransferLedger;
import org.dromara.land.service.IBusLandBlockService;
import org.dromara.land.service.IBusLandTransferLedgerService;
import org.dromara.message.service.IMsgNotifyTargetDetailService;
import org.dromara.tender.domain.vo.BusBiddingPlanAnnexVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -16,6 +28,12 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 项目级大屏
*
@ -24,18 +42,62 @@ import java.util.List;
*/
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/project/big/screen")
public class ProjectBigScreenController {
@Resource
private ProjectBigScreenService projectBigScreenService;
private final IBusLandTransferLedgerService busLandTransferLedgerService;
// @GetMapping("/{projectId}")
// public R<BusBiddingPlanAnnexVo> getInfo(@NotNull(message = "主键不能为空")
// @PathVariable Long id) {
// return R.ok(busBiddingPlanAnnexService.queryById(id));
// }
private final IBusLandBlockService busLandBlockService;
@GetMapping("/{projectId}")
public R<List<ProjectLandVo>> landCount(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) {
List<BusLandTransferLedger> levelList = busLandTransferLedgerService.list(Wrappers.lambdaQuery(BusLandTransferLedger.class)
.eq(BusLandTransferLedger::getProjectId, projectId));
// 根据 landBlockId 分组,并对 designArea 和 transferAea 进行求和
Map<Long, Map<String, BigDecimal>> groupedResult = levelList.stream()
.collect(Collectors.groupingBy(
BusLandTransferLedger::getLandBlockId, // 按 landBlockId 分组
Collectors.collectingAndThen(
Collectors.toList(),
list -> {
BigDecimal designAreaSum = list.stream()
.map(BusLandTransferLedger::getDesignArea)
.filter(java.util.Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal transferAreaSum = list.stream()
.map(BusLandTransferLedger::getTransferAea)
.filter(java.util.Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 返回一个包含两个求和结果的 Map
return Map.of(
"designArea", designAreaSum,
"transferArea", transferAreaSum
);
}
)
));
List<ProjectLandVo> result = new ArrayList<>();
for(Long landBlockId : groupedResult.keySet()){
ProjectLandVo projectLandVo = new ProjectLandVo();
BusLandBlock landBlock = busLandBlockService.getById(landBlockId);
projectLandVo.setLandName(landBlock.getLandName());
projectLandVo.setTransferArea(groupedResult.get(landBlockId).get("transferArea"));
projectLandVo.setDesignArea(groupedResult.get(landBlockId).get("designArea"));
result.add(projectLandVo);
}
return R.ok(result);
}
/**
* 查询项目天气

View File

@ -0,0 +1,32 @@
package org.dromara.bigscreen.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoneyContractCountVo {
/**
* 100W以下
*/
private Integer firstCount;
/**
* 100W-500W
*/
private Integer secondCount;
/**
* 500W-1000W
*/
private Integer thirdCount;
/**
* 1000W以上
*/
private Integer fourthCount;
}

View File

@ -0,0 +1,28 @@
package org.dromara.bigscreen.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* 支付KPI
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoneyPayVo {
/**
* 应收
*/
private BigDecimal planAmount;
/**
* 实收
*/
private BigDecimal actualAmount;
}

View File

@ -0,0 +1,36 @@
package org.dromara.bigscreen.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoneyTotalAmountVo {
/**
* 收入总金额
*/
private BigDecimal incomeTotalAmount;
/**
* 支出总金额
*/
private BigDecimal expensesTotalAmount;
/**
* 利润
*/
private BigDecimal profitAmount;
/**
* 工程变更
*/
private BigDecimal changeAmount;
}

View File

@ -0,0 +1,25 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 土地流转
*/
@Data
public class ProjectLandVo {
/**
* 土地名称
*/
private String landName;
/**
* 规划面积
*/
private BigDecimal designArea;
/**
* 流转面积
*/
private BigDecimal transferArea;
}

View File

@ -48,6 +48,11 @@ public class CtrExpensesContract extends BaseEntity {
*/
private String contractSupplier;
/**
* 供应商Id
*/
private Long supplierId;
/**
* 分包内容
*/

View File

@ -49,6 +49,11 @@ public class CtrExpensesContractBo extends BaseEntity {
*/
private String contractSupplier;
/**
* 供应商Id
*/
private Long supplierId;
/**
* 分包内容
*/

View File

@ -68,6 +68,11 @@ public class CtrExpensesContractVo implements Serializable {
@ExcelProperty(value = "供应商")
private String contractSupplier;
/**
* 供应商Id
*/
private Long supplierId;
/**
* 分包内容
*/

View File

@ -3,6 +3,7 @@ package org.dromara.ctr.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -130,7 +131,14 @@ public class CtrExpensesContractServiceImpl extends ServiceImpl<CtrExpensesContr
* 保存前的数据校验
*/
private void validEntityBeforeSave(CtrExpensesContract entity){
//TODO 做一些数据校验,如唯一约束
//校验编号是否唯一
List<CtrExpensesContract> list = list(Wrappers.<CtrExpensesContract>lambdaQuery()
.eq(CtrExpensesContract::getContractCode, entity.getContractCode())
.ne(entity.getId() != null, CtrExpensesContract::getId, entity.getId())
);
if (CollectionUtil.isNotEmpty(list)) {
throw new ServiceException("保存合同信息失败,合同编号已存在");
}
}
/**

View File

@ -2,6 +2,7 @@ package org.dromara.ctr.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -10,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.ctr.domain.CtrExpensesContract;
import org.dromara.ctr.domain.CtrFile;
import org.dromara.ctr.service.ICtrFileService;
import org.springframework.stereotype.Service;
@ -128,7 +130,14 @@ public class CtrIncomeContractServiceImpl extends ServiceImpl<CtrIncomeContractM
* 保存前的数据校验
*/
private void validEntityBeforeSave(CtrIncomeContract entity){
//TODO 做一些数据校验,如唯一约束
//校验编号是否唯一
List<CtrIncomeContract> list = list(Wrappers.<CtrIncomeContract>lambdaQuery()
.eq(CtrIncomeContract::getContractCode, entity.getContractCode())
.ne(entity.getId() != null, CtrIncomeContract::getId, entity.getId())
);
if (CollectionUtil.isNotEmpty(list)) {
throw new ServiceException("保存合同信息失败,合同编号已存在");
}
}
/**

View File

@ -1,5 +1,8 @@
package org.dromara.land.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.land.domain.BusLandBlock;
import org.dromara.land.domain.BusLandTransferLedger;
import org.dromara.land.domain.vo.BusLandBlockVo;
import org.dromara.land.domain.bo.BusLandBlockBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -14,7 +17,7 @@ import java.util.List;
* @author Lion Li
* @date 2025-07-25
*/
public interface IBusLandBlockService {
public interface IBusLandBlockService extends IService<BusLandBlock> {
/**
* 查询地块信息

View File

@ -1,5 +1,7 @@
package org.dromara.land.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.land.domain.BusLandTransferLedger;
import org.dromara.land.domain.vo.BusLandTransferLedgerVo;
import org.dromara.land.domain.bo.BusLandTransferLedgerBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -14,7 +16,7 @@ import java.util.List;
* @author Lion Li
* @date 2025-07-25
*/
public interface IBusLandTransferLedgerService {
public interface IBusLandTransferLedgerService extends IService<BusLandTransferLedger> {
/**
* 查询项目土地流转台账

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@ -34,7 +35,7 @@ import java.util.stream.Collectors;
*/
@RequiredArgsConstructor
@Service
public class BusLandBlockServiceImpl implements IBusLandBlockService {
public class BusLandBlockServiceImpl extends ServiceImpl<BusLandBlockMapper, BusLandBlock> implements IBusLandBlockService {
public static final String LAND_PREFIX = "TD-DK-";

View File

@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@ -34,7 +35,8 @@ import java.util.*;
*/
@RequiredArgsConstructor
@Service
public class BusLandTransferLedgerServiceImpl implements IBusLandTransferLedgerService {
public class BusLandTransferLedgerServiceImpl extends ServiceImpl<BusLandTransferLedgerMapper, BusLandTransferLedger>
implements IBusLandTransferLedgerService {
private final BusLandTransferLedgerMapper baseMapper;

View File

@ -111,6 +111,7 @@ public class BusBiddingPlanServiceImpl extends ServiceImpl<BusBiddingPlanMapper,
lqw.eq(bo.getPrice() != null, BusBiddingPlan::getPrice, bo.getPrice());
lqw.eq(bo.getContractPrice() != null, BusBiddingPlan::getContractPrice, bo.getContractPrice());
lqw.eq(StringUtils.isNotBlank(bo.getContent()), BusBiddingPlan::getContent, bo.getContent());
lqw.eq((bo.getStatus()!= null), BusBiddingPlan::getStatus, bo.getStatus());
return lqw;
}