进度、物资管理模块

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.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -219,15 +216,15 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
// 子项目id列表 // 子项目id列表
List<Long> subProjectIds = subProjectList.stream().map(BusProject::getId).toList(); 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); vo.setBoxTransformerPercentage(BigDecimal.ZERO);
// 获取集电线路、送出线路、升压站数据 // 获取集电线路、送出线路、升压站数据
@ -239,27 +236,63 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
if (CollUtil.isNotEmpty(progressCategoryList)) { if (CollUtil.isNotEmpty(progressCategoryList)) {
List<Long> categoryIds = progressCategoryList.stream().map(PgsProgressCategory::getId).distinct().toList(); List<Long> categoryIds = progressCategoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = progressCategoryService.getLeafNodesByTopIds(categoryIds); 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)); .collect(Collectors.groupingBy(PgsProgressCategory::getName));
// 计算集电线路 // 计算集电线路
if (categoryMap.containsKey("集电线路")) { if (categoryMap.containsKey("集电线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("集电线路"); 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("送出线路")) { if (categoryMap.containsKey("送出线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("送出线路"); 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("升压站")) { if (categoryMap.containsKey("升压站")) {
List<PgsProgressCategory> categoryList = categoryMap.get("升压站"); 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("光伏场区")) { if (categoryMap.containsKey("光伏场区")) {
List<PgsProgressCategory> categoryList = categoryMap.get("光伏场区"); 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()) .ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list(); .list();
if (CollUtil.isNotEmpty(roadCategoryList)) { 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() List<PgsProgressCategory> boxTransformerCategoryList = progressCategoryService.lambdaQuery()
@ -278,7 +314,10 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
.ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue()) .ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list(); .list();
if (CollUtil.isNotEmpty(boxTransformerCategoryList)) { if (CollUtil.isNotEmpty(boxTransformerCategoryList)) {
vo.setBoxTransformerPercentage(getCompletedPercentage(boxTransformerCategoryList)); BigDecimal percentage = progressCategoryService.getCompletedPercentage(boxTransformerCategoryList);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setBoxTransformerPercentage(percentage);
}
} }
// 计算总进度 // 计算总进度
vo.setTotalPercentage( vo.setTotalPercentage(
@ -288,6 +327,7 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
.add(vo.getAreaPercentage()) .add(vo.getAreaPercentage())
.add(vo.getRoadPercentage()) .add(vo.getRoadPercentage())
.add(vo.getBoxTransformerPercentage()) .add(vo.getBoxTransformerPercentage())
.divide(BigDecimal.valueOf(6), 2, RoundingMode.HALF_UP) // 保留两位小数
); );
return vo; 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) { public static BigDecimal toPercentage(BigDecimal dividend, BigDecimal divisor) {
if (dividend == null || divisor == null || divisor.compareTo(BigDecimal.ZERO) == 0) { 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.MatMaterialsGisReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq; import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq; import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo; import org.dromara.materials.domain.vo.materials.*;
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.service.IMatMaterialsService; import org.dromara.materials.service.IMatMaterialsService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -52,6 +49,24 @@ public class MatMaterialsController extends BaseController {
return materialsService.queryPageList(req, pageQuery); 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) @Log(title = "材料", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(MatMaterialsQueryReq req, HttpServletResponse response) { public void export(MatMaterialsQueryReq req, HttpServletResponse response) {
List<MatMaterialsVo> list = materialsService.queryList(req); List<MatMaterialsExcelVo> list = materialsService.queryExcelList(req);
ExcelUtil.exportExcel(list, "材料名称", MatMaterialsVo.class, response); ExcelUtil.exportExcel(list, "材料名称", MatMaterialsExcelVo.class, response);
} }
/** /**

View File

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

View File

@ -1,5 +1,7 @@
package org.dromara.materials.domain.dto.materialsinventory; package org.dromara.materials.domain.dto.materialsinventory;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
@ -19,16 +21,19 @@ public class MatMaterialsInventoryCreateReq implements Serializable {
/** /**
* 材料id * 材料id
*/ */
@NotNull(message = "材料主键不能为空")
private Long materialsId; private Long materialsId;
/** /**
* 项目id * 项目id
*/ */
@NotNull(message = "项目主键不能为空")
private Long projectId; private Long projectId;
/** /**
* 出入库状态 * 出入库状态
*/ */
@NotBlank(message = "出/入库状态不能为空")
private String outPut; 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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.materials.domain.MatMaterials; 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.materialreceiveitem.MatMaterialReceiveItemDto;
import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq; import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq; import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq; import org.dromara.materials.domain.dto.materials.MatMaterialsQueryReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq; import org.dromara.materials.domain.dto.materials.MatMaterialsUpdateReq;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo; import org.dromara.materials.domain.vo.materials.*;
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 java.util.Collection; import java.util.Collection;
import java.util.List; 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 材料库存数据列表 * @return 材料库存数据列表
*/ */
List<MatMaterialsByFormCodeVo> queryMaterialsByFormCode(Long projectId); 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); 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; return true;
} }

View File

@ -183,6 +183,7 @@ public class MatMaterialsInventoryServiceImpl extends ServiceImpl<MatMaterialsIn
// 将实体类和 DTO 进行转换 // 将实体类和 DTO 进行转换
MatMaterialsInventory materialsInventory = new MatMaterialsInventory(); MatMaterialsInventory materialsInventory = new MatMaterialsInventory();
BeanUtils.copyProperties(req, materialsInventory); BeanUtils.copyProperties(req, materialsInventory);
Long number = req.getNumber();
// 数据校验 // 数据校验
validEntityBeforeSave(materialsInventory, true); validEntityBeforeSave(materialsInventory, true);
// 获取最后一次库存数量 // 获取最后一次库存数量
@ -193,19 +194,19 @@ public class MatMaterialsInventoryServiceImpl extends ServiceImpl<MatMaterialsIn
.last("limit 1")); .last("limit 1"));
if (lastMaterialsInventory != null) { if (lastMaterialsInventory != null) {
if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) { if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) {
long left = lastMaterialsInventory.getResidue() - req.getNumber(); long left = lastMaterialsInventory.getResidue() - number;
if (left < 0) { if (left < 0) {
throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST); throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST);
} }
materialsInventory.setResidue(left); materialsInventory.setResidue(left);
} else { } else {
materialsInventory.setResidue(lastMaterialsInventory.getResidue() + req.getNumber()); materialsInventory.setResidue(lastMaterialsInventory.getResidue() + number);
} }
} else { } else {
if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) { if (MatMaterialsInventoryOutPutEnum.OUT.getValue().equals(req.getOutPut())) {
throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST); throw new ServiceException("库存不足", HttpStatus.BAD_REQUEST);
} else { } 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 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus; 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.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils; 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.MatMaterialReceive;
import org.dromara.materials.domain.MatMaterials; import org.dromara.materials.domain.MatMaterials;
import org.dromara.materials.domain.MatMaterialsInventory; 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.materialreceiveitem.MatMaterialReceiveItemDto;
import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq; import org.dromara.materials.domain.dto.materials.MatMaterialsCreateReq;
import org.dromara.materials.domain.dto.materials.MatMaterialsGisReq; 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.dto.materialsinventory.MatMaterialsInventoryCreateReq;
import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum; import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum;
import org.dromara.materials.domain.enums.MatMaterialsInventoryReceiveStatusEnum; import org.dromara.materials.domain.enums.MatMaterialsInventoryReceiveStatusEnum;
import org.dromara.materials.domain.vo.materials.MatMaterialsByFormCodeVo; import org.dromara.materials.domain.vo.materials.*;
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.materialsinventory.MatMaterialsInventoryOutVo; 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.mapper.MatMaterialsMapper;
import org.dromara.materials.service.IMatCompanyService; import org.dromara.materials.service.*;
import org.dromara.materials.service.IMatMaterialReceiveService;
import org.dromara.materials.service.IMatMaterialsInventoryService;
import org.dromara.materials.service.IMatMaterialsService;
import org.dromara.project.domain.BusProject; import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.tender.service.ITenderSupplierInputService; import org.dromara.tender.service.ITenderSupplierInputService;
@ -74,6 +72,13 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
@Resource @Resource
private IMatMaterialReceiveService materialReceiveService; 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; return lqw;
} }
// 从对象中取值 // 从对象中取值
Long id = req.getId();
String materialsName = req.getMaterialsName(); String materialsName = req.getMaterialsName();
Long companyId = req.getCompanyId(); Long companyId = req.getCompanyId();
Long projectId = req.getProjectId(); Long projectId = req.getProjectId();
@ -329,7 +333,6 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
lqw.like(StringUtils.isNotBlank(quantityCount), MatMaterials::getQuantityCount, quantityCount); lqw.like(StringUtils.isNotBlank(quantityCount), MatMaterials::getQuantityCount, quantityCount);
// 精确查询 // 精确查询
lqw.eq(ObjectUtils.isNotEmpty(status), MatMaterials::getStatus, status); 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(projectId), MatMaterials::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId); lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId);
return lqw; return lqw;
@ -356,9 +359,18 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
return materialsVoPage; return materialsVoPage;
} }
@Override /**
* 生成材料并入库
*
* @param projectId 项目id
* @param itemList 接收材料列表
* @param formCode 表单编号
* @param supplierUnit 供应商单位
* @param nickname 操作用户昵称
*/
@Async @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) { for (MatMaterialReceiveItemDto item : itemList) {
MatMaterials matMaterials = new MatMaterials(); MatMaterials matMaterials = new MatMaterials();
matMaterials.setMaterialsName(item.getName()); matMaterials.setMaterialsName(item.getName());
@ -376,6 +388,7 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
req.setNumber(item.getAcceptedQuantity().longValue()); req.setNumber(item.getAcceptedQuantity().longValue());
req.setOutPutTime(new Date()); req.setOutPutTime(new Date());
req.setOperator(nickname); req.setOperator(nickname);
req.setRecipient(supplierUnit);
materialsInventoryService.insertByBo(req); materialsInventoryService.insertByBo(req);
} }
} }
@ -498,4 +511,278 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
} }
return resultList; 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 jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; 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.core.DefaultExcelListener;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log; import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType; import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController; import org.dromara.common.web.core.BaseController;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.progress.domain.PgsProgressCategory; import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq; import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq; import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
@ -90,7 +90,7 @@ public class PgsProgressCategoryController extends BaseController {
@Log(title = "进度类别", businessType = BusinessType.EXPORT) @Log(title = "进度类别", businessType = BusinessType.EXPORT)
@Transactional @Transactional
@PostMapping("/export") @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<>(); LambdaQueryWrapper<PgsProgressCategory> queryWrapper = new LambdaQueryWrapper<>();
//根据projectid拿到整个数据 //根据projectid拿到整个数据
@ -108,7 +108,7 @@ public class PgsProgressCategoryController extends BaseController {
//获取非方阵类别name 非方阵类别有多级 暂定只有2级 也有可能没有父子关系 //获取非方阵类别name 非方阵类别有多级 暂定只有2级 也有可能没有父子关系
queryWrapper = new LambdaQueryWrapper<>(); 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); List<PgsProgressCategory> unMatrixList = pgsProgressCategoryService.list(queryWrapper);
if (!unMatrixList.isEmpty()) { if (!unMatrixList.isEmpty()) {
for (PgsProgressCategory unMatrix : unMatrixList) { for (PgsProgressCategory unMatrix : unMatrixList) {
@ -116,18 +116,18 @@ public class PgsProgressCategoryController extends BaseController {
names.add(unMatrix.getName()); names.add(unMatrix.getName());
//寻找子类 //寻找子类
queryWrapper = new LambdaQueryWrapper<>(); queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,unMatrix.getId()); queryWrapper.eq(PgsProgressCategory::getParentId, unMatrix.getId());
List<PgsProgressCategoryVo> children = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper)); List<PgsProgressCategoryVo> children = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper));
if (!children.isEmpty()) { if (!children.isEmpty()) {
//寻找孙类 然后添加 //寻找孙类 然后添加
List<PgsProgressCategoryVo> grandson = new ArrayList<>(); List<PgsProgressCategoryVo> grandson = new ArrayList<>();
for (PgsProgressCategoryVo childrenCategory : children) { for (PgsProgressCategoryVo childrenCategory : children) {
queryWrapper = new LambdaQueryWrapper<>(); queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getParentId,childrenCategory.getId()); queryWrapper.eq(PgsProgressCategory::getParentId, childrenCategory.getId());
List<PgsProgressCategoryVo> grandsonCategory = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper)); List<PgsProgressCategoryVo> grandsonCategory = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper));
if (!grandsonCategory.isEmpty()) { if (!grandsonCategory.isEmpty()) {
grandson.addAll(grandsonCategory); grandson.addAll(grandsonCategory);
}else { } else {
grandson = children; grandson = children;
} }
} }
@ -138,7 +138,7 @@ public class PgsProgressCategoryController extends BaseController {
//获取矩阵类别name //获取矩阵类别name
queryWrapper = new LambdaQueryWrapper<>(); 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); List<PgsProgressCategory> matrixList = pgsProgressCategoryService.list(queryWrapper);
if (!matrixList.isEmpty()) { if (!matrixList.isEmpty()) {
for (PgsProgressCategory pgsProgressCategory : matrixList) { for (PgsProgressCategory pgsProgressCategory : matrixList) {
@ -146,12 +146,16 @@ public class PgsProgressCategoryController extends BaseController {
names.add(pgsProgressCategory.getName() + "-" + pgsProgressCategory.getMatrixName()); names.add(pgsProgressCategory.getName() + "-" + pgsProgressCategory.getMatrixName());
//找到该矩阵下的列表 //找到该矩阵下的列表
queryWrapper = new LambdaQueryWrapper<>(); queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PgsProgressCategory::getMatrixId,pgsProgressCategory.getMatrixId()); queryWrapper.eq(PgsProgressCategory::getMatrixId, pgsProgressCategory.getMatrixId());
listValues.add(pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper))); listValues.add(pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper)));
} }
} }
try {
ExcelUtil.exportMultiSheetExcelEnhanced(listValues, names, PgsProgressCategoryVo.class, null, response); 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.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
/** /**
@ -31,6 +32,21 @@ public class PgsProgressCategoryTopVo implements Serializable {
*/ */
private String name; 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<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.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.vo.progresscategory.*; import org.dromara.progress.domain.vo.progresscategory.*;
import java.math.BigDecimal;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -174,4 +175,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
* @return 最底层的叶子节点 * @return 最底层的叶子节点
*/ */
List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIds); 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())) category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.SUB_PROJECT.getValue()))
.toList(); .toList();
if (CollUtil.isNotEmpty(subList)) { 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 -> { List<PgsProgressCategoryTopVo> subVoList = subList.stream().map(category -> {
PgsProgressCategoryTopVo vo = new PgsProgressCategoryTopVo(); PgsProgressCategoryTopVo vo = new PgsProgressCategoryTopVo();
BeanUtils.copyProperties(category, vo); 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; return vo;
}).toList(); }).toList();
topList.addAll(subVoList); topList.addAll(subVoList);
@ -235,6 +249,15 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
return vo; return vo;
}).toList(); }).toList();
topVo.setMatrixStructureList(matrixVoList); 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); topList.add(topVo);
} }
} }
@ -1200,7 +1223,8 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
Wrappers.<PgsProgressCategory>lambdaQuery() Wrappers.<PgsProgressCategory>lambdaQuery()
.and(wrapper -> { .and(wrapper -> {
for (Long topId : topIds) { 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(); .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.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq; import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.enums.PgsFinishStatusEnum; 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.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo; import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo; import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo;
@ -353,7 +354,12 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
BigDecimal completed = progressCategory.getCompleted(); BigDecimal completed = progressCategory.getCompleted();
BigDecimal completedTotal = completed.subtract(number).add(finishedNumber); BigDecimal completedTotal = completed.subtract(number).add(finishedNumber);
progressCategory.setCompleted(completedTotal); 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()); progressCategory.setStatus(PgsFinishStatusEnum.FINISH.getValue());
} }
// 判断当前是否已完成计划数量 // 判断当前是否已完成计划数量

View File

@ -4,13 +4,11 @@ import cn.dev33.satoken.annotation.SaIgnore;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R; 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.common.satoken.utils.LoginHelper;
import org.dromara.project.domain.dto.project.BusProjectQueryReq; 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.BusProjectContractorTeamListVo;
import org.dromara.project.domain.vo.project.BusProjectVo; 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.domain.vo.userprojectrelevancy.BusLoginUserProjectRelevancyVo;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusUserProjectRelevancyService; import org.dromara.project.service.IBusUserProjectRelevancyService;
@ -75,4 +73,13 @@ public class BusProjectAppController {
busProjectQueryReq.setPId(0L); busProjectQueryReq.setPId(0L);
return R.ok(projectService.queryList(busProjectQueryReq)); 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()); 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() List<PgsProgressCategory> subProgressCategoryList = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getRelevancyStructure, PgsRelevancyStructureEnum.SUB_PROJECT.getValue()) .eq(PgsProgressCategory::getRelevancyStructure, PgsRelevancyStructureEnum.SUB_PROJECT.getValue())
.in(PgsProgressCategory::getProjectId, subProjectIds) .in(PgsProgressCategory::getProjectId, subProjectIds)
@ -1035,6 +1023,19 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return matrixVo; return matrixVo;
}).toList(); }).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<FacMatrix> matrices = matrixMap.getOrDefault(subProject.getId(), new ArrayList<>());
List<FacMatrixStructureVo> matrixVos = matrices.stream().map(matrix -> { List<FacMatrixStructureVo> matrixVos = matrices.stream().map(matrix -> {
@ -1057,6 +1058,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
matrixVos.stream() matrixVos.stream()
).toList(); ).toList();
subProjectVo.setChildren(resultList); subProjectVo.setChildren(resultList);
}
return subProjectVo; return subProjectVo;
}).toList(); }).toList();