进度、物资管理模块

This commit is contained in:
lcj
2025-09-06 15:30:57 +08:00
parent ff9f49b1d9
commit e0cc521291
25 changed files with 1062 additions and 117 deletions

View File

@ -30,10 +30,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -219,15 +216,15 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
// 子项目id列表
List<Long> subProjectIds = subProjectList.stream().map(BusProject::getId).toList();
// 计算集电线路
vo.setCollectorLinePercentage(BigDecimal.ZERO);
vo.setCollectorLinePercentage(BigDecimal.valueOf(0.00));
// 计算送出线路
vo.setExportLinePercentage(BigDecimal.ZERO);
vo.setExportLinePercentage(BigDecimal.valueOf(0.00));
// 计算升压站
vo.setSubstationPercentage(BigDecimal.ZERO);
vo.setSubstationPercentage(BigDecimal.valueOf(0.00));
// 计算光伏场区
vo.setAreaPercentage(BigDecimal.ZERO);
vo.setAreaPercentage(BigDecimal.valueOf(0.00));
// 计算道路
vo.setRoadPercentage(BigDecimal.ZERO);
vo.setRoadPercentage(BigDecimal.valueOf(0.00));
// 计算箱变
vo.setBoxTransformerPercentage(BigDecimal.ZERO);
// 获取集电线路、送出线路、升压站数据
@ -239,27 +236,63 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
if (CollUtil.isNotEmpty(progressCategoryList)) {
List<Long> categoryIds = progressCategoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = progressCategoryService.getLeafNodesByTopIds(categoryIds);
Map<String, List<PgsProgressCategory>> categoryMap = leafNodesByTopIds.stream()
Map<String, List<PgsProgressCategory>> categoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
// 计算集电线路
if (categoryMap.containsKey("集电线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("集电线路");
vo.setCollectorLinePercentage(getCompletedPercentage(categoryList));
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setCollectorLinePercentage(percentage);
}
}
// 计算送出线路
if (categoryMap.containsKey("送出线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("送出线路");
vo.setExportLinePercentage(getCompletedPercentage(categoryList));
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setExportLinePercentage(percentage);
}
}
// 计算升压站
if (categoryMap.containsKey("升压站")) {
List<PgsProgressCategory> categoryList = categoryMap.get("升压站");
vo.setSubstationPercentage(getCompletedPercentage(categoryList));
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setSubstationPercentage(percentage);
}
}
// 计算光伏场区
if (categoryMap.containsKey("光伏场区")) {
List<PgsProgressCategory> categoryList = categoryMap.get("光伏场区");
vo.setAreaPercentage(getCompletedPercentage(categoryList));
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setAreaPercentage(percentage);
}
}
}
// 计算道路
@ -269,7 +302,10 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
.ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list();
if (CollUtil.isNotEmpty(roadCategoryList)) {
vo.setRoadPercentage(getCompletedPercentage(roadCategoryList));
BigDecimal percentage = progressCategoryService.getCompletedPercentage(roadCategoryList);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setRoadPercentage(percentage);
}
}
// 计算箱变
List<PgsProgressCategory> boxTransformerCategoryList = progressCategoryService.lambdaQuery()
@ -278,7 +314,10 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
.ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list();
if (CollUtil.isNotEmpty(boxTransformerCategoryList)) {
vo.setBoxTransformerPercentage(getCompletedPercentage(boxTransformerCategoryList));
BigDecimal percentage = progressCategoryService.getCompletedPercentage(boxTransformerCategoryList);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setBoxTransformerPercentage(percentage);
}
}
// 计算总进度
vo.setTotalPercentage(
@ -288,6 +327,7 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
.add(vo.getAreaPercentage())
.add(vo.getRoadPercentage())
.add(vo.getBoxTransformerPercentage())
.divide(BigDecimal.valueOf(6), 2, RoundingMode.HALF_UP) // 保留两位小数
);
return vo;
}
@ -319,25 +359,4 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
}
}
/**
* 获取项目进度百分比
*
* @param categoryList 项目进度列表
* @return 项目进度百分比
*/
private BigDecimal getCompletedPercentage(List<PgsProgressCategory> categoryList) {
BigDecimal completedTotal = BigDecimal.ZERO;
BigDecimal allTotal = BigDecimal.ZERO;
for (PgsProgressCategory category : categoryList) {
BigDecimal completed = category.getCompleted();
BigDecimal total = category.getTotal();
if (PgsProgressUnitTypeEnum.NUMBER.getValue().equals(category.getUnitType())) {
completedTotal = completedTotal.add(completed);
} else if (PgsProgressUnitTypeEnum.PERCENTAGE.getValue().equals(category.getUnitType())) {
completedTotal = completedTotal.add(completed.divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP).multiply(total));
}
allTotal = allTotal.add(total);
}
return BigDecimalUtil.toPercentage(completedTotal, allTotal);
}
}

View File

@ -18,9 +18,11 @@ public class BigDecimalUtil {
*/
public static BigDecimal toPercentage(BigDecimal dividend, BigDecimal divisor) {
if (dividend == null || divisor == null || divisor.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
return BigDecimal.valueOf(0.00);
}
return dividend.divide(divisor, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
return dividend
.multiply(new BigDecimal("100"))
.divide(divisor, 2, RoundingMode.HALF_UP);
}
}

View File

@ -19,10 +19,7 @@ import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsGisVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsNumberVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsVo;
import org.dromara.materials.domain.vo.materials.*;
import org.dromara.materials.service.IMatMaterialsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -52,6 +49,24 @@ public class MatMaterialsController extends BaseController {
return materialsService.queryPageList(req, pageQuery);
}
/**
* 获取材料出/入库关联列表
*/
@SaCheckPermission("materials:materials:listRelevancy")
@GetMapping("/listRelevancy")
public TableDataInfo<MatMaterialsRelevancyInventoryVo> listRelevancy(MatMaterialsQueryReq req, PageQuery pageQuery) {
return materialsService.queryRelevancyOutPutList(req, pageQuery);
}
/**
* 获取材料使用详情列表
*/
@SaCheckPermission("materials:materials:listUseDetail")
@GetMapping("/listUseDetail")
public TableDataInfo<MatMaterialsUseDetailVo> listUseDetail(MatMaterialsQueryReq req, PageQuery pageQuery) {
return materialsService.queryUseDetailList(req, pageQuery);
}
/**
* 导出材料列表
*/
@ -59,8 +74,8 @@ public class MatMaterialsController extends BaseController {
@Log(title = "材料", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(MatMaterialsQueryReq req, HttpServletResponse response) {
List<MatMaterialsVo> list = materialsService.queryList(req);
ExcelUtil.exportExcel(list, "材料名称", MatMaterialsVo.class, response);
List<MatMaterialsExcelVo> list = materialsService.queryExcelList(req);
ExcelUtil.exportExcel(list, "材料名称", MatMaterialsExcelVo.class, response);
}
/**

View File

@ -15,11 +15,6 @@ public class MatMaterialsQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 5563677643070664671L;
/**
* 主键id
*/
private Long id;
/**
* 材料名称
*/

View File

@ -1,5 +1,7 @@
package org.dromara.materials.domain.dto.materialsinventory;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serial;
@ -19,16 +21,19 @@ public class MatMaterialsInventoryCreateReq implements Serializable {
/**
* 材料id
*/
@NotNull(message = "材料主键不能为空")
private Long materialsId;
/**
* 项目id
*/
@NotNull(message = "项目主键不能为空")
private Long projectId;
/**
* 出入库状态
*/
@NotBlank(message = "出/入库状态不能为空")
private String outPut;
/**

View File

@ -0,0 +1,76 @@
package org.dromara.materials.domain.vo.materials;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-05 22:02
*/
@Data
@ExcelIgnoreUnannotated
public class MatMaterialsExcelVo implements Serializable {
@Serial
private static final long serialVersionUID = 368467478399780659L;
@ExcelProperty(value = "材料名称")
private String materialsName;
@ExcelProperty(value = "计划数量")
private String quantityCount;
@ExcelProperty(value = {"入库登记", "供货单位"})
private String supplier;
@ExcelProperty(value = {"入库登记", "数量"})
private Long putNumber;
@ExcelProperty(value = {"入库登记", "签收人"})
private String signer;
@ExcelProperty(value = {"入库登记", "日期"})
private String putTime;
@ExcelProperty(value = {"出库登记", "接收单位"})
private String recipient;
@ExcelProperty(value = {"出库登记", "数量"})
private Long outNumber;
@ExcelProperty(value = {"出库登记", "出库人"})
private String operator;
@ExcelProperty(value = {"出库登记", "领用人"})
private String shipper;
@ExcelProperty(value = {"出库登记", "领用日期"})
private String receivingDate;
@ExcelProperty(value = {"到货剩余登记", "剩余量"})
private Long residue;
@ExcelProperty(value = {"到货剩余登记", "处理方式"})
private String disposition;
@ExcelProperty(value = {"使用登记", "使用部位"})
private String usePart;
@ExcelProperty(value = {"使用登记", "使用数量"})
private BigDecimal useNumber;
@ExcelProperty(value = {"使用登记", "使用日期"})
private String useTime;
@ExcelProperty(value = {"使用登记", "剩余量"})
private BigDecimal surplus;
@ExcelProperty(value = "备注")
private String remark;
}

View File

@ -0,0 +1,95 @@
package org.dromara.materials.domain.vo.materials;
import lombok.Data;
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-05 21:04
*/
@Data
public class MatMaterialsRelevancyInventoryVo implements Serializable {
@Serial
private static final long serialVersionUID = -4478461830960704369L;
/**
* 材料id
*/
private Long id;
/**
* 入库id
*/
private Long inventoryId;
/**
* 材料名称
*/
private String materialsName;
/**
* 项目id
*/
private Long projectId;
/**
* 出/入库的数量
*/
private Long number;
/**
* 剩余库存数量(记录最后一次操作留下的库存数)
*/
private Long residue;
/**
* 操作人(入库人、领料人)
*/
private String operator;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 公司信息
*/
private String companyName;
/**
* 表单编号
*/
private String formCode;
/**
* 规格型号名称
*/
private String typeSpecificationName;
/**
* 计量单位
*/
private String weightId;
/**
* 预计材料数量
*/
private String quantityCount;
/**
* 出库记录
*/
private List<MatMaterialsInventoryVo> children;
}

View File

@ -0,0 +1,71 @@
package org.dromara.materials.domain.vo.materials;
import lombok.Data;
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryOutUseVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-06 12:38
*/
@Data
public class MatMaterialsUseDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = -30861905964079368L;
/**
* 主键id
*/
private Long id;
/**
* 物资名称
*/
private String materialsName;
/**
* 计划数量
*/
private String quantityCount;
/**
* 供货单位
*/
private String companyName;
/**
* 入库id
*/
private Long inventoryId;
/**
* 入库数量
*/
private Long number;
/**
* 签收人
*/
private String operator;
/**
* 交接单位
*/
private String recipient;
/**
* 入库时间
*/
private Date enterTime;
/**
* 出库列表
*/
private List<MatMaterialsInventoryOutUseVo> outList;
}

View File

@ -0,0 +1,70 @@
package org.dromara.materials.domain.vo.materialsinventory;
import lombok.Data;
import org.dromara.materials.domain.vo.materialsuserecord.MatMaterialsUseRecordByOutVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-06 12:40
*/
@Data
public class MatMaterialsInventoryOutUseVo implements Serializable {
@Serial
private static final long serialVersionUID = -2437030140389673201L;
/**
* 主键id
*/
private Long id;
/**
* 材料id
*/
private Long materialsId;
/**
* 接收单位
*/
private String recipient;
/**
* 数量
*/
private Long number;
/**
* 出库人
*/
private String operator;
/**
* 领用人
*/
private String shipper;
/**
* 领用日期
*/
private Date createTime;
/**
* 剩余量
*/
private Long residue;
/**
* 处理方式
*/
private String disposition;
/**
* 使用登记
*/
private List<MatMaterialsUseRecordByOutVo> useList;
}

View File

@ -0,0 +1,54 @@
package org.dromara.materials.domain.vo.materialsuserecord;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author lilemy
* @date 2025-09-06 12:49
*/
@Data
public class MatMaterialsUseRecordByOutVo implements Serializable {
@Serial
private static final long serialVersionUID = -2259728802128537314L;
/**
* 主键ID
*/
private Long id;
/**
* 库存ID
*/
private Long inventoryId;
/**
* 使用部位
*/
private String usePart;
/**
* 使用数量
*/
private BigDecimal useNumber;
/**
* 使用日期
*/
private Date createTime;
/**
* 剩余量
*/
private BigDecimal residueNumber;
/**
* 备注
*/
private String remark;
}

View File

@ -6,15 +6,14 @@ import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.materials.domain.MatMaterials;
import org.dromara.materials.domain.MatMaterialsInventory;
import org.dromara.materials.domain.MatMaterialsUseRecord;
import org.dromara.materials.domain.dto.materialreceiveitem.MatMaterialReceiveItemDto;
import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsGisVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsNumberVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsVo;
import org.dromara.materials.domain.vo.materials.*;
import java.util.Collection;
import java.util.List;
@ -111,8 +110,19 @@ public interface IMatMaterialsService extends IService<MatMaterials> {
/**
* 生成材料并入库
*
* @param projectId 项目id
* @param itemList 接收材料列表
* @param formCode 表单编号
* @param supplierUnit 供应商单位
* @param nickname 操作用户昵称
*/
void create(Long projectId, List<MatMaterialReceiveItemDto> itemList, String formCode, String nickname);
void create(Long projectId,
List<MatMaterialReceiveItemDto> itemList,
String formCode,
String supplierUnit,
String nickname
);
/**
* 获取材料库存数据列表
@ -129,4 +139,50 @@ public interface IMatMaterialsService extends IService<MatMaterials> {
* @return 材料库存数据列表
*/
List<MatMaterialsByFormCodeVo> queryMaterialsByFormCode(Long projectId);
/**
* 获取材料出/入库列表
*
* @param req 查询条件
* @param pageQuery 分页条件
* @return 材料出/入库列表
*/
TableDataInfo<MatMaterialsRelevancyInventoryVo> queryRelevancyOutPutList(MatMaterialsQueryReq req, PageQuery pageQuery);
/**
* 获取材料分页对象视图
*
* @param materialsPage 材料分页对象
* @return 材料分页对象视图
*/
Page<MatMaterialsRelevancyInventoryVo> getRelevancyVoPage(Page<MatMaterials> materialsPage);
/**
* 获取材料使用详情列表
*
* @param req 查询条件
* @param pageQuery 分页条件
* @return 材料使用详情列表
*/
TableDataInfo<MatMaterialsUseDetailVo> queryUseDetailList(MatMaterialsQueryReq req, PageQuery pageQuery);
/**
* 获取材料使用详情列表
*
* @param materials 材料
* @param inventoryList 材料库存列表
* @param useList 材料使用列表
* @return 材料使用详情列表
*/
List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials,
List<MatMaterialsInventory> inventoryList,
List<MatMaterialsUseRecord> useList);
/**
* 获取材料库存数据列表
*
* @param req 查询条件
* @return 材料库存数据列表
*/
List<MatMaterialsExcelVo> queryExcelList(MatMaterialsQueryReq req);
}

View File

@ -272,7 +272,13 @@ public class MatMaterialReceiveServiceImpl extends ServiceImpl<MatMaterialReceiv
purchaseDocService.create(materialReceive.getDocId(), map);
}
//生成库存
materialsService.create(materialReceive.getProjectId(), itemList, materialReceive.getFormCode(), nickname);
materialsService.create(
materialReceive.getProjectId(),
itemList,
materialReceive.getFormCode(),
materialReceive.getSupplierUnit(),
nickname
);
}
return true;
}

View File

@ -183,6 +183,7 @@ public class MatMaterialsInventoryServiceImpl extends ServiceImpl<MatMaterialsIn
// 将实体类和 DTO 进行转换
MatMaterialsInventory materialsInventory = new MatMaterialsInventory();
BeanUtils.copyProperties(req, materialsInventory);
Long number = req.getNumber();
// 数据校验
validEntityBeforeSave(materialsInventory, true);
// 获取最后一次库存数量
@ -193,19 +194,19 @@ public class MatMaterialsInventoryServiceImpl extends ServiceImpl<MatMaterialsIn
.last("limit 1"));
if (lastMaterialsInventory != null) {
if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) {
long left = lastMaterialsInventory.getResidue() - req.getNumber();
long left = lastMaterialsInventory.getResidue() - number;
if (left < 0) {
throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST);
}
materialsInventory.setResidue(left);
} else {
materialsInventory.setResidue(lastMaterialsInventory.getResidue() + req.getNumber());
materialsInventory.setResidue(lastMaterialsInventory.getResidue() + number);
}
} else {
if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) {
throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST);
} else {
materialsInventory.setResidue(req.getNumber());
materialsInventory.setResidue(number);
}
}
// 填充默认值

View File

@ -9,7 +9,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
@ -19,6 +21,7 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.materials.domain.MatMaterialReceive;
import org.dromara.materials.domain.MatMaterials;
import org.dromara.materials.domain.MatMaterialsInventory;
import org.dromara.materials.domain.MatMaterialsUseRecord;
import org.dromara.materials.domain.dto.materialreceiveitem.MatMaterialReceiveItemDto;
import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq;
@ -27,16 +30,11 @@ import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq;
import org.dromara.materials.domain.dto.materialsinventory.MatMaterialsInventoryCreateReq;
import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum;
import org.dromara.materials.domain.enums.MatMaterialsInventoryReceiveStatusEnum;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsGisVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsNumberVo;
import org.dromara.materials.domain.vo.materials.MatMaterialsVo;
import org.dromara.materials.domain.vo.materials.*;
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryOutVo;
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryVo;
import org.dromara.materials.mapper.MatMaterialsMapper;
import org.dromara.materials.service.IMatCompanyService;
import org.dromara.materials.service.IMatMaterialReceiveService;
import org.dromara.materials.service.IMatMaterialsInventoryService;
import org.dromara.materials.service.IMatMaterialsService;
import org.dromara.materials.service.*;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.dromara.tender.service.ITenderSupplierInputService;
@ -74,6 +72,13 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
@Resource
private IMatMaterialReceiveService materialReceiveService;
@Lazy
@Resource
private IMatMaterialsUseRecordService materialsUseRecordService;
@Resource
private IMatCompanyService companyService;
/**
* 查询材料名称
@ -314,7 +319,6 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
return lqw;
}
// 从对象中取值
Long id = req.getId();
String materialsName = req.getMaterialsName();
Long companyId = req.getCompanyId();
Long projectId = req.getProjectId();
@ -329,7 +333,6 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
lqw.like(StringUtils.isNotBlank(quantityCount), MatMaterials::getQuantityCount, quantityCount);
// 精确查询
lqw.eq(ObjectUtils.isNotEmpty(status), MatMaterials::getStatus, status);
lqw.eq(ObjectUtils.isNotEmpty(id), MatMaterials::getId, id);
lqw.eq(ObjectUtils.isNotEmpty(projectId), MatMaterials::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId);
return lqw;
@ -356,9 +359,18 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
return materialsVoPage;
}
@Override
/**
* 生成材料并入库
*
* @param projectId 项目id
* @param itemList 接收材料列表
* @param formCode 表单编号
* @param supplierUnit 供应商单位
* @param nickname 操作用户昵称
*/
@Async
public void create(Long projectId, List<MatMaterialReceiveItemDto> itemList, String formCode, String nickname) {
@Override
public void create(Long projectId, List<MatMaterialReceiveItemDto> itemList, String formCode, String supplierUnit, String nickname) {
for (MatMaterialReceiveItemDto item : itemList) {
MatMaterials matMaterials = new MatMaterials();
matMaterials.setMaterialsName(item.getName());
@ -376,6 +388,7 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
req.setNumber(item.getAcceptedQuantity().longValue());
req.setOutPutTime(new Date());
req.setOperator(nickname);
req.setRecipient(supplierUnit);
materialsInventoryService.insertByBo(req);
}
}
@ -498,4 +511,278 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
}
return resultList;
}
/**
* 获取材料出/入库列表
*
* @param req 查询条件
* @param pageQuery 分页条件
* @return 材料出/入库列表
*/
@Override
public TableDataInfo<MatMaterialsRelevancyInventoryVo> queryRelevancyOutPutList(MatMaterialsQueryReq req,
PageQuery pageQuery) {
// 查询数据库
Page<MatMaterials> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
return TableDataInfo.build(this.getRelevancyVoPage(result));
}
/**
* 获取材料分页对象视图
*
* @param materialsPage 材料分页对象
* @return 材料分页对象视图
*/
@Override
public Page<MatMaterialsRelevancyInventoryVo> getRelevancyVoPage(Page<MatMaterials> materialsPage) {
// 获取材料数据
List<MatMaterials> materialsList = materialsPage.getRecords();
// 添加分页信息
Page<MatMaterialsRelevancyInventoryVo> materialsVoPage = new Page<>(
materialsPage.getCurrent(),
materialsPage.getSize(),
materialsPage.getTotal()
);
if (CollUtil.isEmpty(materialsList)) {
return materialsVoPage;
}
// 获取材料ids
List<Long> materialIds = materialsList.stream().map(MatMaterials::getId).toList();
List<MatMaterialsInventory> materialsInventoryList = materialsInventoryService.lambdaQuery()
.in(MatMaterialsInventory::getMaterialsId, materialIds)
.list();
Map<Long, List<MatMaterialsInventory>> map = materialsInventoryList.stream()
.collect(Collectors.groupingBy(MatMaterialsInventory::getMaterialsId));
// 对象列表 => 封装对象列表
List<MatMaterialsRelevancyInventoryVo> materialsVoList = materialsList.stream().map(material -> {
MatMaterialsRelevancyInventoryVo vo = new MatMaterialsRelevancyInventoryVo();
BeanUtils.copyProperties(material, vo);
// 关联查询项目信息
Long companyId = material.getCompanyId();
String materialsName = material.getMaterialsName();
if (companyId != null) {
vo.setCompanyName(companyService.queryById(companyId).getCompanyName());
}
List<MatMaterialsInventory> inventoryList = map.get(material.getId());
List<MatMaterialsInventory> putList = inventoryList.stream()
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.PUT.getValue()))
.toList();
if (CollUtil.isNotEmpty(putList)) {
MatMaterialsInventory put = putList.getFirst();
vo.setInventoryId(put.getId());
vo.setNumber(put.getNumber());
vo.setResidue(put.getResidue());
vo.setOperator(put.getOperator());
}
List<MatMaterialsInventory> outList = inventoryList.stream()
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.OUT.getValue()))
.toList();
if (CollUtil.isNotEmpty(outList)) {
List<MatMaterialsInventoryVo> list = outList.stream().map(inventory -> {
MatMaterialsInventoryVo inventoryVo = new MatMaterialsInventoryVo();
BeanUtils.copyProperties(inventory, inventoryVo);
inventoryVo.setMaterialsName(materialsName);
return inventoryVo;
})
.sorted(Comparator.comparing(MatMaterialsInventoryVo::getCreateTime).reversed())
.toList();
vo.setResidue(list.getFirst().getResidue());
vo.setChildren(list);
}
return vo;
}).toList();
materialsVoPage.setRecords(materialsVoList);
return materialsVoPage;
}
/**
* 获取材料使用详情列表
*
* @param req 查询条件
* @param pageQuery 分页条件
* @return 材料使用详情列表
*/
@Override
public TableDataInfo<MatMaterialsUseDetailVo> queryUseDetailList(MatMaterialsQueryReq req, PageQuery pageQuery) {
// 查询数据库
Page<MatMaterials> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
List<MatMaterials> materialsList = result.getRecords();
// 添加分页信息
Page<MatMaterialsUseDetailVo> materialsVoPage = new Page<>(
result.getCurrent(),
result.getSize(),
result.getTotal()
);
/* if (CollUtil.isEmpty(materialsList)) {
return materialsVoPage;
}*/
return null;
}
/**
* 获取材料使用详情列表
*
* @param materials 材料
* @param inventoryList 材料库存列表
* @param useList 材料使用列表
* @return 材料使用详情列表
*/
@Override
public List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials, List<MatMaterialsInventory> inventoryList, List<MatMaterialsUseRecord> useList) {
return List.of();
}
/**
* 获取材料库存数据列表
*
* @param req 查询条件
* @return 材料库存数据列表
*/
@Override
public List<MatMaterialsExcelVo> queryExcelList(MatMaterialsQueryReq req) {
// 查询数据库
LambdaQueryWrapper<MatMaterials> lqw = this.buildQueryWrapper(req);
List<MatMaterials> materials = this.list(lqw);
if (CollUtil.isEmpty(materials)) {
return List.of();
}
// 获取材料主键
List<Long> ids = materials.stream().map(MatMaterials::getId).toList();
// 获取出入库记录
List<MatMaterialsInventory> inventoryList = materialsInventoryService.lambdaQuery()
.in(MatMaterialsInventory::getMaterialsId, ids)
.list();
// 获取入库记录
List<MatMaterialsInventory> putList = inventoryList.stream()
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.PUT.getValue()))
.toList();
Map<Long, MatMaterialsInventory> putMap = putList.stream()
.collect(Collectors.toMap(MatMaterialsInventory::getMaterialsId, inventory -> inventory));
// 获取使用记录
List<MatMaterialsInventory> outList = inventoryList.stream()
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.OUT.getValue()))
.toList();
List<MatMaterialsUseRecord> useList = new ArrayList<>();
if (CollUtil.isEmpty(outList)) {
List<Long> outIds = outList.stream().map(MatMaterialsInventory::getId).distinct().toList();
// 获取使用记录
useList = materialsUseRecordService.lambdaQuery()
.in(MatMaterialsUseRecord::getInventoryId, outIds)
.list();
}
List<MatMaterialsExcelVo> excelVoList = new ArrayList<>();
for (MatMaterials material : materials) {
MatMaterialsExcelVo vo = new MatMaterialsExcelVo();
Long id = material.getId();
vo.setMaterialsName(material.getMaterialsName());
vo.setQuantityCount(material.getQuantityCount());
// 拼接入库记录
MatMaterialsInventory put = putMap.get(id);
vo.setSupplier(put.getRecipient());
vo.setPutNumber(put.getNumber());
vo.setSigner(put.getOperator());
if (put.getCreateTime() != null) {
vo.setPutTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, put.getCreateTime()));
}
List<MatMaterialsInventory> materialOutList = outList.stream()
.filter(inventory -> inventory.getMaterialsId().equals(id))
.toList();
List<MatMaterialsUseRecord> materialUseList = new ArrayList<>();
if (CollUtil.isNotEmpty(materialOutList)) {
// 拼接第一条出库数据
MatMaterialsInventory out = materialOutList.getFirst();
vo.setRecipient(out.getRecipient());
vo.setOutNumber(out.getNumber());
vo.setOperator(out.getOperator());
vo.setShipper(out.getShipper());
if (out.getCreateTime() != null) {
vo.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
}
vo.setResidue(out.getResidue());
vo.setDisposition(out.getDisposition());
materialUseList = useList.stream()
.filter(record -> record.getInventoryId().equals(out.getId()))
.toList();
if (CollUtil.isNotEmpty(materialUseList)) {
// 拼接第一条使用记录
MatMaterialsUseRecord use = materialUseList.getFirst();
vo.setUsePart(use.getUsePart());
vo.setUseNumber(use.getUseNumber());
if (use.getCreateTime() != null) {
vo.setUseTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, use.getCreateTime()));
}
vo.setSurplus(use.getResidueNumber());
vo.setRemark(use.getRemark());
}
}
List<MatMaterialsExcelVo> childList = new ArrayList<>();
if (CollUtil.isNotEmpty(materialUseList)) {
for (int i = 1; i < materialOutList.size(); i++) {
MatMaterialsInventory out = materialOutList.get(i);
List<MatMaterialsUseRecord> outUseList = materialUseList.stream()
.filter(record -> record.getInventoryId().equals(out.getId()))
.toList();
if (CollUtil.isNotEmpty(outUseList)) {
for (int j = 1; j < outUseList.size(); j++) {
MatMaterialsExcelVo child = new MatMaterialsExcelVo();
MatMaterialsUseRecord use = outUseList.get(j);
if (j == 1) {
// 拼接出库记录
child.setRecipient(out.getRecipient());
child.setOutNumber(out.getNumber());
child.setOperator(out.getOperator());
child.setShipper(out.getShipper());
if (out.getCreateTime() != null) {
child.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
}
child.setResidue(out.getResidue());
child.setDisposition(out.getDisposition());
}
// 拼接使用记录
vo.setUsePart(use.getUsePart());
vo.setUseNumber(use.getUseNumber());
if (use.getCreateTime() != null) {
vo.setUseTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, use.getCreateTime()));
}
vo.setSurplus(use.getResidueNumber());
vo.setRemark(use.getRemark());
childList.add(child);
}
} else {
MatMaterialsExcelVo child = new MatMaterialsExcelVo();
child.setRecipient(out.getRecipient());
child.setOutNumber(out.getNumber());
child.setOperator(out.getOperator());
child.setShipper(out.getShipper());
if (out.getCreateTime() != null) {
child.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
}
child.setResidue(out.getResidue());
child.setDisposition(out.getDisposition());
childList.add(child);
}
}
} else {
childList = materialOutList.stream()
.skip(1)
.map(out -> {
MatMaterialsExcelVo v = new MatMaterialsExcelVo();
v.setRecipient(out.getRecipient());
v.setOutNumber(out.getNumber());
v.setOperator(out.getOperator());
v.setShipper(out.getShipper());
if (out.getCreateTime() != null) {
v.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
}
v.setResidue(out.getResidue());
v.setDisposition(out.getDisposition());
return v;
}).toList();
}
excelVoList.add(vo);
excelVoList.addAll(childList);
}
return excelVoList;
}
}

View File

@ -11,13 +11,13 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.excel.core.DefaultExcelListener;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
@ -90,7 +90,7 @@ public class PgsProgressCategoryController extends BaseController {
@Log(title = "进度类别", businessType = BusinessType.EXPORT)
@Transactional
@PostMapping("/export")
public void export(@RequestBody Map<String, String> projectId , HttpServletResponse response) throws IOException {
public void export(@RequestBody Map<String, String> projectId, HttpServletResponse response) {
LambdaQueryWrapper<PgsProgressCategory> queryWrapper = new LambdaQueryWrapper<>();
//根据projectid拿到整个数据
@ -108,7 +108,7 @@ public class PgsProgressCategoryController extends BaseController {
//获取非方阵类别name 非方阵类别有多级 暂定只有2级 也有可能没有父子关系
queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,0).eq(PgsProgressCategory::getMatrixId,0).in(PgsProgressCategory::getId,ids);
queryWrapper.eq(PgsProgressCategory::getParentId, 0).eq(PgsProgressCategory::getMatrixId, 0).in(PgsProgressCategory::getId, ids);
List<PgsProgressCategory> unMatrixList = pgsProgressCategoryService.list(queryWrapper);
if (!unMatrixList.isEmpty()) {
for (PgsProgressCategory unMatrix : unMatrixList) {
@ -116,18 +116,18 @@ public class PgsProgressCategoryController extends BaseController {
names.add(unMatrix.getName());
//寻找子类
queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,unMatrix.getId());
queryWrapper.eq(PgsProgressCategory::getParentId, unMatrix.getId());
List<PgsProgressCategoryVo> children = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper));
if (!children.isEmpty()) {
//寻找孙类 然后添加
List<PgsProgressCategoryVo> grandson = new ArrayList<>();
for (PgsProgressCategoryVo childrenCategory : children) {
queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,childrenCategory.getId());
queryWrapper.eq(PgsProgressCategory::getParentId, childrenCategory.getId());
List<PgsProgressCategoryVo> grandsonCategory = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper));
if (!grandsonCategory.isEmpty()) {
grandson.addAll(grandsonCategory);
}else {
} else {
grandson = children;
}
}
@ -138,7 +138,7 @@ public class PgsProgressCategoryController extends BaseController {
//获取矩阵类别name
queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,0).ne(PgsProgressCategory::getMatrixId,0).in(PgsProgressCategory::getId,ids);
queryWrapper.eq(PgsProgressCategory::getParentId, 0).ne(PgsProgressCategory::getMatrixId, 0).in(PgsProgressCategory::getId, ids);
List<PgsProgressCategory> matrixList = pgsProgressCategoryService.list(queryWrapper);
if (!matrixList.isEmpty()) {
for (PgsProgressCategory pgsProgressCategory : matrixList) {
@ -146,12 +146,16 @@ public class PgsProgressCategoryController extends BaseController {
names.add(pgsProgressCategory.getName() + "-" + pgsProgressCategory.getMatrixName());
//找到该矩阵下的列表
queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getMatrixId,pgsProgressCategory.getMatrixId());
queryWrapper.eq(PgsProgressCategory::getMatrixId, pgsProgressCategory.getMatrixId());
listValues.add(pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper)));
}
}
try {
ExcelUtil.exportMultiSheetExcelEnhanced(listValues, names, PgsProgressCategoryVo.class, null, response);
} catch (IOException e) {
throw new ServiceException("导出失败");
}
}

View File

@ -0,0 +1,42 @@
package org.dromara.progress.controller.app;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryTopVo;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 进度类别 app 接口
*
* @author lilemy
* @date 2025-09-05 10:29
*/
@Slf4j
@Validated
@RestController
@RequestMapping("/app/progress/progressCategory")
public class PgsProgressCategoryAppController {
@Resource
private IPgsProgressCategoryService progressCategoryService;
/**
* 根据子项目获取进度类别模版顶级目录列表
*/
@GetMapping("/listTopBySubProjectId/{subProjectId}")
public R<List<PgsProgressCategoryTopVo>> listTopBySubProjectId(@NotNull(message = "项目id不能为空")
@PathVariable Long subProjectId) {
List<PgsProgressCategoryTopVo> list = progressCategoryService.getTopListByProjectId(subProjectId);
return R.ok(list);
}
}

View File

@ -0,0 +1,18 @@
package org.dromara.progress.controller.app;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 进度计划 app 接口
*
* @author lilemy
* @date 2025-09-05 14:24
*/
@Validated
@RestController
@RequestMapping("/app/progress/progressPlan")
public class PgsProgressPlanAppController extends BaseController {
}

View File

@ -0,0 +1,18 @@
package org.dromara.progress.controller.app;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 进度计划详情 app 接口
*
* @author lilemy
* @date 2025-09-05 14:24
*/
@Validated
@RestController
@RequestMapping("/app/progress/progressPlanDetail")
public class PgsProgressPlanDetailAppController extends BaseController {
}

View File

@ -0,0 +1,19 @@
package org.dromara.progress.domain.vo.progresscategory;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-05 20:50
*/
@Data
public class PgsProgressCategorySecondVo implements Serializable {
@Serial
private static final long serialVersionUID = 5297363236416903392L;
}

View File

@ -4,6 +4,7 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
@ -31,6 +32,21 @@ public class PgsProgressCategoryTopVo implements Serializable {
*/
private String name;
/**
* 总进度
*/
private BigDecimal progressTotal;
/**
* 完成状态0未开始 1进行中 2已完成
*/
private String status;
/**
* 类型1仅二级 2三级 3有方阵 4三级 + 方阵)
*/
private String type;
/**
* 排序
*/
@ -40,4 +56,9 @@ public class PgsProgressCategoryTopVo implements Serializable {
* 关联方阵结构列表
*/
private List<PgsProgressCategoryMatrixStructureTopVo> matrixStructureList;
/**
* 子类别列表
*/
private List<PgsProgressCategorySecondVo> categorySecondList;
}

View File

@ -10,6 +10,7 @@ import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQuery
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.vo.progresscategory.*;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -174,4 +175,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
* @return 最底层的叶子节点
*/
List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIds);
/**
* 获取项目进度百分比
*
* @param categoryList 项目进度列表
* @return 项目进度百分比
*/
BigDecimal getCompletedPercentage(List<PgsProgressCategory> categoryList);
}

View File

@ -208,9 +208,23 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.SUB_PROJECT.getValue()))
.toList();
if (CollUtil.isNotEmpty(subList)) {
List<Long> topIds = subList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = this.getLeafNodesByTopIds(topIds);
List<PgsProgressCategoryTopVo> subVoList = subList.stream().map(category -> {
PgsProgressCategoryTopVo vo = new PgsProgressCategoryTopVo();
BeanUtils.copyProperties(category, vo);
List<PgsProgressCategory> children = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ancestorSet.contains(category.getId());
})
.toList();
if (CollUtil.isNotEmpty(children)) {
vo.setProgressTotal(this.getCompletedPercentage(children));
vo.setStatus(this.getParentStatus(children));
} else {
vo.setProgressTotal(BigDecimal.ZERO);
}
return vo;
}).toList();
topList.addAll(subVoList);
@ -235,6 +249,15 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
return vo;
}).toList();
topVo.setMatrixStructureList(matrixVoList);
// 获取所有子级,并进行统计
List<Long> topIds = value.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = this.getLeafNodesByTopIds(topIds);
if (CollUtil.isNotEmpty(leafNodesByTopIds)) {
topVo.setProgressTotal(this.getCompletedPercentage(leafNodesByTopIds));
topVo.setStatus(this.getParentStatus(leafNodesByTopIds));
} else {
topVo.setProgressTotal(BigDecimal.ZERO);
}
topList.add(topVo);
}
}
@ -1200,7 +1223,8 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
Wrappers.<PgsProgressCategory>lambdaQuery()
.and(wrapper -> {
for (Long topId : topIds) {
wrapper.or(q -> q.like(PgsProgressCategory::getAncestors, "," + topId + ","));
wrapper.or(q -> q.like(PgsProgressCategory::getAncestors, "," + topId + ","))
.or(q -> q.like(PgsProgressCategory::getAncestors, "," + topId));
}
})
);
@ -1219,4 +1243,27 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
.toList();
}
/**
* 获取项目进度百分比
*
* @param categoryList 项目进度列表
* @return 项目进度百分比
*/
@Override
public BigDecimal getCompletedPercentage(List<PgsProgressCategory> categoryList) {
BigDecimal completedTotal = BigDecimal.ZERO;
BigDecimal allTotal = BigDecimal.ZERO;
for (PgsProgressCategory category : categoryList) {
BigDecimal completed = category.getCompleted();
BigDecimal total = category.getTotal();
if (PgsProgressUnitTypeEnum.NUMBER.getValue().equals(category.getUnitType())) {
completedTotal = completedTotal.add(completed);
} else if (PgsProgressUnitTypeEnum.PERCENTAGE.getValue().equals(category.getUnitType())) {
completedTotal = completedTotal.add(completed.divide(BigDecimal.valueOf(100L), 2, RoundingMode.HALF_UP).multiply(total));
}
allTotal = allTotal.add(total);
}
return BigDecimalUtil.toPercentage(completedTotal, allTotal);
}
}

View File

@ -31,6 +31,7 @@ import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailP
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.enums.PgsFinishStatusEnum;
import org.dromara.progress.domain.enums.PgsProgressUnitTypeEnum;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo;
@ -353,7 +354,12 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
BigDecimal completed = progressCategory.getCompleted();
BigDecimal completedTotal = completed.subtract(number).add(finishedNumber);
progressCategory.setCompleted(completedTotal);
if (completedTotal.compareTo(progressCategory.getTotal()) == 0) {
if (progressCategory.getUnitType().equals(PgsProgressUnitTypeEnum.NUMBER.getValue())
&& completedTotal.compareTo(progressCategory.getTotal()) == 0) {
progressCategory.setStatus(PgsFinishStatusEnum.FINISH.getValue());
}
if (progressCategory.getUnitType().equals(PgsProgressUnitTypeEnum.PERCENTAGE.getValue())
&& completedTotal.compareTo(BigDecimal.valueOf(100)) == 0) {
progressCategory.setStatus(PgsFinishStatusEnum.FINISH.getValue());
}
// 判断当前是否已完成计划数量

View File

@ -4,13 +4,11 @@ import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.project.domain.dto.project.BusProjectQueryReq;
import org.dromara.project.domain.dto.userprojectrelevancy.BusUserProjectRelevancyQueryReq;
import org.dromara.project.domain.vo.project.BusProjectContractorTeamListVo;
import org.dromara.project.domain.vo.project.BusProjectVo;
import org.dromara.project.domain.vo.project.BusSubProjectVo;
import org.dromara.project.domain.vo.userprojectrelevancy.BusLoginUserProjectRelevancyVo;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusUserProjectRelevancyService;
@ -75,4 +73,13 @@ public class BusProjectAppController {
busProjectQueryReq.setPId(0L);
return R.ok(projectService.queryList(busProjectQueryReq));
}
/**
* 查询项目下的子项目列表
*/
@GetMapping("/listSub/{id}")
public R<List<BusSubProjectVo>> listSubProject(@NotNull(message = "项目id不能为空")
@PathVariable Long id) {
return R.ok(projectService.querySubList(id));
}
}

View File

@ -957,19 +957,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
}
Set<Long> subProjectIds = subProjects.stream().map(BusProject::getId).collect(Collectors.toSet());
// 获取方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.in(FacMatrix::getProjectId, subProjectIds)
.list();
Map<Long, List<FacMatrix>> matrixMap = matrixList.stream()
.collect(Collectors.groupingBy(FacMatrix::getProjectId));
// 获取分项工程
Set<Long> matrixIds = matrixList.stream().map(FacMatrix::getId).collect(Collectors.toSet());
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getMatrixId, matrixIds)
.list();
List<PgsProgressCategory> subProgressCategoryList = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getRelevancyStructure, PgsRelevancyStructureEnum.SUB_PROJECT.getValue())
.in(PgsProgressCategory::getProjectId, subProjectIds)
@ -1035,6 +1023,19 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return matrixVo;
}).toList();
// 获取方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.in(FacMatrix::getProjectId, subProjectIds)
.list();
if (CollUtil.isNotEmpty(matrixList)) {
Map<Long, List<FacMatrix>> matrixMap = matrixList.stream()
.collect(Collectors.groupingBy(FacMatrix::getProjectId));
// 获取分项工程
Set<Long> matrixIds = matrixList.stream().map(FacMatrix::getId).collect(Collectors.toSet());
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getMatrixId, matrixIds)
.list();
// 找到该子项目下的方阵
List<FacMatrix> matrices = matrixMap.getOrDefault(subProject.getId(), new ArrayList<>());
List<FacMatrixStructureVo> matrixVos = matrices.stream().map(matrix -> {
@ -1057,6 +1058,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
matrixVos.stream()
).toList();
subProjectVo.setChildren(resultList);
}
return subProjectVo;
}).toList();