feat (farm): 生产计划

- 修改调整按钮的业务逻辑 (计划状态变更)
- 修改重启按钮的业务逻辑
- 生产计划,计划状态定时任务
This commit is contained in:
达富斌
2025-08-30 10:54:44 +08:00
parent 7464c7af87
commit 02b67bd1ae
10 changed files with 160 additions and 60 deletions

View File

@@ -88,7 +88,8 @@ public class CropFarmingCenterController {
@PutMapping("/production-plan/restart")
public CommonResult<Boolean> restartPlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) {
updateReqVO.setPlanStatus(CommonConstants.PLAN_STATUS_2);
cropFarmingCenterService.updateProductionPlan(updateReqVO);
// TODO: 2025/8/29 这里存在业务逻辑问题 ,等产品确认
cropFarmingCenterService.restartProductionPlan(updateReqVO);
return success(true);
}
@Operation(summary = "生产计划-开始按钮")
@@ -107,6 +108,13 @@ public class CropFarmingCenterController {
return success(true);
}
@Operation(summary = "生产计划-调整按钮")
@PutMapping("/production-plan/revise")
public CommonResult<Boolean> revisePlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) {
cropFarmingCenterService.reviseProductionPlan(updateReqVO);
return success(true);
}
// 农事记录
@GetMapping("/farming-record/page")

View File

@@ -44,20 +44,25 @@ public class ProductionPlanRespVO {
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate harvestStartDate;
@Schema(description = "计划开始日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate plantingStartDate;
@Schema(description = "计划结束日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate plantingEndDate;
// @Schema(description = "计划开始日期")
// @JsonFormat(pattern = "yyyy-MM-dd")
// private LocalDate plantingStartDate;
//
// @Schema(description = "计划结束日期")
// @JsonFormat(pattern = "yyyy-MM-dd")
// private LocalDate plantingEndDate;
@Schema(description = "计划执行状态")
private Integer planStatus;
@Schema(description = "计划执行状态-名称")
private String planStatusName;
@Schema(description = "计划执行进度")
private Double planProgress;
@Schema(description = "计划执行状态-子状态")
private Integer planSubStatus;
@Schema(description = "计划执行状态-子状态名称")
private String planSubStatusName;
@Schema(description = "逾期天数")
private Integer overdueDays;
@Schema(description = "租户ID")

View File

@@ -34,15 +34,16 @@ public class ProductionPlanUpdateReqVO {
@Schema(description = "采收开始日期")
private LocalDate harvestStartDate;
@Schema(description = "计划开始日期")
private LocalDate plantingStartDate;
@Schema(description = "计划结束日期")
private LocalDate plantingEndDate;
//
// @Schema(description = "计划开始日期")
// private LocalDate plantingStartDate;
//
// @Schema(description = "计划结束日期")
// private LocalDate plantingEndDate;
@Schema(description = "计划执行状态 (1:未开始;2:进行中;3:已完成;4:逾期)")
private Integer planStatus;
private Integer planSubStatus;
@Schema(description = "租户ID")

View File

@@ -13,12 +13,6 @@ public class ProductionPlanSaveReqVO {
@Schema(description = "基础id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1050")
private String id;
@Schema(description = "种植物种")
private String plantSpecies;
@Schema(description = "物种模型")
private String speciesModel;
@Schema(description = "排产开始日期")
private LocalDate productionStartDate;
@@ -28,9 +22,6 @@ public class ProductionPlanSaveReqVO {
@Schema(description = "采收开始日期")
private LocalDate harvestStartDate;
@Schema(description = "种植区域ID", example = "10011")
private String cultivationAreaId;
@Schema(description = "基地id", example = "29734")
private String baseId;
@@ -44,4 +35,10 @@ public class ProductionPlanSaveReqVO {
private String plotName;
@Schema(description = "租户id")
private String tenantId;
@Schema(description = "计划执行状态")
private Integer planStatus;
@Schema(description = "计划执行状态-子状态")
private Integer planSubStatus;
}

View File

@@ -64,6 +64,7 @@ public class ProductionPlanDO extends BaseDO {
* 执行状态
*/
private Integer planStatus;
private Integer planSubStatus;
/**
* 种植日期

View File

@@ -2,21 +2,23 @@ package cn.iocoder.yudao.module.farm.scheduled;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.farm.service.farmingrecord.FarmingRecordService;
import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO;
import cn.iocoder.yudao.module.farm.dal.dataobject.productionplan.ProductionPlanDO;
import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.*;
/**
* @description: 生产计划
* 表关系
* 模型管理: farm_model_management
* 模型管理-管理周期: farm_model_cycle
* 模型管理-管理周期-环境指标: farm_model_environment_index
* 模型管理-管理周期-病虫草害: farm_model_pest_disease_weed
* 模型管理-管理周期-气象灾害: farm_model_weather_disaster
* 模型管理-管理周期-农事事操: farm_model_farming_operation
* 模型管理-管理周期-农事操作-投入品: farm_model_farming_operation_input
* @description: 生产计划状态
* 任务周期: 每天 00:00:00
* @author: binda
* @date: 2025/8/22 17:12
*/
@@ -26,17 +28,12 @@ import org.springframework.stereotype.Component;
public class ProductionPlanJob implements JobHandler {
private final ProductionPlanService productionPlanService;
private final FarmingRecordService farmingRecordService;
public ProductionPlanJob(ProductionPlanService productionPlanService, FarmingRecordService farmingRecordService) {
public ProductionPlanJob(ProductionPlanService productionPlanService) {
this.productionPlanService = productionPlanService;
this.farmingRecordService = farmingRecordService;
}
/**
* 1. 更新任务状态
* 2. 更新地块面积
* 3. 创建农事记录
*
* @param param 参数
* @return
@@ -44,23 +41,42 @@ public class ProductionPlanJob implements JobHandler {
*/
@Override
public String execute(String param) throws Exception {
this.updatePlanStatusHandler();
this.updatePlanAreaHandler();
this.insertRecordHandler();
this.updatePlanStatus();
return "success";
}
private void updatePlanStatusHandler() {
private void updatePlanStatus() {
// 当前日期
LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
List<ProductionPlanDO> plans = productionPlanService.getProductionPlans(null);
List<ProductionPlanSaveReqVO> uList = new ArrayList<>();
for (ProductionPlanDO plan : plans) {
String id = plan.getId();
LocalDate productionStartDate = plan.getProductionStartDate();
LocalDate productionEndDate = plan.getProductionEndDate();
Integer planStatus = plan.getPlanStatus();
ProductionPlanSaveReqVO uDo = new ProductionPlanSaveReqVO();
uDo.setId(id);
// 未完成 -> 逾期未开始
if (!ObjectUtils.notEqual(planStatus,PLAN_STATUS_1)) {
if (today.isAfter(productionStartDate)) {
uDo.setPlanStatus(PLAN_STATUS_4);
uDo.setPlanSubStatus(PLAN_STATUS_5);
}
private void updatePlanAreaHandler() {
}
private void insertRecordHandler() {
// 进行中 -> 逾期未结束
if (!ObjectUtils.notEqual(planStatus,PLAN_STATUS_2)) {
if (today.isAfter(productionEndDate)) {
uDo.setPlanStatus(PLAN_STATUS_4);
uDo.setPlanSubStatus(PLAN_STATUS_6);
}
}
uList.add(uDo);
}
productionPlanService.updateBatchProductionPlan(uList);
}
}

View File

@@ -31,4 +31,8 @@ public interface CropFarmingCenterService {
Double getTotalArea(Long tenantId);
void deleteProductionPlan(String id);
void reviseProductionPlan(ProductionPlanUpdateReqVO updateReqVO);
void restartProductionPlan(ProductionPlanUpdateReqVO updateReqVO);
}

View File

@@ -24,9 +24,11 @@ import cn.iocoder.yudao.module.farm.service.plotinfo.PlotInfoService;
import cn.iocoder.yudao.module.farm.utils.StrHelperUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -34,7 +36,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.PLAN_MAP;
import static cn.iocoder.yudao.module.farm.enums.CommonConstants.*;
import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.PRODUCTION_PLAN_NOT_EXISTS;
/**
@@ -82,6 +84,7 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
obj.setProductionEndDate(reqVO.getProductionEndDate());
obj.setHarvestStartDate(reqVO.getHarvestStartDate());
obj.setPlanStatus(CommonConstants.PLAN_STATUS_1);
obj.setPlanSubStatus(CommonConstants.PLAN_STATUS_1);
obj.setPlantingDate(e.getPlantingDate());
obj.setPlantingQuantity(e.getPlantingQuantity());
@@ -222,8 +225,8 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
PageResult<ProductionPlanDO> productionPlanDOPageResult = productionPlanMapper.selectPage2(reqVO);
PageResult<ProductionPlanRespVO> resultData = BeanUtils.toBean(productionPlanDOPageResult, ProductionPlanRespVO.class);
resultData.getList().forEach(e -> {
// todo 计划进度比例
e.setPlanProgress(0.00);
// 逾期天数
// 计划状态-名称
e.setPlanStatusName(PLAN_MAP.get(e.getPlanStatus()));
// 模型
@@ -278,4 +281,63 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
throw exception(PRODUCTION_PLAN_NOT_EXISTS);
}
}
@Override
public void reviseProductionPlan(ProductionPlanUpdateReqVO updateReqVO) {
this.changePlanStatus(updateReqVO);
productionPlanMapper.updateById(BeanUtils.toBean(updateReqVO, ProductionPlanDO.class));
}
private void changePlanStatus(ProductionPlanUpdateReqVO updateObj) {
String id = updateObj.getId();
ProductionPlanDO sourceObj = productionPlanMapper.selectOne("id", id);
// 当前状态
Integer currentPlanStatus = sourceObj.getPlanStatus();
// 当前子状态
Integer currentPlanSubStatus = sourceObj.getPlanSubStatus();
// 原始-排产结束日期
LocalDate originalProductionEndDate = sourceObj.getProductionEndDate();
// 最新-排产结束日期
LocalDate newProductionEndDate = updateObj.getProductionEndDate();
// 当前日期
LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
// 日期未修改
if (originalProductionEndDate.compareTo(newProductionEndDate) == 0) {
return;
}
// 只有逾期状态 才需要状态回退
if (ObjectUtils.notEqual(currentPlanStatus,PLAN_STATUS_4)) {
return;
}
// 状态回退 逾期未开始 -> 未开始
if (ObjectUtils.notEqual(currentPlanSubStatus,PLAN_STATUS_5)) {
if (today.isBefore(newProductionEndDate) || today.isEqual(newProductionEndDate)) { // eg: 8.1 - 8.21(today) - 8.30(newProductionEndDate)
updateObj.setPlanStatus(PLAN_STATUS_1);
updateObj.setPlanSubStatus(PLAN_STATUS_1);
}
if (today.isAfter(newProductionEndDate)) { // eg: 8.1 - 8.21(newProductionEndDate) - 8.30(today)
updateObj.setPlanStatus(PLAN_STATUS_4);
updateObj.setPlanSubStatus(PLAN_STATUS_5);
}
}
// 状态还原 逾期未结束 -> 进行中
if (ObjectUtils.notEqual(currentPlanSubStatus,PLAN_STATUS_6)) {
if (today.isBefore(newProductionEndDate) || today.isEqual(newProductionEndDate)) {
updateObj.setPlanStatus(PLAN_STATUS_2);
updateObj.setPlanSubStatus(PLAN_STATUS_2);
}
if (today.isAfter(newProductionEndDate)) {
updateObj.setPlanStatus(PLAN_STATUS_4);
updateObj.setPlanSubStatus(PLAN_STATUS_6);
}
}
}
@Override
public void restartProductionPlan(ProductionPlanUpdateReqVO updateReqVO) {
}
}

View File

@@ -31,6 +31,7 @@ public interface ProductionPlanService {
* @param updateReqVO 更新信息
*/
void updateProductionPlan(@Valid ProductionPlanSaveReqVO updateReqVO);
void updateBatchProductionPlan(@Valid List<ProductionPlanSaveReqVO> updateReqVO);
/**
* 删除种植中心-生产计划-生产计划

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.farm.service.productionplan;
import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.farm.controller.admin.baseinfo.vo.BaseNamePlanRespVO;
import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanPageReqVO;
import cn.iocoder.yudao.module.farm.controller.admin.productionplan.vo.ProductionPlanSaveReqVO;
@@ -63,6 +64,11 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
productionPlanMapper.updateById(updateObj);
}
@Override
public void updateBatchProductionPlan(List<ProductionPlanSaveReqVO> updateReqVO) {
productionPlanMapper.updateBatch(BeanUtils.toBean(updateReqVO,ProductionPlanDO.class));
}
@Override
public void deleteProductionPlan(String id) {
// 校验存在
@@ -90,7 +96,9 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
@Override
public List<ProductionPlanDO> getProductionPlans(String plotId) {
return null;
LambdaQueryWrapperX<ProductionPlanDO> qw = new LambdaQueryWrapperX<>();
qw.eqIfPresent(ProductionPlanDO::getPlotId, plotId);
return productionPlanMapper.selectList(qw);
}
@Override
@@ -185,10 +193,7 @@ public class ProductionPlanServiceImpl implements ProductionPlanService {
.map(ProductionPlanDO::getPlanStatus)
.collect(Collectors.toSet());
// 存在未完成状态的计划 不可删除
if (planStatusSet.size() > 0) {
return false;
}
return false;
return planStatusSet.size() <= 0;
}
@Override